<script setup>
import { ref, computed, watch, onMounted } from "vue";
import dayjs from "../../dayjs";
import { isoWeekPlugin } from "../../dayjs-plugins";
import { useNamespace, useLocale } from "@yh-ui/hooks";
import { useComponentTheme } from "@yh-ui/theme";
import {
  calendarProps,
  calendarEmits,
  DEFAULT_CHINA_HOLIDAYS_2026
} from "./calendar";
import { YhButton } from "../../button";
dayjs.extend(isoWeekPlugin);
defineOptions({
  name: "YhCalendar"
});
const props = defineProps(calendarProps);
const emit = defineEmits(calendarEmits);
const ns = useNamespace("calendar");
const { t, locale } = useLocale();
const { themeStyle } = useComponentTheme(
  "calendar",
  computed(() => props.themeOverrides)
);
const now = dayjs();
const displayDate = ref(props.modelValue ? dayjs(props.modelValue) : now);
const currentMode = ref(props.mode || "month");
watch(
  () => props.mode,
  (val) => {
    if (val) currentMode.value = val;
  }
);
const handleModeChange = (mode) => {
  currentMode.value = mode;
  emit("update:mode", mode);
  emit("panel-change", displayDate.value.toDate(), mode);
};
const monthsList = computed(() => {
  const dateLocale = locale.value.yh?.datepicker;
  if (dateLocale?.months) {
    return [
      dateLocale.months.jan,
      dateLocale.months.feb,
      dateLocale.months.mar,
      dateLocale.months.apr,
      dateLocale.months.may,
      dateLocale.months.jun,
      dateLocale.months.jul,
      dateLocale.months.aug,
      dateLocale.months.sep,
      dateLocale.months.oct,
      dateLocale.months.nov,
      dateLocale.months.dec
    ];
  }
  return ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
});
const selectMonth = (monthIndex) => {
  displayDate.value = displayDate.value.month(monthIndex);
  handleModeChange("month");
};
const selectedDate = ref(props.modelValue ? dayjs(props.modelValue) : void 0);
const rangeStart = ref(
  props.rangeValue?.[0] ? dayjs(props.rangeValue[0]) : void 0
);
const rangeEnd = ref(
  props.rangeValue?.[1] ? dayjs(props.rangeValue[1]) : void 0
);
const hoverDate = ref(void 0);
const multipleSelected = ref(props.multipleValue?.map((d) => dayjs(d)) || []);
const mergedHolidays = computed(() => {
  if (props.showHoliday) {
    return { ...DEFAULT_CHINA_HOLIDAYS_2026, ...props.holidays };
  }
  return props.holidays;
});
const monthKeys = [
  "jan",
  "feb",
  "mar",
  "apr",
  "may",
  "jun",
  "jul",
  "aug",
  "sep",
  "oct",
  "nov",
  "dec"
];
const title = computed(() => {
  if (currentMode.value === "year") {
    const dateLocale2 = locale.value.yh?.datepicker;
    const year = displayDate.value.year();
    return dateLocale2?.year ? `${year}${dateLocale2.year}` : `${year}`;
  }
  if (props.monthHeaderFormat) {
    return displayDate.value.format(props.monthHeaderFormat);
  }
  const calendarLocale = locale.value.yh?.calendar;
  if (calendarLocale?.monthHeaderFormat) {
    return displayDate.value.format(calendarLocale.monthHeaderFormat);
  }
  const dateLocale = locale.value.yh?.datepicker;
  if (dateLocale) {
    const monthName = dateLocale.months[monthKeys[displayDate.value.month()]];
    const year = displayDate.value.year();
    if (!dateLocale.monthBeforeYear && dateLocale.year) {
      return `${year}${dateLocale.year}${monthName}`;
    }
    return dateLocale.monthBeforeYear ? `${monthName} ${year}` : `${year} ${dateLocale.year} ${monthName}`;
  }
  return displayDate.value.format("YYYY-MM");
});
const weekDays = computed(() => {
  const days = [
    { label: t("calendar.weeks.sun"), value: 0 },
    { label: t("calendar.weeks.mon"), value: 1 },
    { label: t("calendar.weeks.tue"), value: 2 },
    { label: t("calendar.weeks.wed"), value: 3 },
    { label: t("calendar.weeks.thu"), value: 4 },
    { label: t("calendar.weeks.fri"), value: 5 },
    { label: t("calendar.weeks.sat"), value: 6 }
  ];
  const start = props.firstDayOfWeek % 7;
  return [...days.slice(start), ...days.slice(0, start)];
});
const isDateDisabled = (date) => {
  if (props.disabled) return true;
  if (props.disabledDate && props.disabledDate(date.toDate())) return true;
  if (props.minDate && date.isBefore(dayjs(props.minDate), "day")) return true;
  if (props.maxDate && date.isAfter(dayjs(props.maxDate), "day")) return true;
  return false;
};
const isWeekend = (date) => {
  const day = date.day();
  return day === 0 || day === 6;
};
const isInRange = (date) => {
  if (props.selectionMode !== "range") return false;
  const start = rangeStart.value;
  const end = rangeEnd.value || hoverDate.value;
  if (!start || !end) return false;
  const min = start.isBefore(end) ? start : end;
  const max = start.isBefore(end) ? end : start;
  return date.isAfter(min, "day") && date.isBefore(max, "day");
};
const isMultipleSelected = (date) => {
  if (props.selectionMode !== "multiple") return false;
  return multipleSelected.value.some((d) => d.isSame(date, "day"));
};
const rows = computed(() => {
  const date = displayDate.value;
  const firstDay = date.startOf("month");
  const weekday = firstDay.day();
  const offset = (weekday - props.firstDayOfWeek % 7 + 7) % 7;
  let current = firstDay.subtract(offset, "day");
  const matrix = [];
  for (let i = 0; i < 6; i++) {
    const weekNumber = current.isoWeek();
    const row = [];
    for (let j = 0; j < 7; j++) {
      const dateStr = current.format("YYYY-MM-DD");
      const holidayInfo = mergedHolidays.value[dateStr];
      const isCurrentMonth = current.isSame(displayDate.value, "month");
      const isTodayDate = current.isSame(now, "day");
      const disabled = isDateDisabled(current);
      let isSelected = false;
      if (props.selectionMode === "single") {
        isSelected = selectedDate.value ? current.isSame(selectedDate.value, "day") : false;
      } else if (props.selectionMode === "multiple") {
        isSelected = isMultipleSelected(current);
      } else if (props.selectionMode === "range") {
        isSelected = rangeStart.value && current.isSame(rangeStart.value, "day") || rangeEnd.value && current.isSame(rangeEnd.value, "day") || false;
      }
      const cell = {
        date: current,
        day: current.date(),
        type: getDayType(current),
        isCurrent: isCurrentMonth,
        isToday: isTodayDate,
        isSelected,
        isDisabled: disabled,
        isWeekend: isWeekend(current),
        isHoliday: holidayInfo?.isOffDay === true,
        holidayName: holidayInfo?.name,
        isWorkday: holidayInfo?.isOffDay === false,
        isInRange: isInRange(current),
        isRangeStart: props.selectionMode === "range" && rangeStart.value?.isSame(current, "day"),
        isRangeEnd: props.selectionMode === "range" && rangeEnd.value?.isSame(current, "day"),
        dateStr
      };
      row.push(cell);
      current = current.add(1, "day");
    }
    matrix.push({ weekNumber, cells: row });
  }
  return matrix;
});
function getDayType(date) {
  if (date.isBefore(displayDate.value, "month")) return "prev-month";
  if (date.isAfter(displayDate.value, "month")) return "next-month";
  return "current-month";
}
const selectDate = (cell) => {
  if (props.readonly || cell.isDisabled) return;
  const date = cell.date;
  if (!props.showOtherMonths && cell.type !== "current-month") return;
  if (props.selectionMode === "single") {
    const oldDate = selectedDate.value;
    selectedDate.value = date;
    if (!date.isSame(displayDate.value, "month")) {
      displayDate.value = date;
    }
    emit("update:modelValue", date.toDate());
    emit("select", date.toDate(), cell);
    if (!oldDate || !date.isSame(oldDate, "day")) {
      emit("change", date.toDate());
    }
  } else if (props.selectionMode === "range") {
    if (!rangeStart.value || rangeStart.value && rangeEnd.value) {
      rangeStart.value = date;
      rangeEnd.value = void 0;
      hoverDate.value = void 0;
    } else {
      if (date.isBefore(rangeStart.value)) {
        rangeEnd.value = rangeStart.value;
        rangeStart.value = date;
      } else {
        rangeEnd.value = date;
      }
      emit("update:rangeValue", [rangeStart.value.toDate(), rangeEnd.value.toDate()]);
      emit("range-change", [rangeStart.value.toDate(), rangeEnd.value.toDate()]);
    }
    emit("select", date.toDate(), cell);
  } else if (props.selectionMode === "multiple") {
    const idx = multipleSelected.value.findIndex((d) => d.isSame(date, "day"));
    if (idx > -1) {
      multipleSelected.value.splice(idx, 1);
    } else {
      multipleSelected.value.push(date);
    }
    emit(
      "update:multipleValue",
      multipleSelected.value.map((d) => d.toDate())
    );
    emit("select", date.toDate(), cell);
  }
};
const handleCellHover = (cell) => {
  if (props.selectionMode === "range" && rangeStart.value && !rangeEnd.value) {
    hoverDate.value = cell.date;
  }
};
const moveMonth = (delta) => {
  displayDate.value = displayDate.value.add(delta, "month");
  emit("panel-change", displayDate.value.toDate(), currentMode.value);
};
const handlePrev = () => {
  if (currentMode.value === "year") {
    displayDate.value = displayDate.value.subtract(1, "year");
    emit("panel-change", displayDate.value.toDate(), "year");
  } else {
    moveMonth(-1);
  }
};
const handleNext = () => {
  if (currentMode.value === "year") {
    displayDate.value = displayDate.value.add(1, "year");
    emit("panel-change", displayDate.value.toDate(), "year");
  } else {
    moveMonth(1);
  }
};
const goToday = () => {
  displayDate.value = now;
  if (props.selectionMode === "single" && !props.readonly && !props.disabled) {
    const todayCell = rows.value.flatMap((r) => r.cells).find((c) => c.isToday);
    if (todayCell && !todayCell.isDisabled) {
      selectDate(todayCell);
    }
  }
};
watch(
  () => props.modelValue,
  (val) => {
    if (val) {
      const d = dayjs(val);
      selectedDate.value = d;
      displayDate.value = d;
    }
  }
);
watch(
  () => props.rangeValue,
  (val) => {
    if (val) {
      rangeStart.value = val[0] ? dayjs(val[0]) : void 0;
      rangeEnd.value = val[1] ? dayjs(val[1]) : void 0;
    }
  }
);
watch(
  () => props.multipleValue,
  (val) => {
    multipleSelected.value = val?.map((d) => dayjs(d)) || [];
  }
);
watch(
  () => props.selectionMode,
  () => {
    selectedDate.value = props.modelValue ? dayjs(props.modelValue) : void 0;
    rangeStart.value = props.rangeValue?.[0] ? dayjs(props.rangeValue[0]) : void 0;
    rangeEnd.value = props.rangeValue?.[1] ? dayjs(props.rangeValue[1]) : void 0;
    multipleSelected.value = props.multipleValue?.map((d) => dayjs(d)) || [];
  }
);
onMounted(() => {
  if (props.defaultValue && !props.modelValue) {
    selectedDate.value = dayjs(props.defaultValue);
    displayDate.value = dayjs(props.defaultValue);
  }
});
const getSlotData = (cell) => {
  return {
    isSelected: cell.isSelected,
    type: cell.type,
    day: cell.dateStr,
    date: cell.date.toDate(),
    isToday: cell.isToday,
    isDisabled: cell.isDisabled,
    isWeekend: cell.isWeekend,
    isHoliday: cell.isHoliday,
    holidayName: cell.holidayName,
    isWorkday: cell.isWorkday,
    isInRange: cell.isInRange,
    isRangeStart: cell.isRangeStart,
    isRangeEnd: cell.isRangeEnd
  };
};
const getCellExtraClass = (cell) => {
  if (props.cellClassName) {
    return props.cellClassName(cell.date.toDate());
  }
  return "";
};
const rootClass = computed(() => [
  ns.b(),
  ns.is("fullscreen", props.fullscreen),
  ns.is("readonly", props.readonly),
  ns.is("disabled", props.disabled),
  ns.m(props.size)
]);
defineExpose({
  /** 当前显示的日期对象 (Dayjs) */
  displayDate,
  /** 当前选中的日期对象 (Dayjs - 单选模式) */
  selectedDate,
  /** 切换月份 (delta: 1 或 -1) */
  moveMonth,
  /** 跳转到今天 */
  goToday,
  /** 手动选中日期 */
  selectDate
});
</script>

