/* Свод «Ген Дир» — оформление.
 *
 * ⚠ БЛОК ТОКЕНОВ НИЖЕ — ДОСЛОВНАЯ КОПИЯ РАЗДЕЛА ТОКЕНОВ ИЗ
 * `finance/web/static/css/dashboard.css`. ПРАВКА ОДНОГО ТРЕБУЕТ ПЕРЕНОСА
 * В ДРУГОЙ, и на это есть тест `web/tests/test_tokens_copy.py`.
 *
 * Копия, а не общий файл, по той же причине, что и `auth.py`: свод и
 * финансы — отдельные репозитории, связанные данными, а не кодом. Но
 * расходиться палитре нельзя совсем: свод и блок стоят на одном домене и
 * открываются один за другим в одном окне, поэтому разъехавшийся оттенок
 * фона читается не как «два сервиса», а как «что-то сломалось». Значения
 * там подобраны по контрасту WCAG и по ΔE между сериями — это расчёт, а
 * не вкус, и повторять его на глаз нельзя.
 *
 * Часть токенов (`--series-*`) свод не использует: цифр и графиков здесь
 * нет. Они всё равно скопированы — блок остаётся сверяемым целиком, а
 * выборочная копия разъехалась бы первой.
 *
 * СВОЁ ОФОРМЛЕНИЕ НАЧИНАЕТСЯ НИЖЕ, ПОСЛЕ ТОКЕНОВ.
 */

/* ───────────────────────────────────────────────────────────────────────
   1. Токены
   ─────────────────────────────────────────────────────────────────────── */

