<script setup>
import { useCalendarStore } from '@/stores/CalendarStore'
import { ref, computed, watch, onUnmounted, nextTick } from 'vue'
import BaseDialog from './BaseDialog.vue'
import WeekdaySelector from './WeekdaySelector.vue'
import Numeric from './Numeric.vue'
import {
  addDaysStr,
  getMondayOfISOWeek,
  fromLocalString,
  formatDateShort,
  formatDateLong,
  DEFAULT_TZ,
} from '@/utils/date'
import { addDays, addMonths } from 'date-fns'

const props = defineProps({
  selection: { type: Object, default: () => ({ startDate: null, dayCount: 0 }) },
})

const emit = defineEmits(['clear-selection'])

const calendarStore = useCalendarStore()

const showDialog = ref(false)
const dialogMode = ref('create') // 'create' or 'edit'
const editingEventId = ref(null)
const unsavedCreateId = ref(null)
const occurrenceContext = ref(null) // { baseId, occurrenceIndex, weekday, occurrenceDate }
const title = computed({
  get() {
    if (editingEventId.value && calendarStore.events?.has(editingEventId.value)) {
      return calendarStore.events.get(editingEventId.value).title || ''
    }
    return ''
  },
  set(v) {
    if (editingEventId.value && calendarStore.events?.has(editingEventId.value)) {
      calendarStore.events.get(editingEventId.value).title = v
      calendarStore.touchEvents()
    }
  },
})
const recurrenceEnabled = ref(false)
const recurrenceInterval = ref(1) // N in "Every N weeks/months"
const recurrenceFrequency = ref('weeks') // 'weeks' | 'months'
const recurrenceWeekdays = ref([false, false, false, false, false, false, false])
const recurrenceOccurrences = ref(0) // 0 = unlimited
const colorId = ref(0)
const eventSaved = ref(false)
const titleInput = ref(null)

const uiDisplayFrequency = ref('weeks') // 'weeks' | 'months' | 'years'

// Helper to get starting weekday (Sunday-first index)
function getStartingWeekday(selectionData = null) {
  const currentSelection = selectionData || props.selection
  if (!currentSelection.start) return 0
  const date = fromLocalString(currentSelection.start, DEFAULT_TZ)
  return date.getDay() // 0=Sunday, 6=Saturday
}

const fallbackWeekdays = computed(() => {
  const startingDay = getStartingWeekday()
  const fallback = [false, false, false, false, false, false, false]
  fallback[startingDay] = true
  return fallback
})

// Maps UI frequency display (including years) to store frequency (weeks/months only)
const displayFrequency = computed({
  get() {
    return uiDisplayFrequency.value
  },
  set(val) {
    const oldFreq = uiDisplayFrequency.value
    const currentDisplayValue = displayInterval.value
    uiDisplayFrequency.value = val

    if (oldFreq === val) return

    if (oldFreq === 'years' && val === 'months') {
      recurrenceFrequency.value = 'months'
      recurrenceInterval.value = currentDisplayValue
    } else if (oldFreq === 'months' && val === 'years') {
      recurrenceFrequency.value = 'months'
      recurrenceInterval.value = currentDisplayValue * 12
    } else if (val === 'years') {
      recurrenceFrequency.value = 'months'
      recurrenceInterval.value = 12
    } else if (val === 'months') {
      recurrenceFrequency.value = 'months'
      if (oldFreq === 'weeks') {
        recurrenceInterval.value = 1
      }
    } else if (val === 'weeks') {
      recurrenceFrequency.value = 'weeks'
      recurrenceInterval.value = 1
    }
  },
})

// Computed property for display interval (handles years conversion)
const displayInterval = computed({
  get() {
    if (uiDisplayFrequency.value === 'years') {
      return recurrenceInterval.value / 12
    }
    return recurrenceInterval.value
  },
  set(val) {
    if (uiDisplayFrequency.value === 'years') {
      recurrenceInterval.value = val * 12
    } else {
      recurrenceInterval.value = val
    }
  },
})

