/* ==========================================================================
   эТОИР — Design Tokens · v0.2
   Направление: Industrial Swiss (см. docs/DESIGN_SYSTEM.md)
   Единственный источник правды. Подключать ПЕРЕД landing.css.

   v0.2 — ревизия. Ключевое:
   · accent ушёл с #F59E0B (= Tailwind amber-500) на охристый сигнальный #C27C12
   · neutral ушёл с сине-серого на серо-зелёный графит (родословная RAL 7035/7016)
   · primary задавлен по насыщенности: #1D5D9B → #1F5075
   · semantic получил *-ink: старые чипы давали ~3.3:1 и проваливали AA
   · motion: убран экспоненциальный хвост, reveal — вытирание, а не сдвиг
   ========================================================================== */

:root {
  /* ---------- Neutral: графит с зеленцой ----------
     Сине-серый — температура «тёмной темы для разработчиков». Реальная
     промышленная краска и станина уходят в зелень: RAL 7035, RAL 7016.
     Сдвиг едва заметен поштучно и решающе заметен полосой.                    */
  --n-0:   #FFFFFF;
  --n-25:  #FAFBFA;
  --n-50:  #F3F5F3;
  --n-100: #E6EAE7;
  --n-200: #D2D8D3;
  --n-300: #B2BAB4;
  --n-400: #858D87;
  --n-500: #5E665F;
  --n-600: #454C47;
  --n-700: #333934;
  --n-800: #222724;
  --n-900: #171B18;
  --n-950: #0D100E;

  /* ---------- Primary: сталь, а не веб ----------
     #1D5D9B (v0.1) всё ещё звенел «интерфейсным синим». Насыщенность снята,
     светлота убрана — цвет краски на щите управления, не цвет ссылки.         */
  --p-50:  #EDF1F5;
  --p-100: #D6E0E9;
  --p-200: #AEC2D3;
  --p-300: #7C9AB4;
  --p-400: #4C7295;
  --p-500: #1F5075;  /* база бренда */
  --p-600: #17405F;
  --p-700: #123249;
  --p-800: #0D2536;
  --p-900: #091A26;

  /* ---------- Accent: сигнальный оранжевый ----------
     Яркий предупредительный оранж, RAL 2004 / 2009. Кричит громче охры и
     кирпича — держать в узде: 1–2 пятна на экран. Светлее прежних баз,
     поэтому foreground на белом уходит из AA: акцентом красим ПЛАШКУ
     (кнопка = тёмный текст), а не буквы на светлом.                        */
  --a-50:  #FFF2E6;
  --a-100: #FCDABB;
  --a-300: #FDA95F;
  --a-400: #FE8A2A;  /* doc-кнопка, тёмный текст */
  --a-500: #FD7500;  /* база = CTA, тёмный текст ≈7:1 (белый — 2.7, провал) */
  --a-500-rgb: 253, 117, 0;  /* для rgba() подсветок */
  --a-600: #E56600;  /* hover CTA, тёмный текст ≈5.7:1 */
  --a-700: #B85200;

  /* ---------- Semantic: сигнальные цвета ----------
     Родословная ГОСТ 12.4.026 / RAL 6032·1003·3001 — язык площадки.
     Три роли на цвет, и это не педантизм:
       --x      сигнал (точка, полоса, заливка) — работает только как пятно
       --x-bg   подложка чипа
       --x-ink  ТЕКСТ на подложке — потому что сигнал на своём же -bg
                даёт ~3:1 и проваливает AA. Ровно этот баг был в v0.1.        */
  --ok:      #1F7A4C;  --ok-bg:   #E8F2EC;  --ok-ink:   #145635;
  --warn:    #E0A400;  --warn-bg: #F7EDD3;  --warn-ink: #7A5600;
  --stop:    #A82418;  --stop-bg: #F5E5E3;  --stop-ink: #8A1E14;
  --info:    var(--p-500); --info-bg: var(--p-50); --info-ink: var(--p-700);

  /* ---------- Роли ----------
     Компоненты обращаются СЮДА, а не к ступеням. Иначе [data-zone] мёртв.    */
  --bg:            var(--n-0);
  --bg-sunken:     var(--n-50);
  --surface:       var(--n-0);
  --surface-alt:   var(--n-25);
  --text:          var(--n-900);
  --text-muted:    var(--n-500);
  --text-faint:    var(--n-400);
  --border:        var(--n-200);
  --border-strong: var(--n-300);
  --border-faint:  var(--n-100);
  --focus:         var(--p-500);

  /* Бренд КАК ТЕКСТ (ссылка, иконка, outline-кнопка) — отдельная роль от
     бренда КАК ЗАЛИВКА (--p-500). В светлой теме это одно значение, в
     тёмной — принципиально разные: заливка должна держать белый текст,
     а текст — читаться на почти чёрном фоне. Одна ступень не умеет оба. */
  --brand-ink:     var(--p-500);

  /* Чернила на фиксированной заливке. НЕ переворачиваются по теме: оранжевая
     плашка оранжевая в обеих, значит и текст на ней один и тот же. */
  --ink-on-brand:  var(--n-0);
  --ink-on-accent: var(--n-950);

  /* ---------- Типографика ----------
     Golos Text (Paratype) — кириллица здесь родная, а не досыпанный субсет.
     Для продукта, который никогда не выйдет за пределы русского рынка, это
     инженерное решение, а не патриотическое: рисунок Ж, Д, Щ, ять-подобных
     хвостов сделан первым, а не подогнан под латинский скелет.
     Плюс — вес 900, которого у IBM Plex Sans просто нет (потолок 700).
     Mono остаётся IBM Plex Mono: показания прибора.

     ⚠ Субсеты не проверены инструментально. Стек падает на Plex Sans.       */
  --font-sans: 'Golos Text', 'IBM Plex Sans', -apple-system, 'Segoe UI', sans-serif;
  --font-mono: 'IBM Plex Mono', ui-monospace, 'JetBrains Mono', monospace;

  /* Шкала. Кириллица ~на 15% длиннее латиницы → дисплей сдержаннее обычного.
     Но масса добрана весом (900) и трекингом, а не кеглем: у AI-систем
     дисплей выходит лёгким именно потому, что кегль растят, а вес — нет.     */
  --t-display:  clamp(2.75rem, 1.30rem + 5.2vw, 4.75rem);  /* 44 → 76 */
  --t-h1:       clamp(2rem, 1.30rem + 2.5vw, 3.25rem);     /* 32 → 52 */
  --t-h2:       clamp(1.5rem, 1.15rem + 1.4vw, 2.25rem);   /* 24 → 36 */
  --t-h3:       clamp(1.1875rem, 1.05rem + 0.5vw, 1.4375rem); /* 19 → 23 */
  --t-lead:     1.1875rem;  /* 19 */
  --t-body:     1.0625rem;  /* 17 */
  --t-sm:       0.9375rem;  /* 15 */
  --t-xs:       0.8125rem;  /* 13 */
  --t-label:    0.6875rem;  /* 11 — mono, uppercase, разряжен */

  --lh-display: 0.96;   /* плотнее 1 — строки сцепляются в блок, это масса */
  --lh-tight:   1.06;
  --lh-snug:    1.22;
  --lh-body:    1.6;
  --lh-flat:    1.4;

  --tr-display: -0.035em;  /* было -0.025: рыхлый дисплей читается как слабый */
  --tr-head:    -0.02em;
  --tr-body:    0;
  --tr-label:   0.12em;    /* mono-метки разряжены сильнее: это шкала прибора */

  --fw-regular:  400;
  --fw-medium:   500;
  --fw-semibold: 600;
  --fw-bold:     700;
  --fw-black:    900;   /* новое. Дисплей живёт здесь. */

  /* ---------- Ритм: база 4px, вертикаль кратна 8 ---------- */
  --s-1:  0.25rem;  --s-2:  0.5rem;   --s-3:  0.75rem;  --s-4:  1rem;
  --s-5:  1.5rem;   --s-6:  2rem;     --s-7:  3rem;     --s-8:  4rem;
  --s-9:  6rem;     --s-10: 8rem;     --s-11: 12rem;

  /* Отбивка секций — одна на весь сайт. Локальный padding = баг. */
  --section-y: clamp(3rem, 1.5rem + 4vw, 6rem);   /* 48 → 96 */
  --stack-lg:  var(--s-7);
  --stack-md:  var(--s-5);
  --stack-sm:  var(--s-3);

  /* ---------- Сетка ----------
     Лист с полем. Левое поле — не пустота, а рабочая зона: там живут номера
     разделов и mono-аннотации, как на поле чертежа. Симметричный контейнер
     по центру — самый громкий признак сгенерированной страницы.              */
  --grid-max:    1240px;
  --rail:        104px;   /* поле листа. <1100px схлопывается. */
  --grid-narrow: 68ch;    /* проза. ch, а не px: длина строки — это знаки. */
  --grid-cols:   12;
  --gutter:      var(--s-5);
  --gutter-sm:   var(--s-4);

  /* ---------- Радиусы: инструмент, а не игрушка ---------- */
  --r-xs:   2px;
  --r-sm:   3px;
  --r-md:   4px;   /* дефолт. v0.1 держал 6 — всё ещё мягко. */
  --r-lg:   6px;
  --r-pill: 999px; /* НЕ ИСПОЛЬЗУЕТСЯ. Оставлен как явный запрет: пилюля —
                      стартап-тик. Статус на заводе прямоугольный. */

  /* ---------- Тени: почти нет ----------
     Иерархия строится линией и фоном. Тень — только у того, что физически
     «над» полосой.                                                            */
  --sh-none:  none;
  --sh-hair:  0 0 0 1px var(--border);
  --sh-raise: 0 1px 0 rgba(13, 16, 14, 0.04), 0 2px 6px rgba(13, 16, 14, 0.05);
  --sh-pop:   0 6px 20px rgba(13, 16, 14, 0.11), 0 1px 3px rgba(13, 16, 14, 0.07);
  --sh-focus: 0 0 0 2px var(--bg), 0 0 0 4px var(--p-500);  /* двойное кольцо:
                читается и на светлом, и на цветном, и на инверсной полосе */

  /* ---------- Motion: механизм ----------
     v0.1 держал cubic-bezier(0.22,1,0.36,1) — экспоненциальный выброс с
     длинным хвостом. Это и есть «плавное желе»: движение долго крадётся к
     финишу. Привод так не работает — он доезжает и встаёт.                   */
  --e-out:   cubic-bezier(0.2, 0, 0, 1);      /* доезжает и встаёт */
  --e-inout: cubic-bezier(0.65, 0, 0.35, 1);
  --e-step:  steps(6, end);                    /* дискретность: счётчик, шкала */
  --d-fast:  90ms;    /* было 120 */
  --d-base:  160ms;   /* было 200 */
  --d-slow:  260ms;   /* было 320. Потолок. */
  --reveal-x: 6%;     /* вытирание. Сдвиг по Y убран — см. DESIGN_SYSTEM §6 */
}