<template>
  <div :class="rootClass" :style="themeStyle">
    <!-- 顶栏 -->
    <div :class="ns.e('header')">
      <div
        :class="ns.e('title')"
        @click="currentMode === 'month' ? handleModeChange('year') : handleModeChange('month')"
        style="cursor: pointer"
      >
        <slot name="header" :date="title">{{ title }}</slot>
      </div>

      <div :class="ns.e('controls')">
        <div :class="ns.e('nav-group')">
          <yh-button class="yh-calendar__nav-btn" size="small" @click="handlePrev()">
            {{
              currentMode === "year" ? t("calendar.prevYear", "\u4E0A\u4E00\u5E74") : t("calendar.prevMonth")
            }}
          </yh-button>
          <yh-button
            class="yh-calendar__nav-btn yh-calendar__nav-btn--today"
            size="small"
            @click="goToday"
          >
            {{ t("calendar.today") }}
          </yh-button>
          <yh-button class="yh-calendar__nav-btn" size="small" @click="handleNext()">
            {{
              currentMode === "year" ? t("calendar.nextYear", "\u4E0B\u4E00\u5E74") : t("calendar.nextMonth")
            }}
          </yh-button>
        </div>
      </div>
    </div>

    <!-- 表身 -->
    <div :class="ns.e('body')">
      <table v-if="currentMode === 'month'" :class="ns.e('table')">
        <thead>
          <tr>
            <th v-if="showWeekNumber" :class="ns.e('week-number-header')">
              {{ t("calendar.week") }}
            </th>
            <th
              v-for="day in weekDays"
              :key="day.value"
              :class="[ns.e('weekday'), {
  [ns.em('weekday', 'weekend')]: highlightWeekends && (day.value === 0 || day.value === 6)
}]"
            >
              <span>{{ day.label }}</span>
            </th>
          </tr>
        </thead>
        <tbody>
          <tr v-for="(row, rowIndex) in rows" :key="rowIndex">
            <td v-if="showWeekNumber" :class="ns.e('week-number')">
              {{ row.weekNumber }}
            </td>
            <td
              v-for="(cell, cellIndex) in row.cells"
              :key="cellIndex"
              :class="[ns.e('day'), ns.is('today', cell.isToday), ns.is('selected', cell.isSelected), ns.is('disabled', cell.isDisabled), ns.is('weekend', highlightWeekends && cell.isWeekend), ns.is('holiday', cell.isHoliday), ns.is('workday', cell.isWorkday), ns.is('in-range', cell.isInRange), ns.is('range-start', cell.isRangeStart), ns.is('range-end', cell.isRangeEnd), ns.is('other-month', cell.type !== 'current-month'), ns.is('hidden', !showOtherMonths && cell.type !== 'current-month'), ns.is(cell.type, true), getCellExtraClass(cell)]"
              @click="selectDate(cell)"
              @mouseenter="handleCellHover(cell)"
            >
              <div :class="ns.e('day-inner')">
                <!-- 日期数字 -->
                <div :class="ns.e('day-value')">
                  {{ cell.day }}
                </div>

                <!-- 假期/补班标记 -->
                <div
                  v-if="showHoliday && (cell.isHoliday || cell.isWorkday)"
                  :class="[ns.e('day-badge'), cell.isHoliday ? ns.em('day-badge', 'holiday') : ns.em('day-badge', 'workday')]"
                >
                  {{ cell.isHoliday ? t("calendar.holiday") : t("calendar.workday") }}
                </div>

                <!-- 自定义内容插槽 -->
                <div :class="ns.e('day-content')">
                  <slot name="date-cell" :data="getSlotData(cell)"></slot>
                </div>
              </div>
            </td>
          </tr>
        </tbody>
      </table>

      <!-- 年视图 -->
      <div v-else :class="ns.e('months-grid')">
        <div
          v-for="(monthName, index) in monthsList"
          :key="index"
          :class="[ns.e('month-cell'), ns.is('current-month', displayDate.year() === now.year() && index === now.month())]"
          @click="selectMonth(index)"
        >
          <div :class="ns.e('month-cell-inner')">
            {{ monthName }}
          </div>
        </div>
      </div>
    </div>

    <!-- 底部插槽 -->
    <div v-if="$slots.footer" :class="ns.e('footer')">
      <slot name="footer"></slot>
    </div>
  </div>