const selectedColor = computed({
  get() {
    if (editingEventId.value && calendarStore.events?.has(editingEventId.value)) {
      return calendarStore.events.get(editingEventId.value).colorId
    }
    return colorId.value
  },
  set(v) {
    const n = parseInt(v)
    if (editingEventId.value && calendarStore.events?.has(editingEventId.value)) {
      calendarStore.events.get(editingEventId.value).colorId = n
      calendarStore.touchEvents()
    }
    colorId.value = n
  },
})

// Maps 0 (unlimited) to 'unlimited' string in store
const repeatCountBinding = computed({
  get() {
    if (editingEventId.value && calendarStore.events?.has(editingEventId.value)) {
      const rc = calendarStore.events.get(editingEventId.value).repeatCount
      return rc === 'unlimited' ? 0 : parseInt(rc, 10) || 0
    }
    return recurrenceOccurrences.value
  },
  set(v) {
    if (editingEventId.value && calendarStore.events?.has(editingEventId.value)) {
      calendarStore.events.get(editingEventId.value).repeatCount = v === 0 ? 'unlimited' : String(v)
      calendarStore.touchEvents()
    }
    recurrenceOccurrences.value = v
  },
})

const repeat = computed({
  get() {
    if (!recurrenceEnabled.value) return 'none'
    return recurrenceFrequency.value
  },
  set(val) {
    if (val === 'none') {
      recurrenceEnabled.value = false
      return
    }
    recurrenceEnabled.value = true
    if (val === 'weeks') {
      recurrenceFrequency.value = 'weeks'
      uiDisplayFrequency.value = 'weeks'
      if (recurrenceInterval.value >= 12) {
        recurrenceInterval.value = 1 // Reset to sensible weekly default
      }
    } else if (val === 'months') {
      recurrenceFrequency.value = 'months'
    }
  },
})

function buildStoreWeekdayPattern() {
  let sunFirst = [...recurrenceWeekdays.value]

  if (!sunFirst.some(Boolean)) {
    const startingDay = getStartingWeekday()
    sunFirst[startingDay] = true
  }

  return sunFirst
}

function loadWeekdayPatternFromStore(storePattern) {
  if (!Array.isArray(storePattern) || storePattern.length !== 7) return
  recurrenceWeekdays.value = [...storePattern]
}

function openCreateDialog(selectionData = null) {
  calendarStore.$history?.beginCompound()
  if (unsavedCreateId.value && !eventSaved.value) {
    if (calendarStore.events?.has(unsavedCreateId.value)) {
      calendarStore.deleteEvent(unsavedCreateId.value)
    }
    unsavedCreateId.value = null
  }
  const currentSelection = selectionData || props.selection

  let start, end
  if (currentSelection.startDate && currentSelection.dayCount) {
    start = currentSelection.startDate
    end = addDaysStr(currentSelection.startDate, currentSelection.dayCount - 1)
  } else if (currentSelection.start && currentSelection.end) {
    start = currentSelection.start
    end = currentSelection.end
  } else {
    start = null
    end = null
  }

  occurrenceContext.value = null
  dialogMode.value = 'create'
  recurrenceEnabled.value = false
  recurrenceInterval.value = 1
  recurrenceFrequency.value = 'weeks'
  uiDisplayFrequency.value = 'weeks'
  recurrenceWeekdays.value = [false, false, false, false, false, false, false]
  recurrenceOccurrences.value = 0
  colorId.value = calendarStore.selectEventColorId(start, end)
  eventSaved.value = false

  const startingDay = getStartingWeekday({ start, end })
  recurrenceWeekdays.value[startingDay] = true

  editingEventId.value = calendarStore.createEvent({
    title: '',
    startDate: start,
    endDate: end,
    colorId: colorId.value,
    repeat: repeat.value,
    repeatInterval: recurrenceInterval.value,
    repeatCount:
      recurrenceOccurrences.value === 0 ? 'for now' : String(recurrenceOccurrences.value),
    repeatWeekdays: buildStoreWeekdayPattern(),
  })
  unsavedCreateId.value = editingEventId.value

  showDialog.value = true

  nextTick(() => {
    if (titleInput.value) {
      titleInput.value.focus()
      if (title.value) {
        titleInput.value.select()
      }
    }
  })
}