/* Светлая — база. Объявлено до тёмного блока: у :root и [data-theme] одна
   специфичность, побеждает тот, кто ниже. */
:root { color-scheme: light; }

/* Инверсная зона — не тема, а полоса. Роли переопределяются, компоненты нет. */
[data-zone="inverse"] {
  --bg:            var(--n-950);
  --bg-sunken:     var(--n-900);
  --surface:       var(--n-900);
  --surface-alt:   var(--n-800);
  --text:          var(--n-25);
  --text-muted:    var(--n-300);
  --text-faint:    var(--n-400);
  --border:        rgba(255, 255, 255, 0.12);
  --border-strong: rgba(255, 255, 255, 0.22);
  --border-faint:  rgba(255, 255, 255, 0.07);
  --sh-focus:      0 0 0 2px var(--n-950), 0 0 0 4px var(--a-400);
}

/* ==========================================================================
   ТЁМНАЯ ТЕМА · v0.3 — только app-зона (кабинет)
   --------------------------------------------------------------------------
   Маркетинг остаётся светлым: DESIGN_SYSTEM §1 («экран показывают на
   совещании через проектор»). Тёмная — для того, кто сидит в наряде смену.

   Ставится атрибутом на <html>. Медиазапроса здесь НЕТ намеренно: «системная»
   тема резолвится инлайн-скриптом в <head> (см. static/js/theme.js) в
   явный data-theme. Один блок вместо двух копий по 40 строк.

   ── Как это работает и почему диффа почти нет ──────────────────────────────
   Приложение уже красится ступенями --n-… и --p-… (≈160 употреблений). Поэтому
   тема НЕ переопределяет компоненты — она переопределяет саму лестницу:

   1. НЕЙТРАЛЬ ЗЕРКАЛИТСЯ ПО СЕРЕДИНЕ: n-25↔n-900, n-50↔n-800, n-100↔n-700,
      n-200↔n-600, n-300↔n-500, n-400 сам себе. Любой `var(--n-50)` как
      «светлая подложка» автоматически становится тёмной подложкой.
   2. КРАЯ ЛЕСТНИЦЫ ПРИБИТЫ: --n-0 остаётся белым, --n-950 — почти чёрным.
      В коде они значат не «край градиента», а «белые чернила на цветной
      плашке» / «тёмные чернила на охре». Перевернуть их = сломать ~23 места.
   3. ЛЕСТНИЦА PRIMARY НЕ МОНОТОННА в тёмной, и это не опечатка: каждая
      ступень держит свою РОЛЬ (p-50 = подложка, p-500 = заливка,
      p-600 = hover, p-700 = нажатие), а не позицию в градиенте.
   4. СЕМАНТИКА ПЕРЕСЧИТАНА ЦЕЛИКОМ: светлый --ok-bg #E8F2EC в тёмной был бы
      белым пятном. Правило §8.8 в силе — текст только из --*-ink.

   Контраст считан, не прикинут (§2.1 — там же признание, что в 0.1 числа
   были на глаз). Минимумы на этой полосе:
     text 16.8:1 · muted 8.8:1 · brand-ink 8.7:1 · заливка p-500 под белым
     5.5:1 · все --*-ink на своей подложке ≥ 7.3:1.
   ========================================================================== */