:root {
  color-scheme: light;

  /* ⚠ ГРУНТ ХОЛОДНЫЙ, А НЕ КРЕМОВЫЙ, И ЭТО ГЛАВНАЯ ПРАВКА ВСЕЙ ПАЛИТРЫ.
     Прежний #F6F6F4 — тёплый бумажный тон; на нём белая карточка почти не
     отделялась, и весь экран читался как один лист. Синеватый грунт даёт
     карточке подняться, не прибавляя ей ни тени, ни рамки: разница по
     светлоте та же, а по температуре — заметная.
     Утверждено владельцем 2026-09-04 по макету светлой темы. */
  --ground: #EEF1F7;
  --surface: #FFFFFF;
  --surface-alt: #F6F8FC;

  /* Чернила уведены в ту же синеву. Чистый нейтральный текст на холодном
     грунте выглядит выцветшим — глаз читает его как «выключено». */
  --ink: #12162A;
  --ink-mid: #40465F;
  /* Пояснительный ярус: подписи осей, `.card__note`, подвал, `.tile__prev`.
     Порог AA 4,5:1 обязан держаться на ВСЕХ ТРЁХ фонах, а не только на
     белом, — на этом уже обжигались. Замер: 5,24 на surface, 4,63 на
     ground, 4,93 на surface-alt. */
  --ink-soft: #656B87;
  --rule: #E6E9F2;
  --rule-strong: #D5DAE8;
  /* ⚠ ГРАНИЦА КАРТОЧКИ — ПОЛУПРОЗРАЧНАЯ, И ЭТО НЕ ПРИДИРКА К ОТТЕНКУ.
     Сплошной `--rule` верен ровно на одном фоне: на `--surface`. На
     `--surface-alt` и на `--ground` он либо теряется, либо становится
     заметнее самой карточки. Полупрозрачная граница ложится на любой фон
     одинаково, потому что берёт его же цвет.

     Значения от Vercel: 8% чёрного в светлой теме, 15% БЕЛОГО в тёмной —
     там граница меняет не только силу, но и природу. Ровная инверсия
     чёрного дала бы невидимый край. Чёрный подкрашен синим — тем же, что
     чернила: нейтральный на холодном грунте читается как грязь. */
  --ring: rgba(18, 22, 42, 0.08);

  /* Акцент насыщеннее прежнего #3D4C8F: тот был почти неотличим от
     `--ink-mid` и на активной вкладке не читался как «выбрано». */
  --accent: #4B56D2;
  --accent-soft: rgba(75, 86, 210, 0.10);

  /* ⚠ СЕМАНТИКА НЕ БЕРЁТСЯ ИЗ МАКЕТА. В макете состояния яркие (#D64545,
     #0F8F5C) — они там стоят БЕЛЫМ ТЕКСТОМ НА ЗАЛИВКЕ плитки, где контраст
     считается наоборот. На странице те же цвета работают мелким текстом на
     белом, и яркие значения дают 4,0:1 — ниже AA. Здесь стоят затемнённые
     версии тех же оттенков: 6,09 · 6,55 · 6,53 на surface. */
  --state-good: #10704E;
  --state-warn: #7D5606;
  --state-bad: #B02A2F;
  --state-good-bg: rgba(16, 112, 78, 0.10);
  --state-warn-bg: rgba(125, 86, 6, 0.12);
  --state-bad-bg: rgba(176, 42, 47, 0.10);

  /* Разведены по ΔE, а не подобраны на глаз. Пороги: 25 от семантики,
     16 от структурного акцента, 22 между собой.

     ⚠ СЕРИЯ-1 СДВИНУТА В СИНЕВУ вместе со сменой акцента. Прежний #3667C9
     отделялся от нового акцента #4B56D2 на 19,7 — формально выше порога 16,
     но это «столбец выручки почти того же цвета, что активная вкладка».
     #2E7BC4 даёт 39,3, то есть возвращает тот запас, ради которого порог и
     писался. Замеры остального: серии между собой 38,9 / 26,1 / 51,3,
     от семантики минимум 44,7, контраст на белом 4,42 / 5,26 / 4,33.

     Красного и зелёного в наборе нет вовсе — линия на графике не должна
     читаться как оценка. */
  --series-1: #2E7BC4;
  --series-2: #8854B6;
  --series-3: #5B7D9A;
  --series-1-soft: rgba(46, 123, 196, 0.16);
  --series-3-soft: rgba(91, 125, 154, 0.20);

  /* ⚠ ТРИ СЛОЯ С ОТРИЦАТЕЛЬНЫМ SPREAD, А НЕ ДВА У САМОГО КРАЯ.
     Прежняя тень — `0 1px 2px .05, 0 1px 1px .04` — оба слоя прижаты к
     нулю, рассеянного слоя нет вовсе. Это и есть главная причина, по
     которой карточки читались плоскими: глубины у них не было никакой.

     Значения сняты с боевого стиля Vercel Geist, а не подобраны: слой 1
     контактный (1px, 2%), слой 2 средний (8/16 при spread −4, 4%), слой 3
     рассеянный (24/32 при spread −8, 6%). Отрицательный spread втягивает
     большое размытие внутрь, чтобы оно не расползалось вбок — именно это
     отличает дорогую тень от одной жирной размазни.

     ПОДТОН СИНИЙ, А НЕ НЕЙТРАЛЬНЫЙ: у Stripe все двенадцать теневых
     токенов подкрашены в фирменный синий, ни одного чёрного. Нейтральный
     серый на цветной подложке читается как грязь. */
  --shadow: 0px 1px 1px rgba(13, 23, 56, 0.02),
            0px 8px 16px -4px rgba(13, 23, 56, 0.04),
            0px 24px 32px -8px rgba(13, 23, 56, 0.06);

  --font-ui: "Golos Text", "Segoe UI", system-ui, -apple-system, sans-serif;
  --font-mono: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;

  /* 14px вместо 10: на макете карточка заметно мягче, и это единственное,
     что отличает её силуэт от таблицы. Вложенные элементы берут на 4-6
     меньше, иначе угол внутри выглядит острее внешнего. */
  --radius: 14px;
  --gap: 20px;

  /* ── Тёмная палитра: ЗНАЧЕНИЯ ЖИВУТ ТОЛЬКО ЗДЕСЬ ──────────────────────
     Тему включают два разных селектора — системный внутри @media и ручной
     `[data-theme="dark"]`, — и объединить их в CSS нельзя. Раньше каждый
     нёс свою копию значений, и это немедленно выстрелило: правка палитры
     попала в один блок и не попала в другой, отчего ручной переключатель
     остался со старыми цветами, а системная тема — с новыми. На глаз такое
     не видно вовсе: надо сидеть в тёмной теме И нажать переключатель.
     Теперь значение написано один раз, а оба селектора только
     переприсваивают — механически и одинаково.

     ⚠ ТЁМНАЯ НЕ ИНВЕРСИЯ СВЕТЛОЙ. Ступени поверхности взяты отдельно:
     грунт глубже карточки, карточка глубже вложенной плашки. Инверсия дала
     бы карточку СВЕТЛЕЕ грунта ровно настолько же, насколько в светлой
     теме она темнее, — и весь экран поплыл бы. */
  --d-ground: #12141F;
  --d-surface: #1C1F2D;
  --d-surface-alt: #262A3A;
  --d-ink: #EFF1F8;
  --d-ink-mid: #C5CADD;
  /* Тот же порог на всех трёх фонах: 5,75 · 6,44 · 5,00. */
  --d-ink-soft: #9298B5;
  --d-rule: #272B3B;
  --d-rule-strong: #363C52;
  --d-ring: rgba(255, 255, 255, 0.13);

  --d-accent: #8A93F0;
  --d-accent-soft: rgba(138, 147, 240, 0.14);

  --d-state-good: #4CC492;
  --d-state-warn: #DCA455;
  --d-state-bad: #F08080;
  --d-state-good-bg: rgba(76, 196, 146, 0.14);
  --d-state-warn-bg: rgba(220, 164, 85, 0.14);
  --d-state-bad-bg: rgba(240, 128, 128, 0.14);

  /* Тем же счётом и с тем же запасом, что светлые. Серия-1 сдвинута по той
     же причине: при прежнем #5769C7 расстояние до нового акцента #8A93F0
     падало до 16,9 — впритык к порогу 16, то есть любая будущая правка
     просела бы ниже незамеченной. #4F94DA даёт 21,3.
     Замеры: серии между собой 40,9 / 27,4 / 51,0, от семантики минимум
     52,2, контраст на карточке 5,13 / 4,97 / 7,21 — выше 3:1, порога WCAG
     для нетекстовой графики. */
  --d-series-1: #4F94DA;
  --d-series-2: #B375D1;
  --d-series-3: #90B0CB;
  --d-series-1-soft: rgba(79, 148, 218, 0.22);
  --d-series-3-soft: rgba(144, 176, 203, 0.24);

  /* ⚠ В ТЁМНОЙ ТЕМЕ ТЕНЬ СИЛЬНЕЕ ВЧЕТВЕРО И РАЗМЫТА БОЛЬШЕ, а не
     «та же тень на тёмном». Замер по боевому стилю Linear: светлая
     `0 7px 24px #0000000f` (6%) против тёмной `0 7px 32px #00000059`
     (35%). На тёмном фоне слабая тень не читается вовсе, и карточка
     сливается с подложкой — ровно то, от чего лечит первая ступень
     поверхности. */
  --d-shadow: 0px 1px 1px rgba(0, 0, 0, 0.20),
              0px 7px 32px rgba(0, 0, 0, 0.45);
}