</template>

<style>
@charset "UTF-8";
/**
 * YH-UI Sass Variables
 * 原具体的 CSS 变量输出规则 (:root, html.dark 等) 已移至 root.scss，以防止各组件样式编译时产生重复的全局变量 CSS 冗余。
 */
.yh-calendar {
  --yh-calendar-primary: var(--yh-color-primary);
  --yh-calendar-primary-light: var(--yh-color-primary-light-9);
  --yh-calendar-primary-dark: var(--yh-color-primary-dark-2);
  --yh-calendar-bg: var(--yh-bg-color);
  --yh-calendar-text: var(--yh-text-color-primary);
  --yh-calendar-cell-height: 100px;
  --yh-calendar-cell-radius: var(--yh-radius-lg);
  --yh-calendar-head-height: 80px;
  --yh-calendar-title-size: 22px;
  --yh-calendar-weekday-color: var(--yh-text-color-secondary);
  --yh-calendar-week-number-color: var(--yh-text-color-placeholder);
  --yh-calendar-holiday-color: var(--yh-color-danger);
  --yh-calendar-disabled-bg: var(--yh-fill-color-light);
  --yh-calendar-disabled-text: var(--yh-text-color-placeholder);
  background: var(--yh-calendar-bg);
  border-radius: var(--yh-radius-xl);
  box-shadow: var(--yh-shadow-lg);
  display: flex;
  flex-direction: column;
  width: 100%;
  min-width: 650px;
  overflow: hidden;
}
.yh-calendar, .yh-calendar *, .yh-calendar *::before, .yh-calendar *::after {
  box-sizing: border-box;
}
.yh-calendar__header {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 16px 32px 20px;
  background: var(--yh-bg-color);
  flex: none;
  min-height: var(--yh-calendar-head-height);
  position: relative;
  border-bottom: 1px solid var(--yh-border-color-extra-light);
  gap: 16px;
}