function openEditDialog(payload) {
  calendarStore.$history?.beginCompound()
  if (
    dialogMode.value === 'create' &&
    unsavedCreateId.value &&
    !eventSaved.value &&
    payload &&
    unsavedCreateId.value !== payload.id
  ) {
    if (calendarStore.events?.has(unsavedCreateId.value)) {
      calendarStore.deleteEvent(unsavedCreateId.value)
    }
    unsavedCreateId.value = null
  }
  occurrenceContext.value = null
  if (!payload) return

  const baseId = payload.id
  let occurrenceIndex = payload.occurrenceIndex || 0
  let weekday = null
  let occurrenceDate = null

  const event = calendarStore.getEventById(baseId)
  if (!event) return

  if (event.isRepeating) {
    if (event.repeat === 'weeks' && occurrenceIndex >= 0) {
      const pattern = event.repeatWeekdays || []
      const baseStart = fromLocalString(event.startDate, DEFAULT_TZ)
      const baseEnd = fromLocalString(event.endDate, DEFAULT_TZ)
      if (occurrenceIndex === 0) {
        occurrenceDate = baseStart
        weekday = baseStart.getDay()
      } else {
        const interval = event.repeatInterval || 1
        const WEEK_MS = 7 * 86400000
        const baseBlockStart = getMondayOfISOWeek(baseStart)
        function isAligned(d) {
          const blk = getMondayOfISOWeek(d)
          const diff = Math.floor((blk - baseBlockStart) / WEEK_MS)
          return diff % interval === 0
        }
        let cur = addDays(baseEnd, 1)
        let found = 0
        let safety = 0
        while (found < occurrenceIndex && safety < 20000) {
          if (pattern[cur.getDay()] && isAligned(cur)) {
            found++
            if (found === occurrenceIndex) break
          }
          cur = addDays(cur, 1)
          safety++
        }
        occurrenceDate = cur
        weekday = cur.getDay()
      }
    } else if (event.repeat === 'months' && occurrenceIndex >= 0) {
      const baseDate = fromLocalString(event.startDate, DEFAULT_TZ)
      occurrenceDate = addMonths(baseDate, occurrenceIndex)
    }
  }
  dialogMode.value = 'edit'
  editingEventId.value = baseId
  loadWeekdayPatternFromStore(event.repeatWeekdays)
  repeat.value = event.repeat // triggers setter mapping into recurrence state
  if (event.repeatInterval) recurrenceInterval.value = event.repeatInterval

  // Set UI display frequency based on loaded data
  if (event.repeat === 'weeks') {
    uiDisplayFrequency.value = 'weeks'
  } else if (event.repeat === 'months') {
    if (event.repeatInterval && event.repeatInterval % 12 === 0 && event.repeatInterval >= 12) {
      uiDisplayFrequency.value = 'years'
    } else {
      uiDisplayFrequency.value = 'months'
    }
  } else {
    uiDisplayFrequency.value = 'weeks'
  }

  const rc = event.repeatCount ?? 'unlimited'
  recurrenceOccurrences.value = rc === 'unlimited' ? 0 : parseInt(rc, 10) || 0
  colorId.value = event.colorId
  eventSaved.value = false

  if (event.isRepeating) {
    if (event.repeat === 'weeks' && occurrenceIndex >= 0) {
      occurrenceContext.value = { baseId, occurrenceIndex, weekday, occurrenceDate }
    } else if (event.repeat === 'months' && occurrenceIndex > 0) {
      occurrenceContext.value = { baseId, occurrenceIndex, weekday: null, occurrenceDate }
    }
  }
  showDialog.value = true

  nextTick(() => {
    if (titleInput.value) {
      titleInput.value.focus()
      if (title.value) {
        titleInput.value.select()
      }
    }
  })
}