/* Один список переприсваиваний на две точки входа. Строки ниже намеренно
   одинаковы в обоих селекторах — на это есть тест. */
@media (prefers-color-scheme: dark) {
  /* Тёмная по системной настройке — но только если человек не выбрал
     светлую руками: ручной выбор обязан побеждать в ОБЕ стороны. */
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --ground: var(--d-ground);
    --surface: var(--d-surface);
    --surface-alt: var(--d-surface-alt);
    --ink: var(--d-ink);
    --ink-mid: var(--d-ink-mid);
    --ink-soft: var(--d-ink-soft);
    --rule: var(--d-rule);
    --rule-strong: var(--d-rule-strong);
    --ring: var(--d-ring);
    --accent: var(--d-accent);
    --accent-soft: var(--d-accent-soft);
    --state-good: var(--d-state-good);
    --state-warn: var(--d-state-warn);
    --state-bad: var(--d-state-bad);
    --state-good-bg: var(--d-state-good-bg);
    --state-warn-bg: var(--d-state-warn-bg);
    --state-bad-bg: var(--d-state-bad-bg);
    --series-1: var(--d-series-1);
    --series-2: var(--d-series-2);
    --series-3: var(--d-series-3);
    --series-1-soft: var(--d-series-1-soft);
    --series-3-soft: var(--d-series-3-soft);
    --shadow: var(--d-shadow);
  }
}