.yh-calendar__title {
  font-size: var(--yh-calendar-title-size);
  font-weight: 900;
  color: var(--yh-calendar-text);
  letter-spacing: 1px;
  position: relative;
}
.yh-calendar__title::after {
  content: "";
  position: absolute;
  bottom: -8px;
  left: 15%;
  right: 15%;
  height: 4px;
  background: var(--yh-calendar-primary);
  border-radius: 10px;
  opacity: 0.8;
}

.yh-calendar__controls {
  display: flex;
  gap: 12px;
  margin-top: 4px;
}

.yh-calendar__body {
  padding: 20px 24px 28px;
  flex: 1;
  background: var(--yh-bg-color-page);
  display: flex;
  flex-direction: column;
}

.yh-calendar__table {
  display: table;
  width: 100%;
  height: auto;
  border-collapse: separate;
  border-spacing: 12px 10px;
  table-layout: fixed;
  margin: 0;
}
.yh-calendar__table tr {
  display: table-row;
  background: transparent;
  border: none;
}
.yh-calendar__table th,
.yh-calendar__table td {
  display: table-cell;
  padding: 0;
  border: none;
  background: transparent;
  position: relative;
  text-align: center;
  vertical-align: middle;
}

.yh-calendar__weekday {
  height: 64px;
  color: var(--yh-calendar-weekday-color);
  font-weight: 800;
  font-size: 15px;
  position: relative;
}
.yh-calendar__weekday > span {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  position: relative;
  z-index: 1;
}
.yh-calendar__weekday::before {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--yh-bg-color-overlay);
  border-radius: 10px;
  z-index: 0;
  border: 1px solid var(--yh-border-color-extra-light);
}