function closeDialog() {
  calendarStore.$history?.endCompound()
  showDialog.value = false
}

function updateEventInStore() {
  if (!editingEventId.value) return

  if (calendarStore.events?.has(editingEventId.value)) {
    const event = calendarStore.events.get(editingEventId.value)
    event.colorId = colorId.value
    event.repeat = repeat.value
    event.repeatInterval = recurrenceInterval.value
    event.repeatWeekdays = buildStoreWeekdayPattern()
    event.repeatCount =
      recurrenceOccurrences.value === 0 ? 'unlimited' : String(recurrenceOccurrences.value)
    event.isRepeating = recurrenceEnabled.value && repeat.value !== 'none'
    calendarStore.touchEvents()
  }
}

function saveEvent() {
  if (editingEventId.value) updateEventInStore()
  eventSaved.value = true
  if (dialogMode.value === 'create') {
    unsavedCreateId.value = null
  }
  if (dialogMode.value === 'create') emit('clear-selection')
  calendarStore.$history?.endCompound()
  closeDialog()
}

function deleteEventAll() {
  if (editingEventId.value) calendarStore.deleteEvent(editingEventId.value)
  calendarStore.$history?.endCompound()
  closeDialog()
}

function deleteEventOne() {
  if (occurrenceContext.value) {
    calendarStore.deleteSingleOccurrence(occurrenceContext.value)
  } else if (isRepeatingBaseEdit.value && editingEventId.value) {
    calendarStore.deleteFirstOccurrence(editingEventId.value)
  }
  calendarStore.$history?.endCompound()
  closeDialog()
}

function deleteEventFrom() {
  if (!occurrenceContext.value) return
  calendarStore.deleteFromOccurrence(occurrenceContext.value)
  calendarStore.$history?.endCompound()
  closeDialog()
}

onUnmounted(() => {
  if (unsavedCreateId.value && !eventSaved.value) {
    if (calendarStore.events?.has(unsavedCreateId.value))
      calendarStore.deleteEvent(unsavedCreateId.value)
  }
})

watch([recurrenceEnabled, recurrenceInterval, recurrenceFrequency], () => {
  if (editingEventId.value && showDialog.value) updateEventInStore()
})
watch(showDialog, (val, oldVal) => {
  if (oldVal && !val) {
    // Closed (cancel, escape, outside click) -> end compound session
    calendarStore.$history?.endCompound()
    if (dialogMode.value === 'create' && unsavedCreateId.value && !eventSaved.value) {
      if (calendarStore.events?.has(unsavedCreateId.value)) {
        calendarStore.deleteEvent(unsavedCreateId.value)
      }
    }
    editingEventId.value = null
    unsavedCreateId.value = null
  }
})
watch(
  recurrenceWeekdays,
  () => {
    if (editingEventId.value && showDialog.value && repeat.value === 'weeks') updateEventInStore()
  },
  { deep: true },
)

defineExpose({
  openCreateDialog,
  openEditDialog,
  closeDialog,
})

const isRepeatingEdit = computed(
  () => dialogMode.value === 'edit' && recurrenceEnabled.value && repeat.value !== 'none',
)
const showDeleteVariants = computed(() => isRepeatingEdit.value && occurrenceContext.value)
const isRepeatingBaseEdit = computed(() => isRepeatingEdit.value && !occurrenceContext.value)
const isLastOccurrence = computed(() => {
  if (!occurrenceContext.value || !editingEventId.value) return false
  const event = calendarStore.getEventById(editingEventId.value)
  if (!event || !event.isRepeating) return false

  if (event.repeatCount === 'unlimited' || recurrenceOccurrences.value === 0) return false

  const totalCount = parseInt(event.repeatCount, 10) || 0
  return occurrenceContext.value.occurrenceIndex === totalCount - 1
})
const formattedOccurrenceShort = computed(() => {
  if (occurrenceContext.value?.occurrenceDate) {
    return formatDateShort(occurrenceContext.value.occurrenceDate)
  }
  if (isRepeatingBaseEdit.value && editingEventId.value) {
    const ev = calendarStore.getEventById(editingEventId.value)
    if (ev?.startDate) {
      return formatDateShort(fromLocalString(ev.startDate, DEFAULT_TZ))
    }
  }
  return ''
})