:root[data-theme="dark"] {
  color-scheme: dark;
  --ground: var(--d-ground);
  --surface: var(--d-surface);
  --surface-alt: var(--d-surface-alt);
  --ink: var(--d-ink);
  --ink-mid: var(--d-ink-mid);
  --ink-soft: var(--d-ink-soft);
  --rule: var(--d-rule);
  --rule-strong: var(--d-rule-strong);
  --ring: var(--d-ring);
  --accent: var(--d-accent);
  --accent-soft: var(--d-accent-soft);
  --state-good: var(--d-state-good);
  --state-warn: var(--d-state-warn);
  --state-bad: var(--d-state-bad);
  --state-good-bg: var(--d-state-good-bg);
  --state-warn-bg: var(--d-state-warn-bg);
  --state-bad-bg: var(--d-state-bad-bg);
  --series-1: var(--d-series-1);
  --series-2: var(--d-series-2);
  --series-3: var(--d-series-3);
  --series-1-soft: var(--d-series-1-soft);
  --series-3-soft: var(--d-series-3-soft);
  --shadow: var(--d-shadow);
}

/* ───────────────────────────────────────────────────────────────────────
   2. База — те же правила, что у финансов: свод и блок открываются один
   за другим в одном окне, и разная типографика читалась бы как переход
   на чужой сайт.
   ─────────────────────────────────────────────────────────────────────── */

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--ground);
  color: var(--ink);
  font-family: var(--font-ui);
  font-size: 15px;
  line-height: 1.5;
  font-weight: 400;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3 { margin: 0; font-weight: 600; letter-spacing: -0.01em; }
p { margin: 0; }
a { color: var(--accent); text-decoration-thickness: 1px; text-underline-offset: 2px; }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 3px;
}

button {
  font: inherit;
  color: inherit;
  cursor: pointer;
  border: 1px solid var(--rule-strong);
  background: var(--surface);
  border-radius: 7px;
  padding: 6px 12px;
}
button:hover { background: var(--surface-alt); }

/* Ссылка, стоящая в ряду с кнопками. Выглядит как они намеренно: разница
   «это ссылка, а не кнопка» читателю здесь не нужна. */
.button-link {
  border: 1px solid var(--rule-strong);
  background: var(--surface);
  border-radius: 7px;
  padding: 6px 12px;
  text-decoration: none;
  color: inherit;
  white-space: nowrap;
}
.button-link:hover { background: var(--surface-alt); }

/* ───────────────────────────────────────────────────────────────────────
   3. Каркас страницы
   ─────────────────────────────────────────────────────────────────────── */

.shell {
  max-width: 1180px;
  margin: 0 auto;
  padding: 0 28px 72px;
}

.masthead {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 24px;
  flex-wrap: wrap;
  padding: 44px 0 28px;
  border-bottom: 1px solid var(--rule);
  margin-bottom: 32px;
}
.masthead--slim { padding-bottom: 20px; margin-bottom: 24px; }

.masthead__eyebrow {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--ink-soft);
  font-weight: 500;
  margin-bottom: 6px;
}
.masthead__title { font-size: 30px; letter-spacing: -0.02em; }
.masthead__sub {
  color: var(--ink-mid);
  font-size: 14px;
  max-width: 62ch;
  margin-top: 8px;
}
.masthead__tools { display: flex; gap: 8px; align-items: center; }

/* ───────────────────────────────────────────────────────────────────────
   4. Сетка блоков

   auto-fill, а не auto-fit: при восьми карточках и широком экране
   auto-fit растянул бы последний ряд на всю ширину, и две карточки
   оказались бы вдвое шире шести соседних — сетка читалась бы как
   иерархия, которой в данных нет.
   ─────────────────────────────────────────────────────────────────────── */

.grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(268px, 1fr));
  gap: var(--gap);
}

.tile {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 20px;
  min-height: 152px;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  text-decoration: none;
  color: inherit;
  box-shadow: var(--shadow);
  transition: border-color 120ms ease, transform 120ms ease;
}
.tile:hover { border-color: var(--rule-strong); transform: translateY(-1px); }

@media (prefers-reduced-motion: reduce) {
  .tile { transition: none; }
  .tile:hover { transform: none; }
}

.tile__state {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-weight: 600;
  color: var(--state-good);
  margin-bottom: 2px;
}
.tile__title { font-size: 19px; font-weight: 600; letter-spacing: -0.01em; }
.tile__sub { font-size: 13px; color: var(--ink-mid); line-height: 1.45; }

/* Неготовый блок приглушён, но НЕ выключен: владелец решил, что такие
   карточки кликабельны — иначе они не отвечают на вопрос «а что там
   будет». Приглушение делается фоном и цветом подписи, а не
   прозрачностью: opacity увела бы текст ниже контрастного порога. */
.tile--soon { background: var(--surface-alt); }
.tile--soon .tile__state { color: var(--ink-soft); }
.tile--soon .tile__title { color: var(--ink-mid); }

.colophon {
  margin-top: 40px;
  padding-top: 20px;
  border-top: 1px solid var(--rule);
  color: var(--ink-soft);
  font-size: 13px;
  max-width: 72ch;
}

/* ───────────────────────────────────────────────────────────────────────
   5. Страница «скоро»
   ─────────────────────────────────────────────────────────────────────── */

.notice {
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  padding: 28px;
  max-width: 68ch;
  display: flex;
  flex-direction: column;
  gap: 14px;
  box-shadow: var(--shadow);
}
.notice__tag {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-weight: 600;
  color: var(--state-warn);
}
.notice__lead { font-size: 17px; color: var(--ink); }
.notice__body { font-size: 14px; color: var(--ink-mid); }

/* ───────────────────────────────────────────────────────────────────────
   6. Вход
   ─────────────────────────────────────────────────────────────────────── */

.gate {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}

.gate__card {
  width: 100%;
  max-width: 380px;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  padding: 32px;
  box-shadow: var(--shadow);
}

.gate__eyebrow {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--ink-soft);
  font-weight: 500;
}
.gate__title { font-size: 26px; margin-top: 6px; letter-spacing: -0.02em; }
.gate__sub { color: var(--ink-mid); font-size: 14px; margin-top: 6px; }

.gate__error {
  margin-top: 18px;
  padding: 10px 12px;
  border-radius: 7px;
  background: var(--state-bad-bg);
  border: 1px solid var(--state-bad);
  color: var(--state-bad);
  font-size: 13px;
}

.gate__label {
  display: block;
  margin-top: 22px;
  margin-bottom: 6px;
  font-size: 12px;
  font-weight: 500;
  color: var(--ink-mid);
}

.gate__input {
  width: 100%;
  font: inherit;
  color: var(--ink);
  background: var(--ground);
  border: 1px solid var(--rule-strong);
  border-radius: 7px;
  padding: 9px 12px;
}

.gate__button {
  width: 100%;
  margin-top: 16px;
  padding: 10px 12px;
  font-weight: 600;
  color: #FFFFFF;
  background: var(--accent);
  border-color: var(--accent);
}
.gate__button:hover { background: var(--accent); filter: brightness(1.08); }

.gate__foot {
  margin-top: 20px;
  font-size: 12px;
  color: var(--ink-soft);
  line-height: 1.45;
}

/* ───────────────────────────────────────────────────────────────────────
   7. Узкий экран

   Базовые правила написаны под компьютер — владелец работает днём за
   ним. Сужение обязательно, но вторично.
   ─────────────────────────────────────────────────────────────────────── */

@media (max-width: 620px) {
  .shell { padding: 0 16px 48px; }
  .masthead { padding-top: 28px; }
  .masthead__title { font-size: 25px; }
  .grid { grid-template-columns: 1fr; }
  .notice { padding: 20px; }
}