.yh-calendar__day {
  --yh-day-bg: var(--yh-calendar-day-bg-color, var(--yh-calendar-day-bg, var(--yh-bg-color)));
  --yh-day-color: var(--yh-calendar-text);
  --yh-day-radius: var(--yh-calendar-cell-radius);
  --yh-day-shadow: var(--yh-shadow-sm);
  --yh-day-scale: 1;
  height: var(--yh-calendar-cell-height);
  cursor: pointer;
  position: relative;
  user-select: none;
}
.yh-calendar__day::before {
  content: "";
  position: absolute;
  inset: 0;
  background-color: var(--yh-day-bg);
  border-radius: var(--yh-day-radius);
  box-shadow: var(--yh-day-shadow);
  transition: all 0.3s cubic-bezier(0.25, 1, 0.5, 1);
  z-index: 0;
}
.yh-calendar__day:hover:not(.is-disabled):not(.is-selected):not(.is-in-range) {
  --yh-day-color: var(--yh-calendar-primary);
  --yh-day-shadow: var(--yh-shadow-lg);
  --yh-day-scale: 1.05;
  z-index: 2;
}
.yh-calendar__day.is-in-range {
  --yh-day-bg: var(--yh-calendar-primary-light);
  --yh-day-radius: 0;
  --yh-day-shadow: none;
}
.yh-calendar__day.is-in-range::before {
  margin: 0 -7px;
}
.yh-calendar__day.is-range-start {
  --yh-day-radius: var(--yh-calendar-cell-radius) 0 0 var(--yh-calendar-cell-radius);
}
.yh-calendar__day.is-range-start::before {
  margin: 0 -7px 0 0;
}
.yh-calendar__day.is-range-end {
  --yh-day-radius: 0 var(--yh-calendar-cell-radius) var(--yh-calendar-cell-radius) 0;
}
.yh-calendar__day.is-range-end::before {
  margin: 0 0 0 -7px;
}
.yh-calendar__day.is-selected {
  z-index: 5;
  --yh-day-bg: var(--yh-calendar-primary-light);
  --yh-day-color: var(--yh-calendar-primary);
  --yh-day-shadow: var(--yh-shadow-md);
}
.yh-calendar__day.is-selected::before {
  border: 2.5px solid var(--yh-calendar-primary);
}
.yh-calendar__day.is-selected .yh-calendar__day-value {
  color: var(--yh-calendar-primary);
  font-weight: 900;
  font-size: 19px;
}
.yh-calendar__day.is-selected.is-today .yh-calendar__day-value::after {
  background-color: var(--yh-calendar-primary);
}
.yh-calendar__day.is-today:not(.is-selected) .yh-calendar__day-value {
  color: var(--yh-calendar-primary);
  font-weight: 800;
}
.yh-calendar__day.is-today .yh-calendar__day-value::after {
  content: "";
  position: absolute;
  bottom: -10px;
  left: 50%;
  transform: translateX(-50%);
  width: 18px;
  height: 4px;
  background: var(--yh-calendar-primary);
  border-radius: 4px;
}