const headerDateShort = computed(() => {
  if (occurrenceContext.value?.occurrenceDate) {
    return formatDateShort(occurrenceContext.value.occurrenceDate)
  }
  if (editingEventId.value) {
    const ev = calendarStore.getEventById(editingEventId.value)
    if (ev?.startDate) {
      return formatDateShort(fromLocalString(ev.startDate, DEFAULT_TZ))
    }
  }
  return ''
})

const finalOccurrenceDate = computed(() => {
  if (!recurrenceEnabled.value) return null
  const count = recurrenceOccurrences.value
  if (!count || count < 1) return null
  const base = editingEventId.value ? calendarStore.getEventById(editingEventId.value) : null
  if (!base) return null
  const start = fromLocalString(base.startDate, DEFAULT_TZ)
  if (uiDisplayFrequency.value === 'weeks') {
    // iterate days until we count 'count-1' additional occurrences (first is base if selected weekday)
    const pattern = buildStoreWeekdayPattern() // Sun..Sat
    // Build Monday-first pattern again for selection clarity
    const monFirst = recurrenceWeekdays.value
    const selectedCount = monFirst.some(Boolean)
    if (!selectedCount) return null
    let occs = 0
    // Determine if the start day counts
    const startWeekdaySun = start.getDay()
    // Convert to Monday-first index
    // We'll just check store pattern
    if (pattern[startWeekdaySun]) occs = 1
    let cursor = new Date(start)
    while (occs < count && occs < 10000) {
      cursor = addDays(cursor, 1)
      if (pattern[cursor.getDay()]) occs++
    }
    if (occs === count) return cursor
    return null
  } else if (uiDisplayFrequency.value === 'months') {
    const monthsToAdd = displayInterval.value * (count - 1)
    return addMonths(start, monthsToAdd)
  } else if (uiDisplayFrequency.value === 'years') {
    const yearsToAdd = displayInterval.value * (count - 1)
    const d = new Date(start)
    d.setFullYear(d.getFullYear() + yearsToAdd)
    return d
  }
})

const formattedFinalOccurrence = computed(() => {
  const d = finalOccurrenceDate.value
  if (!d) return ''
  const now = new Date()
  const includeYear =
    d.getFullYear() !== now.getFullYear() ||
    d.getTime() - now.getTime() >= 1000 * 60 * 60 * 24 * 365
  return formatDateLong(d, includeYear)
})

const recurrenceSummary = computed(() => {
  if (!recurrenceEnabled.value) return 'Does not recur'
  if (uiDisplayFrequency.value === 'weeks') {
    return displayInterval.value === 1 ? 'Weekly' : `Every ${displayInterval.value} weeks`
  } else if (uiDisplayFrequency.value === 'years') {
    return displayInterval.value === 1 ? 'Annually' : `Every ${displayInterval.value} years`
  }
  if (recurrenceFrequency.value === 'months' && recurrenceInterval.value % 12 === 0) {
    const years = recurrenceInterval.value / 12
    return years === 1 ? 'Annually' : `Every ${years} years`
  }
  return displayInterval.value === 1 ? 'Monthly' : `Every ${displayInterval.value} months`
})
</script>