[data-theme="dark"] {
  color-scheme: dark;   /* нативные скроллбары, календари, autofill */

  /* ---------- Нейтраль: зеркало по середине, края прибиты ----------
     ⚠ И ОДНО СОЗНАТЕЛЬНОЕ ОТСТУПЛЕНИЕ ОТ §2. В светлой нейтраль уходит в
     зелень (RAL 7035/7016) — это цвет промышленной краски, и на белой полосе
     он работает. На светлоте 6% тот же оттенок читается не как сталь, а как
     ГРЯЗЬ: у глаза нет опоры, он видит бурый налёт, а не окрашенный металл.
     Поэтому в тёмной нейтраль холодная (синий +4…8 к красному при почти
     нулевой насыщенности). Это не отмена §2, а его продолжение: правило было
     «нейтраль ведёт себя как металл», а не «нейтраль зелёная». */
  --n-0:   #FFFFFF;   /* прибит: чернила на цветной заливке */
  --n-25:  #1A1F27;
  --n-50:  #242A34;
  --n-100: #2E3540;
  --n-200: #3A424E;
  --n-300: #4E5764;
  --n-400: #6C7480;   /* середина — сама себе зеркало */
  --n-500: #9BA4B0;
  --n-600: #C3CAD3;
  --n-700: #DCE1E7;
  --n-800: #E8EBF0;
  --n-900: #F2F4F7;
  --n-950: #0C0F13;   /* прибит: чернила на охре */

  /* ---------- Primary: по ролям, не по градиенту ----------
     Насыщенность на тёмном не снимается, а ДОБАВЛЯЕТСЯ. Светлый #1F5075
     задавлен потому, что на белом листе насыщенный синий звенит. На графите
     тот же приём даёт мёртвую джинсу: цвет теряет и светлоту, и хроматику,
     и кнопка читается как ещё одна серая плашка. Поэтому здесь сталь
     светлее и чище — #2E77AE (0.3) был ровно этой джинсой. */
  --p-50:  #132334;   /* подложка активного пункта, subtle-фон */
  --p-100: #172E45;
  --p-200: #1F4162;   /* тонкая граница */
  --p-300: #3C6E9F;   /* граница outline-кнопки, disabled-заливка */
  --p-400: #5E9AE0;   /* граница в фокусе */
  --p-500: #2A73C4;   /* ЗАЛИВКА. Белый 4.8:1, от полосы отходит 4.0:1 */
  --p-600: #3785DA;   /* hover — светлее, а не темнее: на тёмном свет = ближе */
  --p-700: #21598F;   /* нажатие — утапливается (§8.5), значит темнее */

  /* Бренд как текст. Заливка #2A73C4 буквами на фоне даёт 4.0:1 — мало. */
  --brand-ink: #86B9F0;   /* 9.0:1 на фоне, 7.9:1 на --p-50 */

  /* ---------- Semantic: пересчитан целиком ----------
     Сигналы не просто подняты по светлоте, а СНЯТЫ ПО НАСЫЩЕННОСТИ. Чистый
     #D8402F на почти чёрном горит как индикатор пожарной панели: глаз ловит
     его раньше текста, и полоса выглядит дёшево. §8.2 («цвет — событие»)
     на тёмном требует более тихого сигнала, а не более громкого.
     Роли прежние (§2.1): текст — только из -ink.

     Подложки (-bg) СМЕШИВАЮТСЯ с текущей плоскостью, а не подбираются
     вручную. Ручные #2A2412 / #2B1917 (0.3) — тёмный жёлтый и тёмный красный
     в чистом виде, то есть буквально олива и запёкшаяся кровь: полоса алертов
     читалась как четыре пятна грязи. Смесь «14% сигнала в поверхность»
     остаётся нейтралью с уклоном в сигнал и никогда не мутнеет, а на
     [data-zone] и в светлой теме пересчитывается сама.                       */
  --ok:      #3EA97C;  --ok-ink:   #66D3A3;
  --warn:    #D8A945;  --warn-ink: #EDCB7C;
  --stop:    #C74535;  --stop-ink: #F19A8F;  /* белый на заливке 4.9:1;
                          прежний #D65F50 давал 3.7 — .badge.bg-danger мимо AA */
  --info:    var(--p-500); --info-ink: var(--brand-ink);

  --ok-bg:   color-mix(in srgb, var(--ok)      14%, var(--surface));
  --warn-bg: color-mix(in srgb, var(--warn)    13%, var(--surface));
  --stop-bg: color-mix(in srgb, var(--stop)    16%, var(--surface));
  --info-bg: color-mix(in srgb, var(--p-500)   16%, var(--surface));

  /* Охра на графите горит ярче, чем на белом: та же краска, другая опора.
     Снимаем градус — плашка остаётся сигналом, но перестаёт быть неоном. */
  --a-500: #E08A32;
  --a-500-rgb: 224, 138, 50;
  --a-600: #C9761F;

  /* НО: снятие градуса относится к охре-ЗАЛИВКЕ крупным пятном (--a-500).
     Ступень 400 — это кнопка (`.air-cta`, `.btn-send`, hover `.nav-cta`), и
     0.3.1 увела её в пастель #EDA45C: на графите такая кнопка читается
     бежевой плашкой, а не действием. 400 обязана быть СВЕТЛЕЕ 500, не
     БЛЕДНЕЕ — светлота растёт, насыщенность держится. */
  --a-400: #E8912F;   /* заливка CTA; чернила #0A0D12 на ней 7.9:1 */
  --a-300: #F2A44E;   /* hover: на тёмном светлее = ближе (§ как у --p-600) */

  /* ---------- Плоскости: корпус, а не дно ----------
     Роли не наследуют зеркало. ⚠ И вся лестница ПОДНЯТА на ступень против
     0.3.1 (#0C0F13/#1A1F27/#242A34) — не ради вида, а чтобы стало возможно
     то, чего на тёмном по определению нет: плоскость НИЖЕ страницы.

     В светлой теме [data-zone="inverse"] — единственная тёмная плита на белом
     листе, и это событие. На тёмном 0.3.1 делала её подъёмом, и она садилась
     между фоном и карточкой, то есть переставала быть событием. Событие здесь
     делается наоборот — врезанным экраном, а для врезки нужен корпус: фон
     приложения обязан стоять НАД дном палитры, а не быть им.

     Ступени по-прежнему мелкие (1.15–1.25): на тёмном крупный шаг читается
     как заплата. Иерархию добирает кант, не контраст. */
  --bg:            #1F2530;
  --bg-sunken:     #191E26;   /* фон приложения = КОРПУС, не дно */
  --surface:       #262E39;   /* карточка */
  --surface-alt:   #313A47;   /* шапка карточки, полосатые зоны */
  --text:          #E8EBF0;   /* не чистый белый: #FFF на графите слепит */
  --text-muted:    #9BA4B0;   /* 5.5:1 на карточке */
  --text-faint:    #828A96;   /* 3.9:1; #6C7480 на поднятой плоскости давал 2.9 */

  /* ---------- Границы: белый с альфой, а не серая краска ----------
     Сплошная #333 — главный признак дешёвой тёмной темы: линия «своего»
     цвета не садится на разные плоскости и выглядит грязным швом.
     Полупрозрачный белый берёт подложку под собой и всегда читается как
     кант, а не как ещё один серый. */
  --border:        rgba(255, 255, 255, 0.12);
  --border-strong: rgba(255, 255, 255, 0.24);
  --border-faint:  rgba(255, 255, 255, 0.07);
  --focus:         var(--p-400);

  /* ---------- Тени: на графите размытие не видно ----------
     Светлые --sh-raise/--sh-pop построены на чёрном с alpha 0.04–0.11 —
     на тёмном фоне это ноль. Поднимаем alpha и добавляем светлый кант:
     «над полосой» на тёмном читается кантом, а не размытием.               */
  --sh-raise: 0 0 0 1px rgba(255, 255, 255, 0.06), 0 2px 8px rgba(0, 0, 0, 0.5);
  --sh-pop:   0 0 0 1px rgba(255, 255, 255, 0.09), 0 12px 32px rgba(0, 0, 0, 0.7);
  --sh-focus: 0 0 0 2px var(--bg-sunken), 0 0 0 4px var(--p-400);

  /* ---------- Стекло (liquid glass) ----------
     ⚠ §5 запрещает blur, и запрет остаётся в силе для СВЕТЛОЙ зоны: там он
     вводился против «эппловского» языка на маркетинге. Здесь стекло живёт по
     одному правилу и только по нему:

       стекло разрешено ровно там, где §5 уже разрешает ТЕНЬ —
       у слоя, который физически висит НАД полосой.

     Модалка, дропдаун, тост, offcanvas, sticky-шапка, FAB — да.
     Карточка, таблица, панель — нет: под ними нет фона, который стекло могло
     бы преломить, а поверх данных blur это просто потеря читаемости.

     Стекло — это три вещи вместе, не одна: подложка с альфой, размытие с
     подсветкой насыщенности (иначе цвет под стеклом сереет) и СВЕТЯЩИЙСЯ
     КАНТ сверху. Без канта получается матовое пятно, а не стекло. */
  --glass-bg:     rgba(38, 46, 57, 0.72);   /* = --surface с альфой */
  --glass-bg-deep: rgba(31, 37, 48, 0.88);  /* модалка: под ней читают текст */
  --glass-blur:   saturate(180%) blur(20px);
  --glass-edge:   inset 0 1px 0 rgba(255, 255, 255, 0.10);
  --sh-glass:     var(--glass-edge),
                  0 0 0 1px rgba(255, 255, 255, 0.08),
                  0 16px 40px rgba(0, 0, 0, 0.65);
}