.yh-calendar__day.is-other-month {
  opacity: 0.4;
}
.yh-calendar__day.is-other-month .yh-calendar__day-value {
  color: var(--yh-text-color-secondary);
}
.yh-calendar__day.is-hidden {
  visibility: hidden;
  pointer-events: none;
}
.yh-calendar__day.is-disabled {
  cursor: not-allowed;
  opacity: 0.45;
  pointer-events: none !important;
}
.yh-calendar__day.is-disabled::before {
  background-color: var(--yh-calendar-disabled-bg);
  box-shadow: none;
}
.yh-calendar__day.is-disabled .yh-calendar__day-value {
  color: var(--yh-calendar-disabled-text);
}

.yh-calendar__day-inner {
  position: relative;
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
  padding-top: 20px;
  gap: 8px;
  z-index: 1;
  color: var(--yh-day-color);
  transform: scale(var(--yh-day-scale));
  transition: transform 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275);
}

.yh-calendar__day-value {
  font-size: 17px;
  position: relative;
  line-height: 1;
}

.yh-calendar__day-badge {
  position: static;
  order: -1;
  font-size: 12px;
  font-weight: 800;
  margin-bottom: 6px;
  transform: scale(0.85);
}
.yh-calendar__day-badge--holiday {
  color: var(--yh-calendar-holiday-color);
}

.yh-calendar__day-badge--workday {
  color: var(--yh-text-color-secondary);
}

