/* =========================================================================
   RaiPlan — оформление интерфейса.

   Палитра задана заказчиком: жёлтый #FED500 — акцент и отдел «Голос»,
   тёмный #1C1B24 — шапка и текст, #3D4047 — вторичные элементы,
   зелёный #36C98F — смены и отдел «Чат».

   Цвет отдела — не украшение: по нему видно, чей график на экране. Чат
   залит зелёным, голос — жёлтым, поэтому перепутать отделы нельзя.
   ========================================================================= */

:root {
    --yellow: #FED500;
    --yellow-dark: #E5C000;
    --dark: #1C1B24;
    --dark-2: #3D4047;
    --green: #36C98F;
    --green-dark: #2BA876;

    --bg: #F7F8FA;
    --white: #FFFFFF;
    --border: #E7E9ED;
    --muted: #8C929D;
    --text: #252733;

    /* Цвет пожелания. Взят того же оттенка, что зелёный цвет смены
       (`#36C98F`): совпадают насыщенность 0.576 и светлота 0.500, отличается
       только тон. Заказчик просил именно так — пожелание и смена должны весить
       одинаково, чтобы одно не перекрикивало другое. */
    --wish: #9836C9;
    --wish-dark: #542080;

    /* =====================================================================
       ПАЛИТРА КЛЕТОК КАЛЕНДАРЯ — с референса заказчика («Референс UI»).
       =====================================================================

       Клетка — светлая карточка: заливка, рамка на тон темнее и тёмный текст
       того же тона. Так на референсе выглядят все четыре вида клеток:

         | вид                | заливка | рамка   | текст   |
         |--------------------|---------|---------|---------|
         | обычная смена      | #DDF3E8 | #B9E4D0 | #176B4B |
         | отпуск             | #E5F0FF | #C9DDF8 | #245A9B |
         | больничный         | #FCE8E8 | #F2CACA | #A83D43 |
         | обучение           | #EEE9FC | #D9CEF4 | #6545A5 |

       Пожелание заливку НЕ меняет — так прямо написано в референсе: «пожелание
       сотрудника не должно менять основной цвет ячейки. Оно обозначается
       дополнительной вертикальной полосой слева». Полоса бывает двух цветов:

         выполнено         #239B70  (зелёная)
         не выполнено      #8B9AA8  (серо-голубая)

       `--wish` (фиолетовый) остаётся цветом пожелания в окнах и списках —
       тумблер «Пожелание», список пожеланий, мини-календарь сотрудника: там
       клеток смены нет, полосе негде стоять, и нужен свой акцент.
       ===================================================================== */
    --shift-fill: #DDF3E8;
    --shift-line: #B9E4D0;
    --shift-text: #176B4B;

    --vacation-fill: #E5F0FF;
    --vacation-line: #C9DDF8;
    --vacation-text: #245A9B;

    --sick-fill: #FCE8E8;
    --sick-line: #F2CACA;
    --sick-text: #A83D43;

    --study-fill: #EEE9FC;
    --study-line: #D9CEF4;
    --study-text: #6545A5;

    /* Полоса пожелания слева: «учтено» и «не учтено». */
    --wish-ok: #239B70;
    --wish-no: #8B9AA8;

    /* Акцент интерфейса. Один на все отделы — жёлтый: отдел теперь задаётся
       адресом страницы, а не кнопкой, и цвет за ним не закреплён. */
    --accent: #FED500;
    --accent-ink: #1C1B24;

    /* Размеры клеток. Вид один — компактный: заказчик просил «уберём кнопку
       обычного масштаба и в целом обычный масштаб, оставляем компактный на
       постоянку». Поэтому размеры живут здесь, а второго набора нет.

       Размер подобран «по 25-е число» — так просил заказчик: «Давай сделаем
       уменьшение вида все таки по 25 число, уж слишком все мелко». На экран
       1920 px помещаются дни с 1 по 25-е (180 + 25 × 66 = 1830 px), остаток
       месяца домётывается колесом — ровно то, как устроен WFM, на который
       заказчик ссылался.

       Высота — предел, при котором 23 человека влезают в экран 1080 px:
       277 + 23 × 33 + 31 = 1067, где 31 — уменьшенный нижний отступ страницы
       (см. `.page:has(.calendar.compact)`). Если поднять строку, снизу
       появится вертикальная прокрутка. */
    --employee-width: 180px;
    --day-width: 66px;
    --row-height: 33px;
}

/* =========================
   COMPACT VIEW
   ========================= */

/* Компактный вид: тот же календарь, но клетки узкие. Отдельные правила, а не
   один переключатель шрифта: ужимать приходится не всё подряд, а только то,
   что занимает место. Цвета, границы и порядок остаются прежними — заказчик
   просил уменьшить, а не переделать. */

/* Код сотрудника: 14 → 12 px. Мельче нельзя — по нему человека и находят. */
.calendar.compact .employee-name { font-size: 12px; }

.calendar.compact .employee-info {
    min-width: 0;
    display: flex;
    flex-direction: column;
    justify-content: center;
    height: 100%;
}

/* Столбец сужен до 180 px, строка — до 32 px, поэтому итоги за месяц
   сокращаются до «смен 12 · 168 ч» (см. `summaryFor` в render.js): полная
   строка переносилась бы на три строки и вылезла из клетки. Обрезка
   многоточием, а не перенос: «Оператор · см…» бесполезен, а перенос налез бы
   на соседнюю строку. */
.calendar.compact .employee-role {
    font-size: 10px;
    margin-top: 1px;
    line-height: 1.2;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.calendar.compact .employee-cell { padding: 0 8px; gap: 6px; }

/* Нижний отступ страницы в компактном виде на 3 px меньше: при строке 33 px и
   23 сотрудниках таблица выходила на 1 px за экран 1080, и появлялась полоса
   прокрутки ради одного пикселя. Отступ — единственное, что тут можно убрать
   без потерь: он визуальный, а не содержательный. */
.page:has(.calendar.compact) { padding-bottom: 31px; }

/* Время смены в компактном виде — одна цифра, час начала. В обычном виде та
   же смена читается строкой «07:00 — 16:00»; конец смены в компактном виде
   остаётся в подсказке клетки.
   Прежний вид ставил начало и конец друг под другом в две строки, и заказчик
   сказал прямо: «в глазах рябит». Одна цифра вместо двух строк — меньше
   разнобоя по высоте и по ширине, и клетка читается с одного взгляда. */
.calendar.compact .shift-hour {
    display: block;
    font-variant-numeric: tabular-nums;
    line-height: 1.1;
}

.calendar.compact .shift {
    padding: 1px 2px;
    border-radius: 5px;
    font-size: 13px;
    text-align: center;
    justify-content: center;
}

/* Клетка 66 px — втрое шире прежних 48, и padding можно вернуть: 4 px с каждой
   стороны больше не съедают половину ширины. */
.calendar.compact .day-cell { padding: 2px 3px; }

/* Буква отсутствия: 15 → 13 px. Одной букве в клетке 66 px просторно, и это
   первое, что читает глаз, — мельчить её незачем. */
.calendar.compact .absence { font-size: 13px; border-radius: 6px; }

/* Дата в шапке: 13 → 12 px, день недели — 10 px.
   Шапка с датами живёт в СВОЁМ узле (`#calendarHead`), а не внутри `.calendar`:
   её нельзя держать в области горизонтальной прокрутки, иначе закрепление по
   вертикали перестаёт работать. Поэтому селектор идёт по `.calendar-head`, а не
   по `.calendar` — с одним лишь `.calendar.compact` даты остались бы крупными и
   разъехались с клетками.
   Дата здесь только числом («4», а не «04.11.2026»): полная запись шириной
   68 px не влезала в клетку 48 px и налезала на соседние подписи; в 66 px она
   поместилась бы впритык, но год и месяц дублировали бы заголовок над
   календарём. */
.calendar.compact .day-header,
.calendar-head.compact .day-header { font-size: 12px; }

.calendar.compact .day-header .day-weekday,
.calendar-head.compact .day-header .day-weekday { font-size: 10px; }

/* Шапка столбца сотрудников: подпись «Код сотрудника» в 180 px не помещается
   целиком, поэтому она сокращается до «Код». Урезать её многоточием хуже:
   «Код сотр…» читается как обрывок, а не как сокращение. */
.calendar-head.compact .employee-header { padding: 0 8px; font-size: 12px; }

* {
    box-sizing: border-box;
}

html, body {
    margin: 0;
    padding: 0;
}

body {
    font-family: Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif;
    background: var(--bg);
    color: var(--text);
    -webkit-font-smoothing: antialiased;
}

button {
    font: inherit;
    color: inherit;
}

.hidden {
    display: none !important;
}

/* Акцент один — жёлтый, как у голоса: заказчик просил оставить палитру кнопок
   прежней, а цвет больше не закреплён за отделом (отделов может быть сколько
   угодно). Пока отдел открыт по адресу, переключать цвет нечем и незачем. */
body {
    --accent: #FED500;
    --accent-ink: #1C1B24;
}

/* =========================
   TOP NAVIGATION
========================= */

.topbar {
    height: 62px;
    background: var(--dark);
    color: #fff;
    display: flex;
    align-items: center;
    gap: 26px;
    padding: 0 34px;
    box-shadow: 0 1px 0 rgba(0, 0, 0, .15);
    position: sticky;
    top: 0;
    z-index: 40;
}

.brand {
    display: flex;
    align-items: center;
    gap: 10px;
    padding-right: 22px;
    border-right: 1px solid #34333D;
    /* Название — ссылка на выбор отдела: подчёркивание и синий цвет ссылки
       здесь ни к чему, это часть шапки. */
    color: inherit;
    text-decoration: none;
    cursor: pointer;
}

.brand-mark {
    width: 30px;
    height: 30px;
    border-radius: 8px;
    background: var(--yellow);
    color: var(--dark);
    display: grid;
    place-items: center;
    font-weight: 800;
    font-size: 17px;
}

.brand-name {
    font-size: 15px;
    font-weight: 600;
    letter-spacing: .2px;
}

.topbar-left {
    display: flex;
    align-items: stretch;
    height: 100%;
    gap: 4px;
}

.nav-item {
    position: relative;
    height: 100%;
    padding: 0 20px;
    display: flex;
    align-items: center;
    background: transparent;
    border: 0;
    color: #C9CBD1;
    font-size: 15px;
    font-weight: 500;
    cursor: pointer;
    text-decoration: none;
    transition: color .2s;
}

.nav-item:hover {
    color: #fff;
}

.nav-item.active {
    color: var(--yellow);
    font-weight: 600;
}

.nav-item.active::after {
    content: "";
    position: absolute;
    left: 16px;
    right: 16px;
    bottom: 0;
    height: 3px;
    border-radius: 3px 3px 0 0;
    background: var(--yellow);
}

.topbar-right {
    margin-left: auto;
    display: flex;
    align-items: center;
    gap: 16px;
}

.api-state {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 13px;
    color: #C9CBD1;
}

.api-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--muted);
}