/* Инверсная полоса ВНУТРИ тёмной темы — не инверсия, а подъём.
   [data-zone="inverse"] написан от светлой полосы: он берёт --text из --n-25,
   потому что на белом листе это «почти белый». В тёмной теме лестница
   зеркальна, --n-25 там почти чёрный — и полоса получала чёрный текст на
   тёмном фоне (демо-баннер переставал читаться). Инвертировать нечего:
   страница уже тёмная, поэтому полоса просто поднимается на ступень.
   Значения литеральные, а не через var(--surface-alt): роли переопределяются
   в этом же блоке, ссылка на них дала бы цикл. */
[data-theme="dark"] [data-zone="inverse"] {
  /* НЕ подъём (0.3.1) и НЕ инверсия (светлая тема) — ВРЕЗКА. Полоса уходит
     ниже корпуса на дно палитры: тёмный экран в поднятом корпусе. Это тот же
     смысл, что даёт светлая тема (единственная плита, выпадающая из ритма
     страницы), сделанный единственным доступным на тёмном способом.

     0.3.1 поднимала её на ступень — и она садилась ровно между фоном и
     карточкой, то есть читалась очередной карточкой. Подъём здесь не
     работает в принципе: над картой уже стоят карточки, событием сверху
     полосу не сделать.

     Чернила: muted 7.8:1, faint 5.1:1 (на прежнем #242A34 faint давал 3.0 —
     mono-метки показаний проваливали AA ещё в 0.3.1). */
  --bg:            #0A0D12;
  --bg-sunken:     #0A0D12;
  --surface:       #0A0D12;
  --surface-alt:   #161B22;

  --text:          #E8EBF0;   /* 16.5:1 */
  --text-muted:    #9BA4B0;   /* 7.8:1  */
  --text-faint:    #7C8490;   /* 5.1:1  */

  /* Кант чуть тише корпусного: на дне палитры белая альфа читается сильнее. */
  --border:        rgba(255, 255, 255, 0.10);
  --border-strong: rgba(255, 255, 255, 0.20);
  --border-faint:  rgba(255, 255, 255, 0.06);
  --sh-focus:      0 0 0 2px #0A0D12, 0 0 0 4px var(--a-400);
}

/* Врезка читается кантом по периметру, а не только охряной засечкой сверху:
   на дне палитры разница плоскостей мала, и без канта экран сливается с
   корпусом. `inset`, а не `border` — панель уже несёт border-top 2px охрой,
   настоящая рамка сдвинула бы её содержимое на пиксель. */
[data-theme="dark"] .air-panel {
  box-shadow: inset 0 0 0 1px var(--border);
}

@media (prefers-reduced-motion: reduce) {
  :root { --d-fast: 1ms; --d-base: 1ms; --d-slow: 1ms; --reveal-x: 0%; }
}