.yh-calendar__day-content {
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

.yh-calendar.is-fullscreen {
  height: 100%;
  width: 100%;
  overflow: hidden;
}
.yh-calendar.is-fullscreen .yh-calendar__body {
  padding: 0 16px 16px;
  height: calc(100% - var(--yh-calendar-head-height) - 36px);
  overflow: hidden;
}
.yh-calendar.is-fullscreen .yh-calendar__table {
  display: flex;
  flex-direction: column;
  height: 100%;
  border-spacing: 0;
  gap: 6px;
  min-height: 0;
  overflow: hidden;
}
.yh-calendar.is-fullscreen .yh-calendar__table thead {
  flex: none;
  display: flex;
  flex-direction: column;
  width: 100%;
  margin-bottom: 2px;
}
.yh-calendar.is-fullscreen .yh-calendar__table thead tr {
  display: flex;
  width: 100%;
  gap: 10px;
}
.yh-calendar.is-fullscreen .yh-calendar__table thead th {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 0;
  overflow: hidden;
}
.yh-calendar.is-fullscreen .yh-calendar__table tbody {
  flex: 1;
  display: flex;
  flex-direction: column;
  width: 100%;
  gap: 6px;
  min-height: 0;
  overflow: hidden;
}
.yh-calendar.is-fullscreen .yh-calendar__table tbody tr {
  display: flex;
  flex-direction: row;
  width: 100%;
  flex: 1;
  gap: 10px;
  min-height: 0;
}
.yh-calendar.is-fullscreen .yh-calendar__table tbody td {
  flex: 1;
  display: flex;
  align-items: stretch;
  justify-content: center;
  min-height: 0;
  min-width: 0;
  overflow: hidden;
}
.yh-calendar.is-fullscreen .yh-calendar__day {
  height: 100%;
  min-height: 0;
  overflow: hidden;
}
.yh-calendar.is-fullscreen .yh-calendar__day-inner {
  padding-top: 10px;
}
.yh-calendar.is-fullscreen .yh-calendar__weekday {
  height: 48px;
  min-height: 48px;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

.yh-calendar--small {
  --yh-calendar-cell-height: 56px;
  min-width: 550px;
}
.yh-calendar--small .yh-calendar__header {
  height: 64px;
}

.yh-calendar--large {
  --yh-calendar-cell-height: 120px;
  min-width: 850px;
}

.yh-calendar__year-body {
  padding: 20px 24px 28px;
  flex: 1;
  background: var(--yh-bg-color-page);
  display: flex;
  flex-direction: column;
}

.yh-calendar__months-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-gap: 16px 12px;
  width: 100%;
  height: 100%;
  margin: 0;
}

.yh-calendar__month-cell {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 80px;
  background: var(--yh-bg-color);
  border-radius: var(--yh-calendar-cell-radius);
  box-shadow: var(--yh-shadow-sm);
  cursor: pointer;
  transition: all 0.3s cubic-bezier(0.25, 1, 0.5, 1);
  color: var(--yh-calendar-text);
  font-weight: bold;
  font-size: 16px;
}
.yh-calendar__month-cell:hover {
  color: var(--yh-calendar-primary);
  transform: scale(1.05);
  box-shadow: var(--yh-shadow-md);
}
.yh-calendar__month-cell.is-current-month {
  background: var(--yh-calendar-primary-light);
  color: var(--yh-calendar-primary);
  border: 1.5px solid var(--yh-calendar-primary);
}

html.dark .yh-calendar {
  --yh-calendar-bg: linear-gradient(
    180deg,
    rgba(20, 24, 33, 0.98) 0%,
    rgba(13, 16, 23, 0.98) 100%
  );
  --yh-calendar-text: var(--yh-text-color-primary, #e5eaf3);
  --yh-calendar-primary-light: rgba(64, 158, 255, 0.15);
  --yh-calendar-disabled-bg: rgba(255, 255, 255, 0.02);
  --yh-calendar-disabled-text: var(--yh-text-color-disabled, #6c6e72);
  border: 1px solid rgba(255, 255, 255, 0.06);
  box-shadow: 0 16px 40px rgba(0, 0, 0, 0.45);
}
html.dark .yh-calendar .yh-calendar__title::after {
  opacity: 0.5;
}
html.dark .yh-calendar .yh-calendar__day {
  --yh-day-bg: rgba(25, 29, 38, 0.95);
  --yh-day-color: var(--yh-text-color-regular, #cfd3dc);
  --yh-day-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.05);
}
html.dark .yh-calendar .yh-calendar__day::before {
  background-color: var(--yh-day-bg) !important;
  box-shadow: var(--yh-day-shadow) !important;
}
html.dark .yh-calendar .yh-calendar__day:hover:not(.is-disabled):not(.is-selected):not(.is-in-range) {
  --yh-day-bg: rgba(64, 158, 255, 0.1);
  --yh-day-color: var(--yh-color-primary, #409eff);
  --yh-day-shadow: inset 0 0 0 1px rgba(64, 158, 255, 0.25);
}
html.dark .yh-calendar .yh-calendar__day.is-in-range {
  --yh-day-bg: rgba(64, 158, 255, 0.08);
}
html.dark .yh-calendar .yh-calendar__day.is-in-range::before {
  background-color: var(--yh-day-bg) !important;
  box-shadow: none !important;
}
html.dark .yh-calendar .yh-calendar__day.is-selected {
  --yh-day-bg: rgba(64, 158, 255, 0.18);
  --yh-day-color: var(--yh-color-primary, #409eff);
  --yh-day-shadow: inset 0 0 0 1.5px rgba(64, 158, 255, 0.5);
}
html.dark .yh-calendar .yh-calendar__day.is-selected::before {
  border: none;
  background-color: var(--yh-day-bg) !important;
  box-shadow: var(--yh-day-shadow) !important;
}
html.dark .yh-calendar .yh-calendar__day.is-selected .yh-calendar__day-value {
  color: var(--yh-color-primary, #409eff);
}
html.dark .yh-calendar .yh-calendar__day.is-other-month {
  opacity: 0.35;
  --yh-day-bg: rgba(255, 255, 255, 0.01);
  --yh-day-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.02);
}
html.dark .yh-calendar .yh-calendar__day.is-other-month .yh-calendar__day-value {
  color: var(--yh-text-color-placeholder, #8d9095);
}
html.dark .yh-calendar .yh-calendar__day.is-disabled {
  opacity: 0.3;
}
html.dark .yh-calendar .yh-calendar__day.is-disabled::before {
  background-color: rgba(15, 18, 24, 0.95) !important;
  box-shadow: none !important;
  border: 1px solid rgba(255, 255, 255, 0.02);
}
html.dark .yh-calendar .yh-calendar__header {
  background: linear-gradient(180deg, rgba(24, 28, 38, 0.95) 0%, rgba(20, 23, 31, 0.92) 100%);
  border-bottom-color: rgba(255, 255, 255, 0.05);
}
html.dark .yh-calendar .yh-calendar__body {
  background: linear-gradient(180deg, rgba(16, 19, 26, 0.92) 0%, rgba(12, 14, 20, 0.96) 100%);
}
html.dark .yh-calendar .yh-calendar__weekday::before {
  background: rgba(25, 29, 38, 0.95) !important;
  border-color: rgba(255, 255, 255, 0.06) !important;
}
html.dark .yh-calendar .yh-calendar__weekday {
  color: var(--yh-text-color-secondary, #a3a6ad) !important;
}
html.dark .yh-calendar .yh-calendar__day.is-today:not(.is-selected) .yh-calendar__day-value::after {
  background: rgba(64, 158, 255, 0.75);
}
html.dark .yh-calendar .yh-calendar__month-cell {
  background-color: rgba(25, 29, 38, 0.95) !important;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.05) !important;
  color: var(--yh-text-color-regular, #cfd3dc) !important;
}
html.dark .yh-calendar .yh-calendar__month-cell:hover {
  background-color: rgba(64, 158, 255, 0.1) !important;
  color: var(--yh-color-primary, #409eff) !important;
  box-shadow: inset 0 0 0 1px rgba(64, 158, 255, 0.25) !important;
}
html.dark .yh-calendar .yh-calendar__month-cell.is-current-month {
  background-color: rgba(64, 158, 255, 0.18) !important;
  color: var(--yh-color-primary, #409eff) !important;
  box-shadow: inset 0 0 0 1.5px rgba(64, 158, 255, 0.5) !important;
}
</style>