<template>
  <BaseDialog v-model="showDialog" @submit="saveEvent">
    <template #title>
      {{ dialogMode === 'create' ? 'Create Event' : 'Edit Event'
      }}<template v-if="headerDateShort"> · {{ headerDateShort }}</template>
    </template>
    <label class="ec-field">
      <input type="text" v-model="title" autocomplete="off" ref="titleInput" />
    </label>
    <div class="ec-color-swatches">
      <label v-for="i in 8" :key="i - 1" class="swatch-label">
        <input
          class="swatch"
          :class="'event-color-' + (i - 1)"
          type="radio"
          name="colorId"
          :value="i - 1"
          v-model="selectedColor"
        />
      </label>
    </div>
    <div class="recurrence-block">
      <div class="recurrence-header">
        <label class="switch">
          <input type="checkbox" v-model="recurrenceEnabled" />
          <span>Repeat</span>
        </label>
        <span class="recurrence-summary" v-if="recurrenceEnabled">
          {{ recurrenceSummary }}
          <template v-if="recurrenceOccurrences > 0">
            until {{ formattedFinalOccurrence }}</template
          >
        </span>
        <span class="recurrence-summary muted" v-else>Does not recur</span>
      </div>
      <div v-if="recurrenceEnabled" class="recurrence-form">
        <div class="line compact">
          <Numeric
            v-model="displayInterval"
            :prefix-values="[{ value: 1, display: 'Every' }]"
            :min="2"
            number-prefix="Every "
            aria-label="Interval"
          />
          <select v-model="displayFrequency" class="freq-select">
            <option value="weeks">{{ displayInterval === 1 ? 'week' : 'weeks' }}</option>
            <option value="months">{{ displayInterval === 1 ? 'month' : 'months' }}</option>
            <option value="years">{{ displayInterval === 1 ? 'year' : 'years' }}</option>
          </select>
          <Numeric
            class="occ-stepper"
            v-model="repeatCountBinding"
            :min="2"
            :prefix-values="[{ value: 0, display: '∞' }]"
            number-postfix=" times"
            aria-label="Occurrences (0 = no end)"
            extra-class="occ"
          />
        </div>
        <div v-if="uiDisplayFrequency === 'weeks'" @click.stop>
          <WeekdaySelector
            v-model="recurrenceWeekdays"
            :fallback="fallbackWeekdays"
            :first-day="calendarStore.config.first_day"
          />
        </div>
      </div>
    </div>
    <template #footer>
      <template v-if="dialogMode === 'create'">
        <button type="button" class="ec-btn delete-btn" @click="deleteEventAll">Delete</button>
        <button type="submit" class="ec-btn save-btn">Save</button>
      </template>
      <template v-else>
        <template v-if="showDeleteVariants">
          <div class="ec-delete-group">
            <button type="button" class="ec-btn delete-btn" @click="deleteEventOne">
              Delete {{ formattedOccurrenceShort }}
            </button>
            <button
              v-if="!isLastOccurrence"
              type="button"
              class="ec-btn delete-btn"
              @click="deleteEventFrom"
            >
              Rest
            </button>
            <button type="button" class="ec-btn delete-btn" @click="deleteEventAll">All</button>
          </div>
        </template>
        <template v-else-if="isRepeatingBaseEdit">
          <div class="ec-delete-group">
            <button type="button" class="ec-btn delete-btn" @click="deleteEventOne">
              Delete {{ formattedOccurrenceShort }}
            </button>
            <button type="button" class="ec-btn delete-btn" @click="deleteEventAll">All</button>
          </div>
        </template>
        <template v-else>
          <button type="button" class="ec-btn delete-btn" @click="deleteEventAll">Delete</button>
        </template>
        <button type="button" class="ec-btn close-btn" @click="closeDialog">Close</button>
      </template>
    </template>
  </BaseDialog>
</template>

<style scoped>
.ec-field {
  display: grid;
  gap: 0.25rem;
}

.ec-field > span {
  font-size: 0.85em;
  color: var(--muted);
}

.ec-field input[type='text'],
.ec-field input[type='time'],
.ec-field input[type='number'],
.ec-field select {
  border: 1px solid var(--muted);
  border-radius: 0.4rem;
  padding: 0.5rem 0.6rem;
  width: 100%;
  background: transparent;
  color: var(--ink);
}