.api-state.ok .api-dot { background: var(--green); }
.api-state.bad .api-dot { background: #F2607A; }
.api-state.bad { color: #F2A0AE; }

/* =========================
   PAGE
========================= */

.page {
    padding: 22px 34px 34px;
}

/* =========================
   TOOLBAR
========================= */

.toolbar {
    min-height: 68px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 18px;
    flex-wrap: wrap;
    margin-bottom: 6px;
}

.toolbar-left {
    display: flex;
    align-items: center;
    gap: 14px;
    flex-wrap: wrap;
}

/* =========================
   DAY VIEW
========================= */

/* Один день крупно. Сетка: слева столбец сотрудников шириной как в месяце,
   справа дорожка часов. Показываются только часы, в которые есть смены: с 00
   до 05 менеджеру смотреть нечего, поэтому окно начинается с самой ранней
   смены, а в шапке каждый получас подписан, как на линейке. */
.day-view {
    margin-top: 8px;
}

.day-head {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 10px;
}

.day-head-text {
    margin-left: 6px;
}

.day-head h2 {
    margin: 0;
    font-size: 20px;
    color: var(--dark);
}

.day-subtitle {
    margin: 2px 0 0;
    font-size: 13px;
    color: #5C636F;
}

.day-scroll {
    overflow: auto;
    border: 1px solid var(--border);
    border-radius: 12px;
    background: var(--white);
    max-height: calc(100vh - 220px);
}

.day-grid {
    min-width: 180px;
}

/* Строка: сотрудник слева, дорожка справа. Высота подобрана под полосу смены
   в одну строку — под именем больше ничего не пишется, и строка не растёт. */
.day-row {
    display: grid;
    grid-template-columns: var(--employee-width) 1fr;
    border-bottom: 1px solid #F1F3F6;
}

.day-row:last-child {
    border-bottom: 0;
}

.day-row.has-shift {
    background: #FCFEFD;
}

.day-emp {
    position: sticky;
    left: 0;
    z-index: 3;
    display: flex;
    align-items: center;
    padding: 3px 10px;
    background: var(--white);
    border-right: 1px solid var(--border);
    overflow: hidden;
}

.day-row.has-shift .day-emp {
    background: #FCFEFD;
}

.day-emp-name {
    font-size: 12.5px;
    font-weight: 600;
    color: var(--dark);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.day-track {
    position: relative;
    display: grid;
    grid-template-columns: repeat(48, minmax(26px, 1fr));
    grid-auto-rows: 30px;
    align-items: stretch;
}

.day-slot {
    border-left: 1px solid #F6F7F9;
}

.day-slot-hour {
    border-left-color: #E7E9ED;
}

/* Шапка с часами: липнет к верху прокрутки, чтобы время было видно всегда.
   Подписаны все получасы: час — жирным, минуты — серым, как деления линейки. */
.day-head-row {
    position: sticky;
    top: 0;
    z-index: 5;
    background: #FAFBFC;
    border-bottom: 1px solid var(--border);
}

.day-axis {
    background: #FAFBFC;
}

.day-hour {
    display: flex;
    align-items: center;
    padding-left: 4px;
    font-size: 10.5px;
    color: var(--muted);
    border-left: 1px solid #EDEFF2;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.day-hour-main {
    font-size: 11.5px;
    font-weight: 700;
    color: var(--dark-2);
}

.day-corner {
    justify-content: center;
    background: #FAFBFC;
    font-size: 11.5px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--muted);
}

/* Линии получасов поверх полос: полоса закрашена и закрывала бы сетку, а по
   ней видно, где четверть часа. Щелчки слой не перехватывает. */
.day-lines {
    position: absolute;
    inset: 0;
    z-index: 3;
    display: grid;
    pointer-events: none;
}

.day-line {
    border-left: 1px solid rgba(28, 27, 36, .10);
}

.day-line-hour {
    border-left-color: rgba(28, 27, 36, .22);
}

/* Полоса смены: зелёная заливка, как у клетки месяца. Внутри — отрезки:
   перерывы и обеды залиты жёлтым (тот же цвет, что у выходных), работа
   прозрачна и показывает заливку смены. */
.day-block {
    position: absolute;
    top: 4px;
    z-index: 2;
    height: 22px;
    display: flex;
    align-items: stretch;
    border-radius: 7px;
    overflow: hidden;
    box-shadow: 0 1px 2px rgba(28, 27, 36, .08);
}

.day-block.day-work {
    background: var(--shift-fill);
    border: 1px solid var(--shift-line);
    color: var(--shift-text);
}

.day-block.day-absence {
    height: 20px;
    align-items: center;
    justify-content: center;
    background: #F4F5F7;
    color: var(--dark-2);
    font-size: 11.5px;
    font-weight: 500;
}

.day-block.day-vacation {
    background: var(--vacation-fill);
    border: 1px solid var(--vacation-line);
    color: var(--vacation-text);
}

.day-block.day-sick {
    background: var(--sick-fill);
    border: 1px solid var(--sick-line);
    color: var(--sick-text);
}

.day-block.day-study {
    background: var(--study-fill);
    border: 1px solid var(--study-line);
    color: var(--study-text);
}

.day-part {
    align-self: stretch;
    min-width: 0;
}

.day-part-work {
    background: transparent;
}

/* Перерывы (10 минут) и обеды (30 минут) — одним жёлтым, как выходные в
   месяце. Заказчик просил не делать обед темнее: это одна и та же пауза. */
.day-part-break,
.day-part-lunch {
    background: #FFE99A;
}

.day-block-label {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    z-index: 1;
    max-width: calc(100% - 8px);
    padding: 0 6px;
    border-radius: 5px;
    background: rgba(255, 255, 255, .82);
    font-size: 10.5px;
    font-weight: 600;
    color: var(--shift-text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    pointer-events: none;
}

.day-empty {
    padding: 30px 20px;
    text-align: center;
    color: var(--muted);
    font-size: 14px;
}

/* Подвал дня: сводка по месяцу и легенда. Стоят под расписанием, потому что
   сверху они отодвигали бы сам день. */
.day-footer {
    margin-top: 10px;
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.day-summary {
    font-size: 13px;
    color: var(--dark-2);
}

/* Легенда в подвале: та же, но без «прилипания» и отступа снизу — она уже
   внизу страницы. Настраивается по id: общий блок `.legend` остаётся для
   месячного вида. */
#dayLegend {
    position: static;
    margin: 0;
    background: transparent;
    border: 0;
    padding: 0;
}

/* =========================
   EMPLOYEES
========================= */

/* Список сотрудников отдела. Строка — человек: ФИО, логин, код. Справа
   крестик: убрать из отдела. ФИО и логины приходят из этого браузера, поэтому
   у части строк их может не быть — там стоит прочерк. */
.employees-page {
    max-width: 920px;
}

.employees-head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 16px;
    margin-bottom: 4px;
}

.employees-head h2 {
    margin: 0 0 6px;
    font-size: 20px;
    color: var(--dark);
}

.employees-hint {
    margin: 0;
    max-width: 560px;
    font-size: 13px;
    line-height: 1.5;
    color: #5C636F;
}

.employees-table {
    margin-top: 12px;
    background: var(--white);
    border: 1px solid var(--border);
    border-radius: 12px;
    overflow: hidden;
}

.employees-table th {
    padding: 10px 14px;
    background: #FAFBFC;
    text-transform: uppercase;
    letter-spacing: .04em;
    font-size: 11.5px;
}

.employees-table td {
    padding: 10px 14px;
    font-size: 13.5px;
    border-bottom: 1px solid #F1F3F6;
}

.employees-table tr:last-child td {
    border-bottom: 0;
}

.employees-name {
    font-weight: 600;
    color: var(--dark);
}

.employees-code {
    font-variant-numeric: tabular-nums;
    color: var(--dark-2);
}

.employees-muted {
    color: var(--muted);
}

.employees-actions,
.employees-actions-head {
    width: 52px;
    text-align: center;
}

/* Крестик: маленький и сдержанный, но с красным текстом — это действие
   «убрать человека», а не украшение строки. */
.employee-remove {
    width: 28px;
    height: 28px;
    border: 0;
    border-radius: 8px;
    background: #F4F5F7;
    color: #8C1D33;
    font-size: 13px;
    line-height: 1;
    cursor: pointer;
    transition: background .15s, color .15s;
}

.employee-remove:hover {
    background: #FCE8E8;
}

.employees-empty {
    padding: 26px 14px !important;
    text-align: center;
    color: var(--muted);
}

/* =========================
   HOME: ВЫБОР ОТДЕЛА
========================= */

/* Главная страница. Отделов может быть сколько угодно, поэтому карточки идут
   сеткой: на широком экране в ряд, на узком — по одной. Палитра одна, жёлтая:
   цвет больше не закреплён за отделом. */
.home-page {
    max-width: 1080px;
    margin: 0 auto;
    padding: 10px 0 30px;
}

.home-intro h1 {
    margin: 0 0 8px;
    font-size: 26px;
    color: var(--dark);
}

.home-hint {
    margin: 0 0 18px;
    font-size: 14px;
    line-height: 1.5;
    color: #5C636F;
}

.home-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
    gap: 16px;
    margin-bottom: 28px;
}

.home-empty {
    margin: 0;
    padding: 22px;
    border-radius: 12px;
    background: var(--white);
    border: 1px dashed #DDE0E5;
    color: var(--muted);
    font-size: 14px;
}

.home-card {
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding: 18px 18px 16px;
    border-radius: 14px;
    background: var(--white);
    border: 1px solid var(--border);
    box-shadow: 0 2px 8px rgba(28, 27, 36, .04);
}

.home-card-link {
    display: block;
    color: inherit;
    text-decoration: none;
}

.home-card h3 {
    margin: 0 0 4px;
    font-size: 18px;
    color: var(--dark);
}

.home-card-code {
    margin: 0;
    font-size: 12.5px;
    color: var(--muted);
    font-variant-numeric: tabular-nums;
}

.home-card-counts {
    margin: 0;
    font-size: 13px;
    color: var(--dark-2);
}

.home-card-actions {
    display: flex;
    gap: 8px;
    margin-top: auto;
}

.home-card-actions .action-btn {
    height: 36px;
    padding: 0 14px;
    font-size: 13px;
    text-decoration: none;
}

.home-create {
    padding: 20px 22px 18px;
    border-radius: 14px;
    background: var(--white);
    border: 1px solid var(--border);
}

.home-create h2 {
    margin: 0 0 6px;
    font-size: 18px;
    color: var(--dark);
}

.home-form {
    display: flex;
    align-items: flex-end;
    gap: 12px;
    flex-wrap: wrap;
}

.home-field {
    display: flex;
    flex-direction: column;
    gap: 6px;
    font-size: 13px;
    font-weight: 600;
    color: var(--dark-2);
}

.home-field input {
    height: 38px;
    padding: 0 10px;
    border-radius: 9px;
    border: 1px solid #DDE0E5;
    font-size: 13.5px;
    font-family: inherit;
    width: 220px;
}

.home-field input[type="number"] {
    width: 120px;
}

/* Название отдела в панели: вместо кнопок переключения. */
.department-name {
    font-size: 20px;
    font-weight: 700;
    color: var(--dark);
}

.month-navigation {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-left: 26px;
}

.month {
    min-width: 168px;
    padding: 6px 10px;
    border: 0;
    border-radius: 9px;
    background: transparent;
    font-size: 25px;
    line-height: 1.1;
    font-weight: 700;
    color: var(--dark);
    cursor: pointer;
    text-align: center;
    transition: background .2s;
}

.month:hover {
    background: #EEF0F3;
}

.month-arrow {
    width: 38px;
    height: 38px;
    border: 0;
    border-radius: 9px;
    background: #EEF0F3;
    color: var(--dark-2);
    cursor: pointer;
    display: grid;
    place-items: center;
    font-size: 20px;
    transition: background .2s;
}

.month-arrow:hover {
    background: #E4E6EA;
}

/* =========================
   ACTION BUTTONS
========================= */

.actions {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
}

.action-btn {
    height: 44px;
    padding: 0 18px;
    border-radius: 10px;
    display: inline-flex;
    align-items: center;
    gap: 9px;
    font-size: 14px;
    font-weight: 600;
    cursor: pointer;
    transition: transform .2s, box-shadow .2s, background .2s;
}

.action-btn:disabled {
    opacity: .5;
    cursor: not-allowed;
    transform: none;
    box-shadow: none;
}

.action-btn:not(:disabled):hover {
    transform: translateY(-1px);
    box-shadow: 0 4px 12px rgba(28, 27, 36, .08);
}

.import-btn {
    background: var(--white);
    border: 1px solid #DDE0E5;
    color: var(--dark-2);
}

.plan-btn {
    background: var(--dark-2);
    border: 1px solid var(--dark-2);
    color: #fff;
}

/* Пока идёт расчёт, на кнопке тикает обратный отсчёт. Цифры разной ширины
   сдвигали бы надпись на каждом тике, поэтому разрядность фиксированная, а
   ширина кнопки — по самой длинной надписи («5:00»), чтобы соседние кнопки
   не прыгали вместе с таймером. */
.plan-btn.is-counting {
    font-variant-numeric: tabular-nums;
    cursor: progress;
    min-width: 128px;
    justify-content: center;
}

.plan-label {
    font-variant-numeric: tabular-nums;
}

.export-btn {
    background: var(--yellow);
    border: 1px solid var(--yellow);
    color: var(--dark);
}

/* Очистка расписаний: необратимое действие, поэтому кнопка скромнее прочих
   и заметно «опасная» при наведении. Ширина фиксированная — это крестик,
   а не подпись. */
.clear-btn {
    width: 44px;
    padding: 0;
    justify-content: center;
    background: var(--white);
    border: 1px solid #DDE0E5;
    color: var(--dark-2);
    font-size: 16px;
    line-height: 1;
}

.clear-btn:not(:disabled):hover {
    background: var(--dark-2);
    border-color: var(--dark-2);
    color: #fff;
}

/* =========================
   NOTICES
========================= */

.notices {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.notice {
    padding: 11px 15px;
    border-radius: 10px;
    font-size: 14px;
    line-height: 1.45;
    border: 1px solid transparent;
}

.notice-info { background: #EEF4FF; border-color: #D6E2FF; color: #21408A; }
.notice-ok { background: #E9F9F1; border-color: #C6EEDB; color: #155B42; }
.notice-warn { background: #FFF7E3; border-color: #F5E4B5; color: #7A5500; }
.notice-error { background: #FDECEF; border-color: #F7CDD6; color: #8C1D33; }

.notice pre {
    margin: 6px 0 0;
    padding: 8px 10px;
    background: rgba(255, 255, 255, .6);
    border-radius: 8px;
    font-size: 12px;
    overflow-x: auto;
    white-space: pre-wrap;
}

/* =========================
   CALENDAR
========================= */

/* Шапка календаря: строка с датами и её собственный слой прокрутки.
   Стоит СНАРУЖИ `.calendar-wrapper`, потому что внутри контейнера с
   `overflow-x: auto` закрепление по вертикали не работает: такой контейнер сам
   становится областью прокрутки, и `sticky` отсчитывается от него, а по
   вертикали он не прокручивается. Проверено в браузере — внутри прокрутки
   подпись дня уходила на 138 px выше экрана, вынесенная наружу оставалась на
   месте. Здесь `overflow-x: hidden`, чтобы шапку можно было сдвигать
   программно (`syncCalendarHead`), повторяя сдвиг календаря.
   `top: 62px` — высота `.topbar`, чтобы строка дат вставала под ним. */
.calendar-head {
    position: sticky;
    top: 62px;
    z-index: 20;
    overflow-x: hidden;
    background: #FBFCFD;
    border: 1px solid var(--border);
    border-bottom: 0;
    border-radius: 12px 12px 0 0;
}

.calendar-head-grid {
    min-width: calc(var(--employee-width) + var(--day-count, 31) * var(--day-width));
    display: grid;
    grid-template-columns: var(--employee-width) repeat(var(--day-count, 31), var(--day-width));
}

.calendar-wrapper {
    width: 100%;
    background: var(--white);
    border: 1px solid var(--border);
    border-radius: 12px;
    /* Прокрутка только вбок. Высоту не ограничиваем: список сотрудников
       длиннее экрана, и вертикально должна листаться страница, а не эта
       рамка. Иначе колесо над календарём прокручивало бы дни вбок и до
       нижних строк было бы не добраться. */
    overflow-x: auto;
    overflow-y: hidden;
    box-shadow: 0 2px 8px rgba(28, 27, 36, .035);
}

/* Шапка стоит вплотную к календарю: вместе они читаются как одна таблица.
   Класс ставит `syncCalendarHead`: пока строк нет, шапка пуста и её место
   занимает только календарь с обычными скруглениями. */
.calendar-head:empty {
    display: none;
}

.calendar-wrapper.head-attached {
    border-top: 0;
    border-radius: 0 0 12px 12px;
}

.calendar {
    min-width: calc(var(--employee-width) + var(--day-count, 31) * var(--day-width));
    display: grid;
    grid-template-columns: var(--employee-width) repeat(var(--day-count, 31), var(--day-width));
}

/* =========================
   HEADER
========================= */

.calendar-header {
    display: contents;
}

.employee-header,
.day-header {
    height: 46px;
    display: flex;
    align-items: center;
    border-bottom: 1px solid var(--border);
    border-right: 1px solid var(--border);
    background: #FBFCFD;
}

.employee-header {
    position: sticky;
    left: 0;
    z-index: 10;
    padding: 0 16px;
    color: #7D8490;
    font-size: 13px;
    font-weight: 600;
}

.day-header {
    flex-direction: column;
    justify-content: center;
    gap: 2px;
    color: #7D8490;
    font-size: 13px;
    font-weight: 600;
    /* Дата — кнопка: по ней отмечают праздник. Вид остаётся прежним, убирается
       только оформление кнопки по умолчанию. */
    border: 0;
    border-right: 1px solid var(--border);
    border-bottom: 1px solid var(--border);
    font-family: inherit;
    cursor: pointer;
    padding: 0;
    background: #FBFCFD;
}

.day-header:hover {
    background: #F2F5F9;
}

.day-header:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: -2px;
}

.day-header .day-weekday {
    font-size: 11px;
    font-weight: 500;
    color: #A2A8B2;
}

.day-header.weekend { background: #FFFBEF; }
.day-header.weekend .day-weekday { color: var(--yellow-dark); }
.day-header.weekend:hover { background: #FFF6DC; }

/* Праздник — красный того же оттенка, что светложёлтый выходного.
   Заказчик просил именно так: «у нас сб и вскр выделены таким светложёлтым
   цветом, давай также этот отмеченный день выделять красным цветом того же
   оттенка что и желтый». Тон и насыщенность совпадают с #FFFBEF, отличается
   только цвет: #FFEFEF. */
.day-header.holiday {
    background: #FFEFEF;
    color: #8C1D33;
}

.day-header.holiday .day-weekday { color: #C0566E; }

.day-header.holiday:hover { background: #FFE3E3; }

/* Праздник-«переработка»: отгула за него не дают, и это видно по обводке.
   Заливка та же — день всё равно нерабочий, — а пунктир говорит, что
   компенсация другая. Заказчик различает эти случаи двумя кнопками. */
.day-header.holiday.no-comp {
    box-shadow: inset 0 0 0 2px #E8A0AE;
}

.day-header.today {
    color: var(--green-dark);
    font-weight: 700;
    box-shadow: inset 0 -3px 0 0 var(--green);
}

.day-header.free {
    color: #A2A8B2;
    font-weight: 500;
}

/* =========================
   EMPLOYEE ROW
========================= */

.employee-cell {
    height: var(--row-height);
    position: sticky;
    left: 0;
    z-index: 5;
    display: flex;
    align-items: center;
    gap: 11px;
    padding: 0 14px;
    border-right: 1px solid var(--border);
    border-bottom: 1px solid var(--border);
    background: var(--white);
}

.employee-info {
    min-width: 0;
}

.employee-name {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    font-size: 14px;
    font-weight: 600;
    color: #30333C;
}

.employee-role {
    margin-top: 3px;
    font-size: 12px;
    color: #9298A2;
}

/* =========================
   DAY CELLS
========================= */

.day-cell {
    height: var(--row-height);
    padding: 4px;
    border-right: 1px solid var(--border);
    border-bottom: 1px solid var(--border);
    background: #fff;
    position: relative;
}

.day-cell.weekend { background: #FEFDF8; }

/* Праздник в сетке — тот же красный, что в строке с датами: `#FFEFEF`.
   Раньше здесь стоял `#FFFBF0` — цвет выходного дня, и 4 ноября в календаре
   выглядело как обычная суббота, хотя сверху было красным. Заказчик указал на
   это прямо: «в строке дат он подсвечен красным а вот в самом календаре также
   цвет выходного дня, надо поставить такой же оттенок красного на весь
   столбец». Столбец — это клетки всех сотрудников за этот день, и все они
   помечены классом `holiday`, так что правило одно на весь столбец. */
.day-cell.holiday { background: #FFEFEF; }

/* Клетка смены — светлая карточка: заливка, рамка на тон темнее, тёмный текст
   того же тона (палитра с референса, см. `--shift-fill` выше). Раньше смена
   была плотной зелёной плашкой с белым текстом; на референсе клетки светлые, и
   глаз читает месяц спокойнее — заказчик и просил обновить вид по нему.
   `position: relative` нужен полосе пожелания: она рисуется псевдоэлементом и
   не должна сдвигать время. */
.shift {
    position: relative;
    width: 100%;
    height: 100%;
    /* Поля скромные, а текст по центру — как на референсе. Горизонтальные 4 px
       нужны из-за рамки: «09:00 — 18:00» при 13 px занимает ~82 px, и при
       прежних 10 px полей строка вылезала за карточку (замерено в браузере:
       не хватало 5 px). Центрирование делает этот запас незаметным. */
    padding: 6px 4px;
    border-radius: 7px;
    background: var(--shift-fill);
    border: 1px solid var(--shift-line);
    color: var(--shift-text);
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 1px;
    font-size: 13px;
    line-height: 1.2;
    font-weight: 600;
    cursor: pointer;
    text-align: center;
    font-family: inherit;
    transition: transform .15s, box-shadow .15s, filter .15s;
}

.shift:hover {
    transform: scale(.985);
    box-shadow: 0 4px 10px rgba(23, 107, 75, .18);
}

/* Ночная смена — та же карточка на тон глубже. Подпись «через полночь» есть
   только в обычном виде; в компактном смена должна отличаться без неё, иначе
   ночной час не отличить от дневного. */
.shift.overnight {
    background: #D3EFE1;
    border-color: #A9DFC7;
}

.shift-range {
    white-space: nowrap;
}

.shift-extra {
    font-size: 11px;
    font-weight: 500;
    color: rgba(23, 107, 75, .75);
}

/* Полоса пожелания слева — главное обозначение референса. Заливку она не
   меняет: смена остаётся сменой, а полоса говорит, как обошлись с просьбой
   человека. Толщина 3 px и отступ 2 px повторяют образец: полоса внутри
   рамки, скруглённая, по высоте клетки. */
.shift::before {
    content: "";
    position: absolute;
    left: 2px;
    top: 2px;
    bottom: 2px;
    width: 3px;
    border-radius: 2px;
    background: transparent;
}

/* Пожелание учтено — зелёная полоса. */
.shift.wish-ok::before {
    background: var(--wish-ok);
}

/* Пожелание не учтено — серая полоса: человек просил другую смену, просил
   выходной, а смену поставили, или смены ещё нет вовсе. */
.shift.wish-no::before {
    background: var(--wish-no);
}

.absence {
    width: 100%;
    height: 100%;
    border-radius: 7px;
    display: grid;
    place-items: center;
    font-size: 15px;
    font-weight: 700;
    cursor: pointer;
    border: 1px solid transparent;
    font-family: inherit;
}

/* Отсутствия — та же схема «заливка + рамка + тёмный текст», что у смены.
   Цвет вида взят с референса: отпуск синий, больничный красный, обучение
   сиреневый. Раньше отпуск был синим без рамки, больничный оранжевым, а
   обучение светложёлтым — жёлтый спорил с цветом выходного дня и праздника. */
.absence.vacation {
    background: var(--vacation-fill);
    border-color: var(--vacation-line);
    color: var(--vacation-text);
}

.absence.sick {
    background: var(--sick-fill);
    border-color: var(--sick-line);
    color: var(--sick-text);
}

.absence.study {
    background: var(--study-fill);
    border-color: var(--study-line);
    color: var(--study-text);
}

.empty-day { width: 100%; height: 100%; border: 0; background: transparent; cursor: pointer; }
.empty-day:hover { background: rgba(35, 155, 112, .10); border-radius: 7px; }

/* Пожелание без смены: смены ещё нет, поэтому и карточки смены нет — светлая
   «заготовка» с пунктирной рамкой и серой полосой слева. Пунктир отличает её
   от смены, полоса говорит, что просьба пока не выполнена.
   Раньше такая клетка была залита фиолетовым: по референсу пожелание — это
   полоса, а не заливка, и цвет смены оно менять не должно. */
.shift.wish {
    background: #F6F7F9;
    border: 1px dashed #C6CBD3;
    color: #5C636F;
}

.shift.wish:hover {
    box-shadow: 0 4px 10px rgba(92, 99, 111, .18);
}

/* Клетка, которая красится прямо сейчас: окно дня открыто и тумблер
   «Пожелание» включён, но выбор ещё не сохранён. Без этого человек видит
   результат только после закрытия окна — и не понимает, сработало ли.
   Показываем то, что появится: пунктирную рамку и полосу пожелания, только
   приглушённую — она ещё не записана. */
.day-cell.wish-preview {
    background: #F3F5F8;
}

.day-cell.wish-preview .shift {
    border-style: dashed;
}

.day-cell.wish-preview .shift::before {
    background: var(--wish-no);
    opacity: .55;
}

.day-cell.wish-preview .empty-day {
    background: rgba(139, 154, 168, .22);
    border-radius: 7px;
}

.wishes-heading { margin-top: 22px; }
.wish-row .badge { background: var(--wish); color: #fff; }

/* Список пожеланий в окне сотрудника. Отдельного вида не заводим: строки те же,
   что у отпусков, — отличается только значок «П» и цвет полосы. */
.wishes-list { margin-top: 6px; }
.wishes-list .absence-row { border-left: 3px solid var(--wish); }

/* =========================
   SHIFT MODAL
========================= */

.hour-picker {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(76px, 1fr));
    gap: 8px;
}

.hour-option {
    height: 42px;
    border-radius: 9px;
    border: 1px solid #DDE0E5;
    background: var(--white);
    color: var(--dark-2);
    font-family: inherit;
    font-size: 14px;
    font-weight: 600;
    cursor: pointer;
    transition: background .15s, border-color .15s, color .15s;
}

.hour-option:hover {
    border-color: var(--dark-2);
}

.hour-option.active {
    background: var(--yellow);
    border-color: var(--yellow);
    color: var(--dark);
}

/* «Сделать выходным» — действие, снимающее смену. Скромнее прочих, но заметно:
   это не отмена, а изменение расписания. */
.off-btn {
    background: var(--dark-2);
    border: 1px solid var(--dark-2);
    color: #fff;
}

.off-btn:disabled {
    opacity: .45;
}

/* Выбор вида дня: смена или выходной.
   Первый шаг окна, и он должен читаться как выбор, а не как кнопка действия:
   пока ничего не сохранено, нажатие только меняет вид. Поэтому это не
   «кнопки», а переключатель с подсветкой выбранного. */
.kind-picker {
    display: inline-flex;
    gap: 6px;
    padding: 4px;
    border-radius: 11px;
    background: #F1F3F6;
    border: 1px solid var(--border);
}

.kind-option {
    height: 38px;
    padding: 0 20px;
    border: 0;
    border-radius: 8px;
    background: transparent;
    color: #5C636F;
    font-family: inherit;
    font-size: 14px;
    font-weight: 600;
    cursor: pointer;
    transition: background .15s, color .15s, box-shadow .15s;
}

.kind-option:hover {
    color: var(--dark-2);
}

.kind-option.active {
    background: var(--white);
    color: var(--dark);
    box-shadow: 0 1px 3px rgba(28, 27, 36, .12);
}

/* Переключатель «Пожелание сотрудника».
   Вид тот же, что у тумблеров часов в окне сотрудника: это один и тот же
   жест — «включить признак». Отличие только в цвете: у пожелания свой
   фиолетовый, и он единственный признак, который заказчик просил сохранить. */
.mode-switch {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    margin-top: 14px;
    padding: 9px 14px 9px 11px;
    border: 1px solid #DDE0E5;
    border-radius: 10px;
    background: var(--white);
    font-size: 14px;
    font-weight: 600;
    color: var(--dark-2);
    cursor: pointer;
    user-select: none;
    transition: background .15s, border-color .15s, color .15s;
}

.mode-switch input {
    position: absolute;
    opacity: 0;
    pointer-events: none;
}

.mode-switch .track {
    position: relative;
    width: 38px;
    height: 21px;
    border-radius: 11px;
    background: #D5D9E0;
    transition: background .18s;
    flex: 0 0 auto;
}

.mode-switch .track::after {
    content: "";
    position: absolute;
    top: 2px;
    left: 2px;
    width: 17px;
    height: 17px;
    border-radius: 50%;
    background: #fff;
    box-shadow: 0 1px 3px rgba(28, 27, 36, .25);
    transition: transform .18s;
}

.mode-switch input:checked + .track {
    background: var(--wish);
}

.mode-switch input:checked + .track::after {
    transform: translateX(17px);
}

.mode-switch:has(input:checked) {
    background: #F7F0FF;
    border-color: var(--wish);
    color: var(--wish-dark);
}

.mode-switch:has(input:focus-visible) {
    outline: 2px solid var(--wish);
    outline-offset: 2px;
}

/* Просьбу человека выполнить не удалось: смена стоит не в прошенный час или он
   просил выходной, а его поставили.
   По референсу такое положение показывает серая полоса слева (её ставит
   `.shift.wish-no` выше), а не обводка всей клетки: обводка спорила с рамкой
   карточки и читалась как «выбрано», а не как «просьбу не выполнили».
   Класс `wish-missed` остаётся на клетке — по нему видно состояние в разметке
   и в подсказке, — но своего правила у него больше нет: рисовать больше
   нечего, полоса уже на смене. Подписи «просил выходной» в клетке нет: час
   просьбы остался в подсказке. */

/* =========================
   LEGEND
========================= */

/* Расшифровка цветов стоит над календарём, сразу под кнопками отделов:
   заказчик просил видеть её до графика. Внизу она оказывалась ниже длинного
   списка сотрудников, и чтобы вспомнить значение цвета, нужно было листать всю
   страницу. Отступ поэтому снизу, а не сверху. */
/* Легенда стоит под календарём: над графиком она отвлекала внимание, а
   заказчик просил отдать это место самому расписанию. */
.legend {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 16px;
    margin-top: 10px;
    font-size: 12.5px;
    color: #5C636F;
}

.legend-item {
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

.legend-hint {
    margin-left: auto;
    color: var(--muted);
}

.shift-swatch,
.off-swatch,
.wish-ok-swatch,
.wish-no-swatch {
    width: 14px;
    height: 14px;
    border-radius: 4px;
    display: inline-block;
}

/* Образцы повторяют вид клеток: заливка, рамка и полоса пожелания слева.
   Иначе по легенде нельзя понять, что именно искать в календаре. */
.shift-swatch {
    background: var(--shift-fill);
    border: 1px solid var(--shift-line);
}

.off-swatch { background: #F1F2F5; border: 1px solid var(--border); }

.wish-ok-swatch,
.wish-no-swatch {
    background: var(--shift-fill);
    border: 1px solid var(--shift-line);
    box-shadow: inset 3px 0 0 var(--wish-ok);
}

.wish-no-swatch {
    box-shadow: inset 3px 0 0 var(--wish-no);
}

.vacation-swatch,
.sick-swatch,
.study-swatch {
    width: 18px;
    height: 18px;
    border-radius: 5px;
    display: inline-grid;
    place-items: center;
    font-size: 11px;
    font-weight: 700;
    border: 1px solid transparent;
}

/* Образцы отсутствий — те же переменные, что у клеток: одна палитра на все
   места, где виден вид отсутствия (сетка, легенда, мини-календарь, список). */
.vacation-swatch {
    background: var(--vacation-fill);
    border-color: var(--vacation-line);
    color: var(--vacation-text);
}

.sick-swatch {
    background: var(--sick-fill);
    border-color: var(--sick-line);
    color: var(--sick-text);
}

.study-swatch {
    background: var(--study-fill);
    border-color: var(--study-line);
    color: var(--study-text);
}

/* =========================
   EMPTY STATE
========================= */

.empty-state {
    padding: 60px 30px;
    text-align: center;
    color: #6D7480;
    min-width: 100%;
}

.empty-state h3 {
    margin: 0 0 8px;
    font-size: 17px;
    color: var(--dark);
}

.empty-state p {
    margin: 0 0 18px;
    font-size: 14px;
}

/* =========================
   MODALS
========================= */

.modal {
    position: fixed;
    inset: 0;
    background: rgba(28, 27, 36, .45);
    display: grid;
    place-items: center;
    z-index: 60;
    padding: 24px;
}

.modal-content {
    width: min(720px, 100%);
    max-height: 86vh;
    overflow: auto;
    background: var(--white);
    border-radius: 14px;
    padding: 22px 24px 20px;
    box-shadow: 0 24px 60px rgba(28, 27, 36, .28);
}

.modal-content.modal-small {
    width: min(440px, 100%);
}

.modal-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 12px;
}

.modal-header h2 {
    margin: 0;
    font-size: 19px;
    color: var(--dark);
}

.modal-close {
    width: 34px;
    height: 34px;
    border: 0;
    border-radius: 9px;
    background: #F1F2F5;
    color: var(--dark-2);
    font-size: 20px;
    cursor: pointer;
    line-height: 1;
}

.modal-hint {
    margin: 0 0 16px;
    font-size: 13.5px;
    line-height: 1.5;
    color: #5C636F;
}

.modal-hint code {
    background: #F1F2F5;
    padding: 1px 5px;
    border-radius: 5px;
    font-size: 12.5px;
}

.modal-file {
    margin-bottom: 12px;
}

.modal-file label {
    display: block;
    font-size: 13px;
    font-weight: 600;
    margin-bottom: 6px;
    color: var(--dark-2);
}

.modal-file input[type="file"] {
    width: 100%;
    font-size: 13.5px;
}

/* Текстовые поля окон (новый сотрудник): оформление как у `select`, чтобы
   окно не выглядело собранным из разных наборов деталей. */
.modal-file input[type="text"],
.modal-file input[type="number"] {
    width: 100%;
    height: 38px;
    padding: 0 10px;
    border-radius: 9px;
    border: 1px solid #DDE0E5;
    background: var(--white);
    color: var(--dark-2);
    font-size: 13.5px;
    font-family: inherit;
}

/* Зона перетаскивания в окне импорта.
   Файл можно перетащить, вставить из буфера или выбрать щелчком: вся зона —
   большая кнопка, а не мелкое поле. Пунктирная рамка и подсветка при
   перетаскивании подсказывают, что сюда можно бросить файл. */
.drop-zone {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 4px;
    min-height: 132px;
    margin-bottom: 14px;
    padding: 18px;
    border: 1.5px dashed #C9CDD4;
    border-radius: 14px;
    background: #FAFBFC;
    color: var(--dark-2);
    text-align: center;
    cursor: pointer;
    transition: border-color .15s, background .15s, transform .15s;
}

.drop-zone:hover {
    border-color: var(--yellow-dark);
    background: #FFFDF2;
}

.drop-zone:focus-visible {
    outline: 2px solid var(--yellow-dark);
    outline-offset: 2px;
}

/* Файл над зоной: подсвечиваем и слегка приподнимаем — как в почтовых
   клиентах, чтобы было видно, куда отпускать. */
.drop-zone.over {
    border-color: var(--yellow);
    background: #FFF8D6;
    transform: translateY(-1px);
}

.drop-zone-icon {
    width: 34px;
    height: 34px;
    border-radius: 10px;
    display: grid;
    place-items: center;
    background: #FFF3BF;
    color: var(--dark);
    font-size: 18px;
    font-weight: 700;
}

.drop-zone-title {
    font-size: 14.5px;
    font-weight: 600;
    color: var(--dark);
    word-break: break-word;
}

.drop-zone-hint {
    font-size: 12.5px;
    color: var(--muted);
}

/* Выбор отдела в окне ФИО. Обычный `select` в этом оформлении без рамки и
   отступов выглядел бы чужим: остальные поля формы заданы явно. */
.modal-file select {
    width: 100%;
    height: 38px;
    padding: 0 10px;
    border-radius: 9px;
    border: 1px solid #DDE0E5;
    background: var(--white);
    color: var(--dark-2);
    font-size: 13.5px;
    font-family: inherit;
}

/* «Забыть данные отдела»: действие с локальной копией, а не с расписанием.
   Стоит слева от «Закрыть» и покрашено сдержанно-красным — нажать случайно не
   страшно (файл загружается заново), но и звать к нему незачем. */
.forget-btn {
    background: var(--white);
    border: 1px solid #E3C6C6;
    color: #8C1D33;
}

.modal-info {
    font-size: 13.5px;
    line-height: 1.5;
    color: #5C636F;
}

.modal-info ul {
    margin: 8px 0 0;
    padding-left: 20px;
}

.form-actions {
    display: flex;
    justify-content: flex-end;
    gap: 10px;
    margin-top: 18px;
    flex-wrap: wrap;
}

.year-row {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
    margin-bottom: 14px;
}

.year-button {
    height: 34px;
    padding: 0 14px;
    border-radius: 9px;
    border: 1px solid #DDE0E5;
    background: var(--white);
    color: var(--dark-2);
    font-weight: 600;
    font-size: 13.5px;
    cursor: pointer;
}

.year-button.active {
    background: var(--yellow);
    border-color: var(--yellow);
    color: var(--dark);
}

.year-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 8px;
}

.year-month {
    height: 46px;
    border-radius: 10px;
    border: 1px solid #DDE0E5;
    background: var(--white);
    color: var(--dark-2);
    font-size: 14px;
    font-weight: 600;
    cursor: pointer;
    transition: background .2s, transform .2s;
}

.year-month:hover {
    transform: translateY(-1px);
}

.year-month.active {
    background: var(--yellow);
    border-color: var(--yellow);
    color: var(--dark);
}

/* =========================
   EMPLOYEE MODAL
========================= */

.modal-content.modal-wide {
    width: min(1080px, 100%);
}

.modal-subtitle {
    margin: 4px 0 0;
    font-size: 13px;
    color: var(--muted);
}

.employee-columns {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 26px;
    align-items: start;
}

.employee-section {
    min-width: 0;
}

.employee-section h3 {
    margin: 0 0 4px;
    font-size: 15px;
    color: var(--dark);
}

.section-hint {
    margin: 0 0 12px;
    font-size: 12.5px;
    line-height: 1.45;
    color: var(--muted);
}

.hours-section {
    margin-top: 24px;
    padding-top: 20px;
    border-top: 1px solid var(--border);
}

.form-actions-start {
    justify-content: flex-start;
}

/* Кнопки «Отпуск», «Больничный», «Обучение» в окне сотрудника — те же цвета,
   что у клеток: одна палитра на все места, где виден вид отсутствия. */
.vacation-btn {
    background: var(--vacation-fill);
    border: 1px solid var(--vacation-line);
    color: var(--vacation-text);
}

.sick-btn {
    background: var(--sick-fill);
    border: 1px solid var(--sick-line);
    color: var(--sick-text);
}

.study-btn {
    background: var(--study-fill);
    border: 1px solid var(--study-line);
    color: var(--study-text);
}

/* =========================
   MINI CALENDAR
========================= */

.mini-calendar {
    border: 1px solid var(--border);
    border-radius: 10px;
    overflow: hidden;
    background: var(--white);
}

.mini-head {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    background: #FBFCFD;
    border-bottom: 1px solid var(--border);
}

.mini-head span {
    padding: 7px 0;
    text-align: center;
    font-size: 11.5px;
    font-weight: 600;
    color: #7D8490;
}

.mini-head span.weekend {
    color: var(--yellow-dark);
}

.mini-grid {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
}

.mini-day {
    aspect-ratio: 1.35;
    border: 0;
    border-right: 1px solid var(--border);
    border-bottom: 1px solid var(--border);
    background: var(--white);
    color: var(--text);
    font: inherit;
    font-size: 13px;
    cursor: pointer;
    transition: background .15s, color .15s;
}

.mini-day:nth-child(7n) {
    border-right: 0;
}

.mini-day.has-wish { position: relative; box-shadow: inset 0 0 0 2px var(--wish); }
.mini-wish { position: absolute; top: 0; right: 0; color: #fff; background: var(--wish); font-size: 8px; padding: 1px 3px; border-radius: 0 4px 0 4px; }
.mini-day.filler {
    background: #FAFBFC;
    cursor: default;
}

.mini-day.weekend {
    background: #FEFDF8;
}

/* Праздник в мини-календаре — тот же красный, что в строке с датами и в
   сетке. Раньше здесь стоял светложёлтый `#FFFBF0` — цвет выходного, и 4 ноября
   в мини-календаре не отличалось от субботы, хотя в остальных местах оно
   красное. Один цвет на все три места: иначе день выглядит по-разному в
   зависимости от того, куда смотришь. */
.mini-day.holiday {
    background: #FFEFEF;
    color: #8C1D33;
}

.mini-day.today {
    font-weight: 700;
    color: var(--green-dark);
    box-shadow: inset 0 -3px 0 0 var(--green);
}

/* Отсутствие в мини-календаре — те же переменные, что у клеток сетки. Одна
   палитра на все места, где виден вид отсутствия: иначе человек видит разное
   про одно и то же. */
.mini-day.absent {
    background: var(--vacation-fill);
    color: var(--vacation-text);
    font-weight: 600;
}

.mini-day.absent.sick {
    background: var(--sick-fill);
    color: var(--sick-text);
}

.mini-day.absent.study {
    background: var(--study-fill);
    color: var(--study-text);
}

.mini-day:hover:not(.filler) {
    background: #EEF4FF;
}

.mini-day.in-range {
    background: var(--yellow);
    color: var(--dark);
    font-weight: 700;
}

.mini-day.range-start,
.mini-day.range-end {
    background: var(--dark-2);
    color: #fff;
    font-weight: 700;
}

/* =========================
   PICKED RANGE
========================= */

.picked-range {
    margin-top: 10px;
    min-height: 22px;
    font-size: 13px;
    color: var(--dark-2);
}

.picked-range strong {
    color: var(--dark);
}

.picked-range .hint {
    color: var(--muted);
}

/* =========================
   ABSENCES LIST
========================= */

.absences-list {
    display: flex;
    flex-direction: column;
    gap: 8px;
    max-height: 340px;
    overflow-y: auto;
}

.absence-row {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 12px;
    border-radius: 10px;
    border: 1px solid var(--border);
    background: var(--white);
}

.absence-row .badge {
    flex: 0 0 auto;
    width: 26px;
    height: 26px;
    border-radius: 7px;
    display: grid;
    place-items: center;
    font-size: 12px;
    font-weight: 700;
}

/* Значки в списке отсутствий берут те же переменные, что клетки и легенда:
   одно место, где задан цвет вида, — и он не разъедется по экранам. */
.absence-row.vacation .badge {
    background: var(--vacation-fill);
    color: var(--vacation-text);
    box-shadow: inset 0 0 0 1px var(--vacation-line);
}

.absence-row.sick .badge {
    background: var(--sick-fill);
    color: var(--sick-text);
    box-shadow: inset 0 0 0 1px var(--sick-line);
}

.absence-row.study .badge {
    background: var(--study-fill);
    color: var(--study-text);
    box-shadow: inset 0 0 0 1px var(--study-line);
}

.absence-row .text {
    min-width: 0;
    flex: 1;
}

.absence-row .period {
    font-size: 13.5px;
    font-weight: 600;
    color: var(--dark);
}

.absence-row .days {
    margin-top: 2px;
    font-size: 12px;
    color: var(--muted);
}

.absence-row .remove {
    flex: 0 0 auto;
    width: 28px;
    height: 28px;
    border: 0;
    border-radius: 8px;
    background: #F1F2F5;
    color: #7D8490;
    font-size: 15px;
    cursor: pointer;
    transition: background .15s, color .15s;
}

.absence-row .remove:hover {
    background: #FDECEF;
    color: #8C1D33;
}

.absences-empty {
    padding: 22px 14px;
    border: 1px dashed var(--border);
    border-radius: 10px;
    text-align: center;
    font-size: 13px;
    color: var(--muted);
}

/* =========================
   HOUR SWITCHES
========================= */

.hours-note {
    margin-bottom: 10px;
    font-size: 12.5px;
    color: var(--muted);
}

.hours-note.limited {
    color: #7A5500;
}

.hours-switches {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.hour-switch {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 8px 12px 8px 10px;
    border: 1px solid #DDE0E5;
    border-radius: 10px;
    background: var(--white);
    font-size: 13.5px;
    font-weight: 600;
    color: var(--dark-2);
    cursor: pointer;
    user-select: none;
    transition: background .15s, border-color .15s, color .15s;
}

.hour-switch input {
    position: absolute;
    opacity: 0;
    pointer-events: none;
}

.hour-switch .track {
    position: relative;
    width: 34px;
    height: 19px;
    border-radius: 10px;
    background: #D5D9E0;
    transition: background .18s;
    flex: 0 0 auto;
}

.hour-switch .track::after {
    content: "";
    position: absolute;
    top: 2px;
    left: 2px;
    width: 15px;
    height: 15px;
    border-radius: 50%;
    background: #fff;
    box-shadow: 0 1px 3px rgba(28, 27, 36, .25);
    transition: transform .18s;
}

.hour-switch input:checked + .track {
    background: var(--green);
}

.hour-switch input:checked + .track::after {
    transform: translateX(15px);
}

.hour-switch:has(input:checked) {
    background: #E9F9F1;
    border-color: #C6EEDB;
    color: #155B42;
}

.hour-switch:has(input:focus-visible) {
    outline: 2px solid var(--green);
    outline-offset: 2px;
}

/* Базовый час включать нельзя: на него попадают «все остальные», и выключить
   его значило бы запретить человеку работать почти всегда. */
.hour-switch.base {
    background: #F7F8FA;
    border-style: dashed;
    color: var(--muted);
    cursor: default;
}

.hour-switch.base .track {
    opacity: .45;
}

.hour-switch.base .label::after {
    content: " · все остальные";
    font-weight: 400;
    color: var(--muted);
}

.save-state {
    align-self: center;
    font-size: 12.5px;
    color: var(--muted);
}

.save-state.ok {
    color: var(--green-dark);
}

.save-state.error {
    color: #8C1D33;
}

/* =========================
   RESPONSIVE: EMPLOYEE MODAL
========================= */

@media (max-width: 900px) {
    .employee-columns {
        grid-template-columns: 1fr;
        gap: 20px;
    }
}

/* =========================
   SCROLLBAR
========================= */

.calendar-wrapper::-webkit-scrollbar {
    width: 10px;
    height: 10px;
}

.calendar-wrapper::-webkit-scrollbar-track {
    background: #F2F3F5;
}

.calendar-wrapper::-webkit-scrollbar-thumb {
    background: #C7CBD2;
    border-radius: 10px;
}

.calendar-wrapper::-webkit-scrollbar-thumb:hover {
    background: #AEB3BC;
}

/* =========================
   TOOLBAR CAPTION
========================= */

/* Пояснение к разделу: в правилах и отчётах месяц не выбирается, и без строки
   слева было бы пусто, а человек — в недоумении. */
.toolbar-caption {
    align-self: center;
    font-size: 13px;
    color: var(--muted);
}

/* =========================
   RULES AND REPORTS
========================= */

.rules-page,
.reports-page {
    display: block;
}

.rules-head {
    margin: 4px 0 18px;
}

.rules-head h1 {
    margin: 0 0 6px;
    font-size: 22px;
    color: var(--dark);
}

.rules-subtitle {
    margin: 0;
    font-size: 13.5px;
    color: var(--muted);
}

/* Компактные виджеты: блоки правил в рамках со скруглением. Заказчик просил
   именно так — визуально разделить настройки, а не лить их одним потоком.
   Верхний ряд — по два блока в строку, нижний занимает всю ширину. */
.rules-grid,
.reports-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 16px;
    align-items: start;
}

.rules-card {
    background: var(--surface, var(--white));
    border: 1px solid var(--line, var(--border));
    border-radius: 14px;
    padding: 18px 20px 20px;
}

/* Служебные правила и веса — во всю ширину: в них много полей, и в половине
   строки они сжимаются до нечитаемого. */
.rules-card[data-group="hard"],
.rules-card[data-group="hours"],
.rules-card[data-group="weekends"],
.rules-card[data-group="service"],
.report-summary {
    grid-column: 1 / -1;
}

.rules-card-head {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 4px;
}

.rules-card-head h2 {
    margin: 0;
    font-size: 15.5px;
    color: var(--dark);
}

/* Значок обязательности: заказчик просил видеть, что обязательно, а что нет.
   Цвет — акцент отдела: подсветка меняется вместе с отделом. */
.rules-kind {
    padding: 2px 9px;
    border-radius: 20px;
    font-size: 11.5px;
    font-weight: 700;
    letter-spacing: .2px;
}

.rules-kind-hard {
    background: var(--accent);
    color: var(--accent-ink);
}

.rules-kind-soft {
    background: #EEF1F6;
    color: #5C636F;
}

.rules-kind-service {
    background: #F3F5F8;
    color: var(--muted);
}

.rules-card-hint {
    margin: 0 0 14px;
    font-size: 12.5px;
    line-height: 1.45;
    color: var(--muted);
}

.rules-fields {
    display: grid;
    grid-template-columns: 1fr;
    gap: 14px;
}

.rules-columns-2 {
    grid-template-columns: repeat(2, minmax(0, 1fr));
}

.field-span-2 {
    grid-column: 1 / -1;
}

.field-head {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 6px;
}

.field-label {
    font-size: 13px;
    font-weight: 600;
    color: #30333C;
}

.field-tag {
    padding: 1px 7px;
    border-radius: 20px;
    background: #EEF1F6;
    color: #6D7480;
    font-size: 10.5px;
    font-weight: 700;
}

.field-tag-hard {
    background: var(--accent);
    color: var(--accent-ink);
}

.field-hint {
    margin: 6px 0 0;
    font-size: 11.5px;
    line-height: 1.4;
    color: var(--muted);
}

.field-empty {
    margin: 0;
    font-size: 12.5px;
    color: var(--muted);
}

.field-input {
    width: 100%;
    height: 38px;
    padding: 0 11px;
    border: 1px solid var(--line, var(--border));
    border-radius: 9px;
    background: var(--white);
    color: var(--text);
    font: inherit;
    font-size: 13.5px;
}

.field-input:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 1px;
    border-color: var(--accent);
}

/* Тумблер «включено/выключено»: тот же вид, что у тумблеров часов в окне
   сотрудника. */
.field-switch {
    display: inline-flex;
    align-items: center;
    gap: 9px;
    cursor: pointer;
    user-select: none;
}

.field-switch input {
    position: absolute;
    opacity: 0;
    pointer-events: none;
}

.field-switch .track {
    position: relative;
    width: 38px;
    height: 21px;
    border-radius: 11px;
    background: #D5D9E0;
    transition: background .18s;
    flex: 0 0 auto;
}

.field-switch .track::after {
    content: "";
    position: absolute;
    top: 2px;
    left: 2px;
    width: 17px;
    height: 17px;
    border-radius: 50%;
    background: #fff;
    box-shadow: 0 1px 3px rgba(28, 27, 36, .25);
    transition: transform .18s;
}

.field-switch input:checked + .track {
    background: var(--accent);
}

.field-switch input:checked + .track::after {
    transform: translateX(17px);
}

.switch-label {
    font-size: 13px;
    color: var(--dark-2);
}

/* Тумблеры окна очистки. Каждый пункт — на своей строке: их пять, и подписи
   у них длинные («Отпуска, в том числе «Отпуск - НО»»), поэтому в строку они
   не встают и читались бы как один список без границ между пунктами. */
.clear-switch {
    display: flex;
    margin-bottom: 10px;
}

.clear-switch .switch-label {
    font-size: 13.5px;
    font-weight: 600;
    color: var(--dark-2);
}

/* Предупреждение о следствии очистки графика: история выходных и долги отгулов
   выводятся из опубликованных расчётов, и после очистки они обнуляются. Прячем
   не в спойлер, а держим на виду — это не подробность, а цена нажатия. */
.clear-warning {
    margin: 12px 0 0;
    font-size: 12.5px;
    color: #A25016;
}

/* Часы и дни недели: нажатие вместо выпадающего списка — видно разом весь
   набор. Подсвеченные пункты и есть то, что заказчик просил красить цветом
   отдела. */
.hour-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}

.hour-chip {
    height: 30px;
    padding: 0 10px;
    border: 1px solid var(--line, var(--border));
    border-radius: 8px;
    background: var(--white);
    color: #5C636F;
    font-family: inherit;
    font-size: 12.5px;
    font-weight: 600;
    cursor: pointer;
    transition: background .15s, border-color .15s, color .15s;
}

.hour-chip:hover {
    border-color: var(--accent);
    color: var(--dark-2);
}

.hour-chip.active {
    background: var(--accent);
    border-color: var(--accent);
    color: var(--accent-ink);
}

.week-chips .hour-chip {
    padding: 0 12px;
}

/* Обязательные смены по часам: час и число людей. */
.slot-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(148px, 1fr));
    gap: 8px;
}

.slot-row {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 10px;
    border: 1px solid var(--line, var(--border));
    border-radius: 9px;
    background: var(--white);
}

.slot-hour {
    font-size: 13px;
    font-weight: 600;
    color: var(--dark-2);
    min-width: 44px;
}

.slot-input {
    width: 100%;
    height: 30px;
    padding: 0 8px;
    border: 1px solid var(--line, var(--border));
    border-radius: 7px;
    font: inherit;
    font-size: 13px;
    color: var(--text);
}

.slot-input:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 1px;
}

.rules-actions {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-top: 18px;
    flex-wrap: wrap;
}

/* История версий: свёрнута, чтобы не мешать форме. */
.rules-history {
    margin-top: 20px;
    border: 1px solid var(--line, var(--border));
    border-radius: 14px;
    background: var(--white);
    padding: 14px 20px;
}

.rules-history summary {
    cursor: pointer;
    font-size: 14px;
    font-weight: 600;
    color: var(--dark-2);
}

.history-table,
.report-table {
    width: 100%;
    margin-top: 14px;
    border-collapse: collapse;
    font-size: 13px;
}

.history-table th,
.report-table th {
    text-align: left;
    padding: 8px 10px;
    border-bottom: 1px solid var(--line, var(--border));
    color: var(--muted);
    font-weight: 600;
    font-size: 12px;
}

.history-table td,
.report-table td {
    padding: 8px 10px;
    border-bottom: 1px solid #F1F3F6;
    color: var(--text);
}

/* --- отчёты --- */

.report-tiles {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    margin-bottom: 12px;
}

.report-tile {
    flex: 1 1 130px;
    padding: 12px 14px;
    border-radius: 11px;
    background: #F7F9FC;
    border: 1px solid var(--line, var(--border));
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.report-tile-value {
    font-size: 21px;
    font-weight: 700;
    color: var(--dark);
}

.report-tile-label {
    font-size: 11.5px;
    color: var(--muted);
}

.report-hour,
.report-code {
    font-weight: 600;
    color: var(--dark-2);
    white-space: nowrap;
}

.report-bar {
    height: 8px;
    min-width: 90px;
    border-radius: 5px;
    background: #F1F3F6;
    overflow: hidden;
}

.report-bar-fill {
    display: block;
    height: 100%;
    border-radius: 5px;
    background: var(--accent);
}

/* =========================
   RESPONSIVE
========================= */

@media (max-width: 1100px) {
    .topbar { padding: 0 18px; gap: 14px; }
    .brand-name { display: none; }
    .nav-item { padding: 0 12px; font-size: 14px; }
    .page { padding: 18px; }
    .month-navigation { margin-left: 0; }
    .month { font-size: 21px; min-width: 140px; }
    .toolbar-left { width: 100%; }
    .actions { margin-left: auto; }
    .rules-grid,
    .reports-grid { grid-template-columns: 1fr; }
    .rules-columns-2 { grid-template-columns: 1fr; }
}

@media (max-width: 760px) {
    .api-state { display: none; }
    .nav-item { padding: 0 10px; white-space: nowrap; }
    .month { font-size: 19px; min-width: 120px; }
    .actions { width: 100%; }
    .action-btn { flex: 1; justify-content: center; }
    .year-grid { grid-template-columns: repeat(3, 1fr); }
    .toolbar-caption { display: none; }
}