.ec-color-swatches {
  display: grid;
  grid-template-columns: repeat(8, 1fr);
}

.ec-color-swatches .swatch {
  display: grid;
  place-items: center;
  border-radius: 0.4em;
  padding: 0.25em;
  outline: 0.125em solid transparent;
  outline-offset: 0.125em;
  cursor: pointer;
  appearance: none;
  width: 3em;
  height: 1em;
}

.ec-color-swatches .swatch:checked {
  outline-color: var(--ink);
}

.ec-footer {
  display: flex;
  justify-content: space-between;
  gap: 0.75em;
}

.ec-btn {
  border: 0.0625em solid var(--muted);
  background: transparent;
  color: var(--ink);
  padding: 0.5em 0.8em;
  border-radius: 0.4em;
  cursor: pointer;
  transition: all 0.2s ease;
}

.ec-btn:hover {
  background: var(--muted);
}

.ec-btn.save-btn {
  background: var(--today);
  color: #000;
  border-color: transparent;
  font-weight: 500;
}

.ec-btn.save-btn:hover {
  background: color-mix(in srgb, var(--today) 90%, black);
}

.ec-btn.close-btn {
  background: var(--panel);
  border-color: var(--muted);
  font-weight: 500;
}

.ec-btn.close-btn:hover {
  background: var(--muted);
}

.ec-btn.delete-btn {
  background: hsl(0, 70%, 50%);
  color: #fff;
  border-color: transparent;
  font-weight: 500;
}

.ec-btn.delete-btn:hover {
  background: hsl(0, 70%, 45%);
}

.ec-weekday-selector {
  display: grid;
  gap: 0.5em;
}

.ec-field-label {
  font-size: 0.85em;
  color: var(--muted);
}

.ec-weekdays {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 0.25em;
}

.ec-weekday-label {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.25rem;
  cursor: pointer;
  padding: 0.5rem 0.25rem;
  border-radius: 0.3rem;
  transition: background-color 0.2s ease;
}

.ec-weekday-label:hover {
  background: var(--muted);
}

.ec-weekday-checkbox {
  margin: 0;
}

.ec-weekday-text {
  font-size: 0.8em;
  font-weight: 500;
  text-align: center;
}

/* New recurrence block */
.recurrence-block {
  display: grid;
  gap: 0.6em;
}
.recurrence-header {
  display: flex;
  align-items: center;
  gap: 0.75em;
}
.recurrence-header .recurrence-summary {
  font-size: 0.75rem;
  color: var(--ink);
  opacity: 0.85;
}
.recurrence-header .recurrence-summary.muted {
  opacity: 0.5;
}
.switch {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  cursor: pointer;
  font-size: 0.85rem;
}
.switch input {
  width: 1rem;
  height: 1rem;
}
.recurrence-form {
  display: grid;
  gap: 0.6em;
  padding: 0.6em 0.75em 0.75em;
  border: 0.0625em solid var(--muted);
  border-radius: 0.5em;
  background: color-mix(in srgb, var(--muted) 15%, transparent);
}
.line.compact {
  display: flex;
  align-items: center;
  gap: 0.5em;
  flex-wrap: wrap;
  font-size: 0.75em;
}
.freq-select {
  padding: 0.4rem 0.55rem;
  font-size: 0.75rem;
  border: 1px solid var(--input-border);
  background: var(--panel-alt);
  color: var(--ink);
  border-radius: 0.45rem;
  transition:
    border-color 0.18s ease,
    background-color 0.18s ease;
}
.freq-select:focus {
  outline: none;
  border-color: var(--input-focus);
  background: var(--panel-accent);
  color: var(--ink);
  box-shadow:
    0 0 0 1px var(--input-focus),
    0 0 0 4px rgba(37, 99, 235, 0.15);
}
.interval-input,
.occ-input {
  display: none;
}
.ec-field input[type='text'] {
  border: 1px solid var(--input-border);
  background: var(--panel-alt);
  border-radius: 0.45rem;
  padding: 0.4rem 0.5rem;
  transition:
    border-color 0.18s ease,
    background-color 0.18s ease,
    box-shadow 0.18s ease;
}
.ec-field input[type='text']:focus {
  outline: none;
  border-color: var(--input-focus);
  background: var(--panel-accent);
  box-shadow:
    0 0 0 1px var(--input-focus),
    0 0 0 4px rgba(37, 99, 235, 0.15);
}
.mini-stepper {
  display: inline-flex;
  align-items: center;
  background: var(--panel-alt);
  border: 1px solid var(--input-border);
  border-radius: 0.5rem;
  overflow: hidden;
  font-size: 0.7rem;
  height: 1.9rem;
}
.mini-stepper .step {
  background: transparent;
  border: none;
  color: var(--ink);
  padding: 0 0.55rem;
  cursor: pointer;
  font-size: 0.9rem;
  line-height: 1;
  font-weight: 600;
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  transition:
    background-color 0.15s ease,
    color 0.15s ease;
}
.mini-stepper .step:hover:not(:disabled) {
  background: var(--pill-hover-bg);
}
.mini-stepper .step:disabled {
  opacity: 0.35;
  cursor: default;
}
.mini-stepper .value {
  min-width: 1.6rem;
  text-align: center;
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  letter-spacing: 0.02em;
}
.mini-stepper:focus-within {
  border-color: var(--input-focus);
  box-shadow:
    0 0 0 1px var(--input-focus),
    0 0 0 4px rgba(37, 99, 235, 0.15);
}
.mini-stepper.occ .value {
  min-width: 2rem;
}
.occ-stepper.mini-stepper.occ .value {
  min-width: 2rem;
}
.mini-stepper .step:focus-visible {
  outline: 2px solid var(--input-focus);
  outline-offset: -2px;
}
.hint {
  font-size: 0.65rem;
  opacity: 0.65;
}

/* Recurrence UI */
.ec-recurrence-section {
  display: grid;
  gap: 0.4rem;
}
.ec-recurrence-toggle {
  display: flex;
  justify-content: space-between;
  align-items: center;
  width: 100%;
  padding: 0.6rem 0.8rem;
  border: 1px solid var(--muted);
  background: var(--panel);
  border-radius: 0.4rem;
  cursor: pointer;
  font-size: 0.9rem;
  text-align: left;
  transition: background-color 0.15s ease;
}
.ec-recurrence-toggle:hover {
  background: var(--muted);
}
.ec-recurrence-toggle .toggle-icon {
  transition: transform 0.2s ease;
  font-size: 0.7rem;
  color: var(--muted);
}
.ec-recurrence-toggle .toggle-icon.open {
  transform: rotate(180deg);
}
.ec-recurrence-panel {
  display: grid;
  gap: 0.6rem;
  padding: 0.6rem;
  border: 1px solid var(--muted);
  border-radius: 0.4rem;
  background: color-mix(in srgb, var(--muted) 20%, transparent);
}

/* Repeat modes */
.ec-repeat-modes {
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem;
}
.ec-repeat-modes .mode-btn {
  flex: 1 1 auto;
  padding: 0.4rem 0.6rem;
  border: 1px solid var(--muted);
  background: var(--panel);
  border-radius: 0.4rem;
  cursor: pointer;
  font-size: 0.75rem;
  line-height: 1.1;
  white-space: nowrap;
  transition:
    background-color 0.15s ease,
    color 0.15s ease,
    border-color 0.15s ease;
}
.ec-repeat-modes .mode-btn.active {
  background: var(--today);
  color: #000;
  border-color: var(--today);
  font-weight: 600;
}
.ec-repeat-modes .mode-btn:hover {
  background: var(--muted);
}

.ec-occurrences-field {
  margin-top: 0.2rem;
}
.ec-occurrences-field .ec-field input[type='number'] {
  max-width: 6rem;
}
</style>
