/* ===========================================================================
   Lingo — design system (single source of truth for colour, shape, type, depth)
   Loaded BEFORE style.css. Components must consume the semantic tokens below,
   never raw hex. The five brand colours come from the owner's palette:

     deep sky blue   #5cc8ff   accent / selection / links      -> --sky-*
     lavender veil   #f2d5f8   soft surface / draft state      -> --veil-*
     vintage grape   #493657   ink / primary fill (the anchor) -> --grape-*
     celadon         #afd5aa   success / done                  -> --cel-*
     grapefruit pink #fe6d73   attention / danger              -> --gf-*

   Contrast rules that keep the whole app readable:
     light fill + grape ink   (sky-300 -> 5.7:1, cel-300 -> 6.5:1)
     grape fill + white text  (10.6:1)
     never white text on a light sky/celadon/grapefruit fill.
   =========================================================================== */

:root{
  /* ---- ramps (the brand hex sits at the starred stop) ---------------------- */
  --sky-50:#f0faff;  --sky-100:#dbf3ff; --sky-200:#b9e7fd; --sky-300:#8fdaff;
  --sky-400:#5cc8ff; /* * */            --sky-500:#2cb0f2; --sky-600:#0d91d3;
  --sky-700:#0971a5; --sky-800:#07567e;

  --veil-50:#fcf7fd; --veil-100:#f8e9fb;
  --veil-200:#f2d5f8; /* * */           --veil-300:#e7beef; --veil-400:#d6a3e0;
  --veil-500:#ba80c6; --veil-600:#9d60a9; --veil-700:#794983; --veil-800:#5b3762;

  --grape-50:#f5f2f7; --grape-100:#ebe6ef; --grape-200:#dad2e0; --grape-300:#beb2c7;
  --grape-400:#9b8ba7; --grape-500:#786388; --grape-600:#5f496e;
  --grape-700:#493657; /* * */          --grape-800:#352541; --grape-900:#251a2e;

  /* ── бумага (blox51 #2): НЕЙТРАЛЬ БАЗОВОЙ СХЕМЫ ───────────────────────────
     Виноградная рампа остаётся брендовой (шапка, логотип), но роль нейтрали у
     неё забирает бумага: приложение должно читаться как хорошая полиграфия, а
     не как белый интерфейс. Виноград светит холодно-сиреневым, и на нём любая
     карточка выглядела вклеенной в фон, а не лежащей на нём.
     Синие схемы (scheme2/scheme3) НЕ трогаем — они переопределяют нейтраль у
     себя и остаются холодными. Рельеф и слои от цвета не зависят.
     Ключевые стопы (замер контраста к бумаге --paper-100 #fbf9f5):
       300 — СТОЛ, −11% светлоты от бумаги: с него глаз уверенно видит слой;
       600 — 3.0:1, нейтральный рельс (тише синего, иначе ломается иерархия);
       700 — 4.66:1, подсказки;  800 — 6.4:1 и 5.1:1 на столе, вторичный текст. */
  --paper-50:#fdfcfa;  --paper-100:#fbf9f5; --paper-200:#efe9dc;
  --paper-300:#e2dac9; /* стол */          --paper-400:#cfc3ab; --paper-500:#b3a68f;
  --paper-600:#9c8f7c; --paper-700:#7a6f63; --paper-800:#5f5749;
  --paper-900:#39312a; --paper-950:#241e19;

  --cel-50:#f1f9f0; --cel-100:#e4f3e2; --cel-200:#cee7ca;
  --cel-300:#afd5aa; /* * */            --cel-400:#86bd7f; --cel-500:#60a857;
  --cel-600:#4b8943; --cel-700:#396c33; --cel-800:#2b5426;

  --gf-50:#ffebeb; --gf-100:#ffdbdc; --gf-200:#fdbec0; --gf-300:#fe9a9d;
  --gf-400:#fe6d73; /* * */             --gf-500:#f5474d; --gf-600:#db242a;
  --gf-700:#a92327; --gf-800:#7e2023;

  /* ---- semantic: text ----------------------------------------------------- */
  --ink:var(--paper-900);         /* headings & body, 12.1:1 на бумаге          */
  --ink-strong:var(--paper-950);  /* the one loud line on a screen              */
  --muted:var(--paper-800);       /* secondary text, 6.4:1                      */
  --faint:var(--paper-700);       /* hints, disabled, timestamps, 4.66:1        */
  /* ТЕКСТ, ЛЕЖАЩИЙ НА СТОЛЕ, а не на бумаге. Стол темнее бумаги на 11%, поэтому
     --faint на нём даёт 1.9:1 и просто исчезает (замер, blox51 #2). Любая подпись
     вне карточки — заголовок дня, счётчик над списком, подпись раздела — берёт
     этот тон: 5.1:1 на столе. В синих схемах стол светлый, там он равен --muted. */
  --on-bg:var(--paper-800);
  --on-dark:#fff;

  /* ---- semantic: surfaces ------------------------------------------------- */
  /* ПРАВИЛО СЛОЁВ (blox51 #2): уровня ровно ДВА и они чередуются —
     СТОЛ (--bg, тёмный) и БУМАГА (--card, светлая). Никогда два светлых подряд:
     до этого страница #faf7fb, панель #fff и плашка #fcf7fd отличались на 3-4%,
     и плашка читалась не как листок сверху, а как вмятина внутри. Панель между
     ними заливки больше не имеет — она держится волоском (см. .opane). */
  --bg:var(--paper-300);          /* СТОЛ — на нём лежит всё                    */
  --card:var(--paper-100);        /* БУМАГА — карточки, плашки, шторки          */
  --surface:var(--paper-200);     /* inset panels, wells — углубление в бумаге  */
  --surface-2:var(--paper-200);   /* softer, warmer inset                       */
  --task-plaque:var(--card);      /* плашка таска — тоже БУМАГА, не подложка    */
  --line:var(--paper-400);        /* default border                             */
  /* ВОЛОСОК НЕ МОЖЕТ БЫТЬ ЦВЕТОМ СТОЛА. Он был ровно var(--paper-300), то есть
     байт в байт --bg: карточка, панель или чип, лежащие на столе, рисовали свою
     границу цветом того самого стола — 1.00:1, рамки не существовало вовсе (а её
     просят ~30 мест: .rect, .hub-card, .opane, .rchip, .stat-tile…). Берём стоп
     МЕЖДУ столом и рамкой по умолчанию: волосок темнее и бумаги, и стола, поэтому
     виден на обоих. Замер: на бумаге 1.32→1.51, на столе 1.00→1.14, на подносе
     --surface 1.15→1.31. Гуще брать нельзя — на подносе у плашки есть ещё и тень,
     и жирный контур поверх неё читается двойным краем. Синие и тёмная схемы
     переопределяют волосок у себя, там совпадения со столом не было. */
  --line-soft:color-mix(in srgb, var(--paper-400) 60%, var(--paper-300));
  --line-strong:var(--paper-500);

  /* ---- semantic: accent (sky) --------------------------------------------- */
  /* АКЦЕНТ БАЗОВОЙ СХЕМЫ — ЧЁРНЫЙ (blox51 #3, заход 3.2, решение владельца).
     Небесно-синий был акцентом с самого начала палитры и после перехода на тёплую бумагу
     остался единственным холодным пятном: обводка выбранной группы, заливка выбранного дня,
     рамка на наведении, ссылки — всё это светилось синим посреди баклажана и бумаги.
     «Чёрный» здесь НЕ #000: чистый чёрный на тёплой бумаге читается дырой ровно по той же
     причине, по которой стол не серый, а бежевый. Чёрный этой схемы — её собственные чернила
     --paper-900. Синий никуда не делся: он остаётся брендовым (радуга логотипа, точка рядом с
     ним, радуга плейлиста) и остаётся акцентом ОБЕИХ синих схем — там он свой.
     Акцент как ТЕКСТ на тон темнее корпуса: акцент-текст отличается от обычного не другим
     цветом, а бОльшим количеством чернил. Ссылки при этом подчёркнуты, так что не теряются. */
  --accent:var(--paper-900);      /* обводки, выделение, подчёркивание           */
  --accent-ink:var(--paper-950);  /* акцент ТЕКСТОМ — гуще корпуса, 15.8:1       */
  /* АКЦЕНТ ЛИНИЕЙ (blox52 #5). Обводка на наведении, рамка выбранного, контур
     играющего трека — всё, где акцент работает ЛИНИЕЙ, а не заливкой, берёт этот
     токен, а не --accent. Разница видна только в синих схемах: там акцент — светлый
     Maya, заведённый под заливки (на нём лежит --ink), и линией он давал 2.02:1 на
     белой карточке и 1.53 на столе — наведение мышью не отличалось от покоя. Средняя
     Maya даёт 3.52 и 2.67. В базовой и ночной схемах --accent-deep РАВЕН --accent
     (там акцент и так предельно контрастен), поэтому правка их не касается вовсе. */
  --accent-deep:var(--paper-900); /* иконки-акценты + акцент линией                */
  /* тот же рецепт, что у состояний: пигмент подмешивается В БУМАГУ, поэтому поверхность сама
     следует бумаге своей схемы. Держим их СВЕТЛЫМИ намеренно: на обеих лежит --ink, и стоит
     подмешать гуще — текст на них уйдёт под AA. Стережёт проба «акцентные поверхности». */
  --accent-tint:color-mix(in srgb, var(--paper-900) 9%, var(--card));
  --accent-line:var(--paper-500);

  /* ---- semantic: states ---------------------------------------------------- */
  /* ТИНТ СОСТОЯНИЯ = БУМАГА + 12% ПИГМЕНТА (blox51 #3, заход 3). Раньше каждый тинт
     был самым бледным стопом своей лестницы, то есть пигментом, разбавленным БЕЛЫМ.
     Пока фон был бело-сиреневым, это работало. На тёплой бумаге три состояния из
     четырёх дали к --card 1.01–1.02 при пороге различимости ~1.06 — то есть на листе
     их не стало видно ВООБЩЕ, а лёжа на столе они читались как ещё один чистый лист
     (1.29–1.31 — ровно столько же, сколько у самой бумаги, 1.32). Уцелел один
     грейпфрут, и оттого казалось, что он полез вперёд: он не полез, вокруг стало тихо.
     Замешивать бледный стоп гуще бесполезно — селадон даже вдвое гуще даёт 1.07,
     вуаль 1.04. Поэтому пигментом работает СРЕДНИЙ стоп той же лестницы: ни одного
     нового цвета в проекте не появляется, а все четыре звучат в один голос, 1.12–1.16.
     Основа — var(--card), поэтому тинт сам следует бумаге СВОЕЙ схемы: в синих схемах
     --card белый, и подмес идёт в белое. Отдельных значений для схем не нужно.
     Порог стережёт проба «состояния слышно» в tools/interaction-dom.js. */
  /* ok/done — celadon */
  --ok:var(--cel-500); --ok-ink:var(--cel-700); --ok-line:var(--cel-200);
  --ok-tint:color-mix(in srgb, var(--cel-500) 12%, var(--card));
  /* alert — the ONE "teacher must act" colour (unassigned homework, to-check
     counters, nag frames). Was amber; grapefruit now owns it. */
  --alert:var(--gf-500); --alert-ink:var(--gf-700); --alert-line:var(--gf-200);
  --alert-tint:color-mix(in srgb, var(--gf-500) 12%, var(--card));
  /* white text on a SOLID alert fill needs the darker stop: #fff on gf-500 is only 3.6:1,
     on gf-600 it is 4.9:1. Filled white-on-red badges (к-проверке counter, group nag number,
     edited flag) use this; the tint/dot/nag-frame keep the brand gf-500. */
  --alert-solid:var(--gf-600);
  /* danger — destructive only (delete, graduate) */
  --danger:var(--gf-600); --danger-ink:var(--gf-700);
  /* draft — unpublished work in progress. Was amber (clashed with alert); the
     lavender veil now carries it, so "черновик" and "надо действовать" never
     look alike again. */
  --draft:var(--veil-500); --draft-ink:var(--veil-700); --draft-line:var(--veil-300);
  /* ШТРИХОВКА ЧЕРНОВИКА (blox52 #8) — «лист, который ещё не отпечатан». Кладётся на
     подложку панели черновика косой линейкой поверх --surface; сила ≤4%, потому что это
     ФАКТУРА, а не состояние: заметно гуще — и панель прочиталась бы отключённой.
     Тон — тот же тон тени схемы (--sh-rgb), поэтому штрих тёплый на тёплой бумаге и
     холодный на холодной. Ночью ПЕРЕВОРАЧИВАЕТСЯ (см. ночную схему): по тёмной подложке
     тёмный штрих не виден вовсе — тот же приём, что у обрезного края листа. */
  --draft-hatch:rgba(var(--sh-rgb),.04);
  /* ЛИНОВКА ПУСТОЙ СТРАНИЦЫ (blox52 #15) — горизонтальные линии пустой панели монитора
     («раньше занятий не было»). Как и штриховка черновика — ФАКТУРА, потолок 4%; но тон —
     ЧЕРНИЛА схемы, не тень: линейка ежедневника проведена тем же пером, что и записи, и
     через var(--ink) сама переворачивается ночью (светлые линии по тёмной бумаге) — своей
     копии в блоке схем не нужно (ловушка §11 не срабатывает: роль собрана из роли). */
  --page-rule:color-mix(in srgb, var(--ink) 4%, transparent);
  --draft-tint:color-mix(in srgb, var(--veil-500) 12%, var(--card));

  /* ---- semantic: homework task types (student rectangles) ------------------ */
  /* ИЕРАРХИЯ ОБЯЗАТЕЛЬНА: «нужна сдача» должно быть ГРОМЧЕ, чем «просто сделать».
     На бумаге это проверяется контрастом к --card: sky-700 даёт 5.9:1, paper-600 —
     3.0:1. Тёмный нейтральный стоп (paper-800, 6.4:1) кричал бы громче синего —
     ровно эта ошибка всплыла на замере (blox51 #2), не повторять. */
  --task-plain:var(--paper-600);  /* nothing to hand in — тише                   */
  --task-sub:var(--sky-700);      /* has a turn-in — громче                      */
  /* theme-frame outline colour (blox26 #5): ONE token per scheme so the unified
     frame recolours with the palette. Scheme2 — ink; scheme3 — the header's
     deep-Maya right edge (overrides below).
     blox51 #4: базовая схема была --paper-400 — тот же тон, что и стол под листом,
     поэтому скобка темы на снимке ПРОПАДАЛА (комментарий обещал grape, но его тут
     никогда не было). Теперь --ink: та же линия, что и в графитовой схеме, 12.1:1
     на бумаге. Рамка темы — единственный контур, который группирует таски, и он
     обязан быть виднее волоска самой карточки. */
  --frame-line:var(--ink);
  /* challenge — the ONE gold in the product (blox15 #6). A challenge is a task
     everybody can see everybody do; gold is what makes it read as a prize, not
     as an alert. Nothing else may use it. */
  /* золото потемнело с #c9962c до #b07d16: на белом оно давало 2.3:1 и на тёплой
     бумаге терялось совсем; теперь 3.45:1 — приз виден, но тише синего рельса. */
  --gold:#b07d16; --gold-line:#eddcae;
  --gold-tint:color-mix(in srgb, var(--gold) 12%, var(--card));
  /* чернила углублены с #8a6412: на новом тинте старые давали 4.49:1 — на волосок
     ниже AA; теперь 5.15:1, и заодно 4.54:1 на золотой рамке вместо 3.95:1. */
  --gold-ink:#7f5b10;

  /* Файловое окно «Классный проводник» (blox33 #1, story 7-bis; перекрашено blox51 #10).
     Тут проходит ГРАНИЦА между чужим и своим, и она проведена по одному признаку:
       ПОВЕРХНОСТЬ — яндексовская. Белая рабочая область, серая обвязка, красная «Я»:
       чужой диск обязан читаться как чужой диск, поэтому это СЫРОЙ бренд-hex,
       сознательно вне блока схем (как --gold) — окно выглядит так в любой схеме.
       КОНТРОЛЫ — НАШИ. Заливка кнопки, выделение, обводка берут палитру ТЕКУЩЕЙ схемы
       (владелец, blox51 #10: «все кнопки в проводнике — к текущей палитре»). Раньше
       и они были яндексовскими, и посреди баклажана с бумагой горел чужой синий.
     Применяется scoped на .plscreen / .exp-shutter (см. explorer.css — там весь скин). */
  --ya-surface:#ffffff;     /* рабочая область файлов — белая, как у Диска */
  --ya-soft:#f4f5f7;        /* серые полосы: шапка окна, адресная строка, тулбар */
  --ya-line:#e6e7ea;        /* тонкие границы-волоски */
  --ya-red:#fc3f1d;         /* фирменная красная «Я» (playlist.css, .pl-ya) */
  /* СИНИЙ ПРОВОДНИКА — единственный цвет контролов, который остался синим, и это
     решение владельца: синий есть в палитре (знак Lingo, радуга плейлиста), поэтому
     ссылки окна менять не потребовалось. Но синий теперь НАШ, а не яндексовский
     #2b5fd9: sky-700 даёт 5.4:1 на белой области файлов. Синие схемы переопределяют
     его на собственные акцентные чернила — см. блок схем ниже. */
  --exp-link:var(--sky-700);

  /* ---- component role tokens (blox26) --------------------------------------
     Added so components speak ROLES, never raw ramp stops (var(--grape-500)…).
     `npm run check` now BLOCKS a raw ramp reference outside this file. Each token
     points at a ramp stop; a colour scheme re-skins the app by overriding the
     token here — so all screens follow the 5-colour palette from ONE place. */
  --muted-strong:var(--paper-900);  /* label a shade darker than --muted; AA on --fill-soft */
  --fill-soft:var(--paper-200);     /* subtle neutral fill (tab track, hover well, chip) — kept
                                       distinct from --surface so a hover over a well still reads */
  --line-mid:var(--paper-400);      /* input & visible borders, between --line and --line-strong */
  --primary:var(--paper-900);       /* dark anchor FILL under white text: selected tab, dragged
                                       lesson tile, pool play button (the sky accent is too light) */
  --primary-strong:var(--paper-950);/* darkest chrome fill: toasts, drag readout */
  /* ЯКОРЬ СХЕМЫ (blox51 #3, заход 3.1) — СПЛОШНАЯ тёмная заливка под белым текстом:
     кнопка-заливка, вкладка выбранного учителя, выбранный сегмент, полоса загрузки,
     акцент плеера, перетаскиваемый чип урока. Раньше эту роль звали --accent-solid и
     она была НЕБЕСНО-СИНЕЙ во всех трёх схемах (базовая sky-700, обе синих #12689e):
     схема перекрашивала шапку и первичную кнопку, а всё остальное сплошное оставалось
     синим — в баклажановой схеме синева бралась из ниоткуда. Теперь у каждой схемы
     ОДИН якорь, тот же, что в шапке: баклажан · графит · Maya.
     Якорь действует и в окне проводника: чужой там только ФОН, кнопки наши (blox51 #10). */
  --anchor:var(--grape-700);        /* баклажан; белый текст 10.6:1                    */
  /* ЯКОРЬ, РАБОТАЮЩИЙ ЧЕРНИЛАМИ (заголовки плиток хаба .hub-t, blox51 #4). В светлых схемах
     это тот же цвет — светлая бумага позволяет ОДНОМУ тону нести и белую подпись на себе, и
     себя на бумаге. Тёмная схема (blox51 #11) сделала это невозможным арифметически: чтобы
     белый на якоре давал 4.5:1, якорь должен быть темнее L=0.18, а чтобы сам якорь читался на
     ночной бумаге — светлее L=0.25. Одного значения на два конца не существует, поэтому роль
     разъехалась на два токена. Светлые схемы держат их равными и ничего не замечают. */
  --anchor-ink:var(--anchor);
  --accent-fill:color-mix(in srgb, var(--paper-900) 16%, var(--card)); /* шаг гуще --accent-tint */
  /* ВЫДЕЛЕНИЕ ТЕКСТА МЫШЬЮ — свой токен, а не --accent-fill. Раньше ::selection брал
     заливку, и это давало 1.34:1 к бумаге: протащил мышью по абзацу — и не видно, что
     выделено. Отдельный токен нужен потому, что у заливки другая работа: на ней лежат
     свои пузыри чата и выбранные записи, её стережёт проба «акцентные поверхности»
     (--ink на ней обязан держать AA), и подкрутить её ради выделения значит подвинуть
     полдюжины поверхностей. Тот же рецепт, только пигмента 26% вместо 16%: 1.63:1 к
     бумаге в базовой, 1.99 в тёмной, при этом текст на выделении 7.4 и 6.4. */
  --sel-bg:color-mix(in srgb, var(--accent) 26%, var(--card));
  --ok-solid:var(--cel-700);        /* green FILL under white text — cel-600 was 4.2:1, under AA */
  --ok-fill:color-mix(in srgb, var(--cel-500) 22%, var(--card));   /* done fill, гуще --ok-tint */
  --alert-fill:color-mix(in srgb, var(--gf-500) 22%, var(--card)); /* drag-over, trash — гуще --alert-tint */
  --alert-strong:var(--gf-700);     /* dark red FILL under white text: recording-on, count-badge hover */
  /* объявление — a STANDING note, deliberately lavender so it never reads as a state
     (draft/alert/done). Fixed across schemes: veil is not a re-skinned family. */
  --note-bg:color-mix(in srgb, var(--veil-500) 12%, var(--card));
  --note-line:var(--veil-300); --note-ink:var(--veil-700);

  /* ---- shape --------------------------------------------------------------- */
  /* ЛЕСТНИЦА РАДИУСОВ (blox51 #3, заход 5). Правило одно: РАДИУС ПО РАЗМЕРУ ПРЕДМЕТА —
     чем крупнее вещь, тем мягче её угол. До этого в public/*.css лежало 165 радиусов числом,
     СЕМНАДЦАТЬ разных значений от 1 до 999, против 38 через токен. Значения при этом не были
     случайны: 9px стоял на мелких контролах (чип, тег, строка, «⋯»), 12px — на контейнерах
     (карточка, панель, поле). То есть правило соблюдалось интуитивно, но одна и та же роль
     записывалась то девяткой, то десяткой, то двенадцаткой, и соседние предметы одного класса
     скруглялись по-разному без причины. Ступени названы по КЛАССУ предмета:
       2xs — полоска, точка, прогресс (браузер всё равно режет радиус до половины высоты);
       xs  — мелкий контрол: кнопка-иконка, бейдж, ползунок;
       sm  — чип, тег, строка списка, сегмент;
       md  — карточка, панель, поле ввода, коробка;
       lg  — крупный контейнер, шторка;
       xl  — лист, модалка;  2xl — гигант;  pill — таблетка. */
  --r-2xs:4px; --r-xs:8px; --r-sm:10px; --r-md:14px; --r-lg:18px; --r-xl:24px; --r-2xl:30px;
  --r-pill:999px;

  /* ---- depth — тень всегда в тон поверхности, никогда серая ----------------
     Тон вынесен в ОДИН токен: без него тёплая тень бумаги протекла бы в синие
     схемы, где поверхность холодная (та же §11-ловушка, что с --card). Схема
     переопределяет только --sh-rgb, все пять теней следуют за ним сами.
     Третий слой (дальнее рассеяние) добавлен к --sh-1 и --sh-2: он и создаёт
     ощущение «лежит», которого не даёт пара контакт+ближний. */
  --sh-rgb:70,55,35;              /* тёплый — тон бумажного стола               */
  /* ВОЛНА ОТ КАСАНИЯ — РЕЖИМ НАЛОЖЕНИЯ (blox52 #8). На бумаге волна работает как
     чернила: она УМНОЖАЕТ поверхность (краска впитывается в лист, тон и зерно бумаги
     видны сквозь неё), а не кладёт полупрозрачное пятно сверху. Роль живёт здесь, а не
     у .ripple, потому что она СХЕМНАЯ: ночью бумага тёмная, чернила светлые, и
     умножение светлым по тёмному не даёт ровно ничего — ночь переопределяет на normal.
     Залитые роли кнопок гасят её у себя (см. .btn--primary в style.css): у них волна
     белая, а умножение белым — тождество. */
  --ripple-blend:multiply;
  --sh-1:0 1px 1px rgba(var(--sh-rgb),.05), 0 2px 4px rgba(var(--sh-rgb),.05),
         0 8px 16px -12px rgba(var(--sh-rgb),.28);
  --sh-2:0 1px 2px rgba(var(--sh-rgb),.05), 0 5px 12px rgba(var(--sh-rgb),.06),
         0 16px 28px -18px rgba(var(--sh-rgb),.40);
  --sh-3:0 3px 8px rgba(var(--sh-rgb),.07), 0 12px 28px rgba(var(--sh-rgb),.10);
  --sh-4:0 10px 24px rgba(var(--sh-rgb),.12), 0 30px 60px rgba(var(--sh-rgb),.16);
  /* вдавливание кнопки. Раньше рядом жила --sh-inset (мягкая внутренняя тень «колодца»), но
     колодец в этом проекте выражен ЦВЕТОМ (--surface), а не тенью, и последнее её место — окно
     согласия — оказалось не колодцем, а листом на столе (blox52 #4). Токен снят как остаток. */
  --sh-press:inset 0 2px 5px rgba(var(--sh-rgb),.30);
  /* ФОКУС-КОЛЬЦО — ДВУСЛОЙНОЕ (зазор + контур). Одним полупрозрачным слоем оно не
     работает: кольцо ложится на ЧЕТЫРЕ разных фона (бумага, стол, тёмная шапка,
     цветная заливка кнопки), и любой один цвет на каком-то из них исчезает —
     в синих схемах прежнее rgba(123,190,234,.45) давало на белом 1.35:1, то есть
     с клавиатуры не было видно ВООБЩЕ, где ты находишься.
     Внутренний слой — 2px цветом БУМАГИ: он отрезает кольцо от самого предмета,
     и он же и есть видимая часть кольца на тёмной шапке. Внешний — 2px тёмным
     фирменным (--ring-c): он и есть кольцо на светлых фонах (12.1:1 на бумаге,
     9.2:1 на столе в базовой; 6.0 и 4.6 в синих; в тёмной схеме наоборот — светлый
     контур, 10.5 и 13.3).
     Третьим слоем ОБЯЗАТЕЛЬНО идёт --sh-1: :focus-visible ставит box-shadow, а он
     заменяет тень целиком — без этой строки кнопка и чип группы теряли бы свою
     тень покоя ровно в момент фокуса и на кадр «проваливались» в лист. */
  --ring-c:var(--accent);
  --ring:0 0 0 2px var(--card), 0 0 0 4px var(--ring-c), var(--sh-1);

  /* ---- ТИСНЕНИЕ (letterpress) — материал самой плашки (blox51 #3, заход 2) --
     Плашка перестала быть «прямоугольником с цветной границей слева» и стала
     ЛИСТОМ БУМАГИ, в который рельс ВДАВЛЕН. Два разных эффекта, и их нельзя
     путать:
       --emb        лежит на плашке: светлый бортик по верхней грани листа +
                    едва заметная тень по нижней. Это то, что делает край
                    бумаги видимым, когда лист лежит на столе такого же тона.
       --emb-groove лежит на рельсе (::before): тень ВНУТРИ канавки сверху-слева,
                    отблеск снизу-справа, и белый бортик СНАРУЖИ снизу — бумага
                    приподнялась по краю продавленной канавки.
     ГЛУБИНА (blox51 #4): дно канавки было .5 — на крупном снимке рельс сидел в
     чёрной борозде, и тиснение читалось как грязь, а не как оттиск. Ослаблено до
     .32 (и .28 в холодных схемах): оттиск остался, тень перестала спорить с самим
     цветом рельса. Смотреть только через `shot.js --el ".oent" --dpr 4`.
     Схемы переопределяют --emb-lo: тёплая грязь в канавке на холодной бумаге
     читается как пятно, а не как тень (та же §11-ловушка, что с --card). */
  --emb-hi:rgba(255,255,255,.95);         /* бортик листа — верхняя грань бумаги  */
  --emb-lo:rgba(20,12,4,.32);             /* дно канавки под рельсом              */
  --emb-edge:rgba(var(--sh-rgb),.18);     /* волосок по краю канавки              */
  --emb:inset 0 1px 0 var(--emb-hi), inset 0 -1px 0 rgba(var(--sh-rgb),.05);
  --emb-groove:inset 2px 2px 2.5px var(--emb-lo),
               inset -1px -1px 1.5px rgba(255,255,255,.28),
               0 1px 0 var(--emb-hi),
               0 0 0 .5px var(--emb-edge);
  /* пигмент рельса подмешивает к --rail тень сверху и отблеск снизу. Сам градиент
     (--emb-rail) живёт НЕ здесь, а в style.css на самой плашке: токен на :root
     подставил бы var(--rail) от :root, где рельса нет, и фон обнулился бы. */
  --emb-deep:#000;                        /* верх рельса — в тени борта канавки  */
  --emb-lift:#fff;                        /* низ рельса — отражённый свет        */

  /* ---- ЛИСТ — ОДИН РЕЦЕПТ НА ВСЮ БУМАГУ (blox52 #4, пп. 1-2) ---------------
     Тиснение придумали в blox51 для плашки таска — и там оно и осталось. Панель,
     плитка кабинета, всплывашка настроек и окно согласия собирались КАЖДАЯ по
     своей тени (--sh-1 / --sh-2 / --sh-3 / --sh-4, а окно согласия — внутренней), и светлого
     бортика по верхней грани у них не было вовсе: эффект «лист имеет толщину»
     был придуман и оплачен, но роздан одному предмету из пяти.
     Рецепт теперь ОДИН, и слоёв в нём три, всегда в этом порядке:
       1. ОБРЕЗНОЙ КРАЙ (--sheet-edge) — полупиксельный контур в тон тени. У
          настоящей бумаги край — это не тень, а ТОРЕЦ: без него лист выглядит
          нарисованным, с ним — вырезанным. Полпикселя на экране БЕЗ удвоения
          точек округляется до целого и стало бы заметной рамкой, поэтому
          прозрачность взята вдвое ниже той, при которой контур читается линией:
          на обычном экране это волосок на грани видимости, на retina — торец.
       2. ТИСНЕНИЕ (--emb) — светлый бортик по верхней грани и тень по нижней.
       3. ТЕНЬ (--sh-N) — ступень подъёма, и выбирают именно её: 1 — лист лежит,
          2 — приподнят, 3 — всплыл над содержимым, 4 — модалка.
     Два частных случая, оба по делу, а не «ещё один рецепт»:
       --sheet-pop  — бортик ОСЛАБЛЕН: всплывашка настроек висит вплотную под
                      тёмной шапкой, и 95%-белый бортик блестел бы там полосой;
       --sheet-rise — тень уходит ВВЕРХ: шторка поднимается снизу, а свет
                      по-прежнему падает сверху.
     Инвариант «у всех листов один рецепт» стережёт «рецепт листа» в
     `npm run check` и проба «материал бумаги» в tools/interaction-dom.js. */
  --sheet-edge:0 0 0 .5px rgba(var(--sh-rgb),.12);
  /* ЗАТЕМНЕНИЕ ПОД МОДАЛКОЙ. Тоже тон тени схемы, но своим токеном и своей плотностью:
     цвет тени — не чёрный, а средний тёплый (70,55,35), и той же .52, что стояла у зашитого
     тёмно-фиолетового числа, он затемняет ЗАМЕТНО слабее (стол уходил бы в 151, а не в 124).
     .68 возвращает прежнюю силу, и теперь она одна на оба места, где накладка встречается. */
  --scrim:rgba(var(--sh-rgb),.68);
  --emb-hi-soft:rgba(255,255,255,.45);    /* бортик под тёмной шапкой — вполсилы */
  --emb-pop:inset 0 1px 0 var(--emb-hi-soft), inset 0 -1px 0 rgba(var(--sh-rgb),.05);
  --sheet-1:var(--sheet-edge), var(--emb), var(--sh-1);
  --sheet-2:var(--sheet-edge), var(--emb), var(--sh-2);
  --sheet-3:var(--sheet-edge), var(--emb), var(--sh-3);
  --sheet-4:var(--sheet-edge), var(--emb), var(--sh-4);
  --sheet-pop:var(--sheet-edge), var(--emb-pop), var(--sh-4);
  --sheet-rise:var(--sheet-edge), var(--emb), 0 -8px 34px rgba(var(--sh-rgb),.18);

  /* ---- ПЛАНКА ШАПКИ (blox52 #5) --------------------------------------------
     Шапка — НЕ лист. Рецепт листа выше говорит «бумага лежит на столе и чуть
     приподнята»; шапка же прибита к верхнему краю, и бумага уезжает ПОД неё.
     Это другой предмет — тяжёлая тёмная планка, — и собран он тремя слоями,
     ни один из которых не повторяет --sheet-*:
       ВОЛОСОК (--plank-lip) — светлая нить по нижней кромке, отблеск на торце
         планки. Он же и есть «материал» шапки: у залитой кнопки фаска (--bevel)
         была, а у шапки не было ничего, и рядом они выглядели сделанными из
         разного. Волосок ПОСТОЯНЕН при любой прокрутке: это торец, а не тень.
       ЛИНИЯ КОНТАКТА (--plank-line) — чёткая тёмная черта БЕЗ размытия прямо
         под кромкой: место, где планка касается стола. Без неё край шапки
         читался обрывом заливки, а не краем предмета.
       КОРОТКАЯ ТЕНЬ (--plank-cast) — 6px рассеяния вместо 28 у --sh-2. Длинная
         размытая тень означает «предмет высоко над столом», то есть парение, —
         а планка прижата.
     ПЛОСКАЯ В НУЛЕ (--plank-flat). Пока страница не прокручена, бумага начинается
     вплотную под шапкой и тени взяться неоткуда — она нужна ровно тогда, когда
     под планку что-то уехало. Слоёв здесь СТОЛЬКО ЖЕ и они той же формы, меняется
     только прозрачность двух нижних: браузер умеет плавно переводить одну тень в
     другую лишь при совпадающем числе слоёв, иначе переход был бы рывком.
     Переключает их привязка к прокрутке в style.css (см. @supports у header).
     СВЕТ В УГЛУ (--hdr-sheen) — лёгкое пятно света сверху слева, чтобы заливка
     читалась поверхностью, а не краской. Потолок в 8% белого назван судьёй и
     не случаен: на шапке лежит БЕЛЫЙ текст, а самая светлая из четырёх шапок
     («Lingo», #1a75b0) держит его на 4.98:1 при норме 4.5 — запаса нет вовсе.
     Поэтому пятно посажено в УГОЛ и гаснет раньше, чем доходит до логотипа, а
     СИЛА света у «Lingo» своя (см. её блок ниже): рецепт один на все схемы,
     переопределено только число, и ровно по замеру. Числа меряются пробой
     «планка шапки» по пикселям снимка, а не выводятся из токенов: свет — это
     градиент ПОВЕРХ --grad-header, и в токенах его не видно. */
  --plank-lip:inset 0 -1px 0 rgba(255,255,255,.10);
  --plank-line:0 1px 0 rgba(var(--sh-rgb),.42);
  --plank-cast:0 4px 6px -2px rgba(var(--sh-rgb),.30);
  --plank:var(--plank-lip), var(--plank-line), var(--plank-cast);
  --plank-flat:var(--plank-lip), 0 1px 0 rgba(var(--sh-rgb),0),
               0 4px 6px -2px rgba(var(--sh-rgb),0);
  --hdr-sheen-a:.08;
  --hdr-sheen:radial-gradient(38% 190% at 3% -30%,
              rgba(255,255,255,var(--hdr-sheen-a)) 0%, rgba(255,255,255,0) 68%);

  /* ---- ГРАВИРОВАННАЯ ЛИНЕЙКА (blox52 #4, п.3) ------------------------------
     То же тиснение, что на карточке, но в одну строку: волосок + светлый блик
     ПОД ним. Разделитель секции в настройках, шапка панели и строка списка
     перестают быть просто серой чертой и читаются как оттиск в бумаге.
     Форм две, потому что блик всегда лежит СНИЗУ от линии, а сама линия бывает
     и по верхней грани предмета (--rule-t: блик уходит внутрь), и по нижней
     (--rule-b: блик уходит наружу). Ставить их на предмет, у которого уже есть
     своя тень, нельзя — box-shadow заменяет её целиком; такому предмету линейка
     дописывается в его собственный рецепт. */
  --rule-t:inset 0 1px 0 var(--emb-hi);
  --rule-b:0 1px 0 var(--emb-hi);

  /* ---- МАТЕРИАЛ СТОЛА: ЗЕРНО И СВЕТ КОМНАТЫ (blox52 #4, пп. 4-5) -----------
     Стол был ровной заливкой — на широком экране это большое пустое поле, по
     которому глазу не за что зацепиться, а ровная заливка читается «интерфейс»,
     а не «картон».
     ЗЕРНО (--grain-img) — процедурный шум, нарисованный ПРЯМО ЗДЕСЬ фильтром
     feTurbulence. Никаких картинок и фотографий текстуры: снимок бумаги — это
     уже скевоморфизм, он стареет и весит. Плитка 128×128 рисуется в свой
     натуральный размер (background-size = размеру svg): любое масштабирование
     плитки и есть источник муара на телефоне. Потолок непрозрачности — 4%,
     стоит 3.5%: выше зерно начинает читаться как грязь на экране.
     СВЕТ КОМНАТЫ (--room-o) — лампа над столом: сверху светлее, к нижним углам
     ровный тон. Сделан ПЛЮСОМ К ЦЕНТРУ СВЕТА, а не минусом к краям, и это не
     вкус, а замер. Затемнение к краям (как просил судья) отнимает яркость у
     СТОЛА, а на столе лежит текст --on-bg: в базовой схеме у него 5.12:1, а в
     синих — 4.72:1 при норме 4.5, то есть запаса нет вовсе, и вуаль в 7% уводила
     подпись на столе под норму (4.18:1). Свет, добавленный сверху, работает в ту
     же сторону глазом и в БЕЗОПАСНУЮ сторону по контрасту: тёмный текст на чуть
     более светлом столе читается только лучше. Цвет света — не белый, а
     var(--card): бумага СВОЕЙ схемы, поэтому лампа тёплая на тёплом столе,
     холодная на холодном и виноградная ночью (белый выбелил бы тёплый стол).
     Оба слоя ПРИБИТЫ К ЭКРАНУ (position:fixed у псевдоэлементов ниже), а не к
     странице: иначе на длинной странице градиент растянулся бы вместе с
     содержимым и стал бы частью содержимого, а не освещением комнаты. */
  --grain-o:.035;
  --room-o:20%;
  --grain-img:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='128' height='128'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3CfeComponentTransfer%3E%3CfeFuncR type='linear' slope='2' intercept='-.5'/%3E%3CfeFuncG type='linear' slope='2' intercept='-.5'/%3E%3CfeFuncB type='linear' slope='2' intercept='-.5'/%3E%3CfeFuncA type='discrete' tableValues='1'/%3E%3C/feComponentTransfer%3E%3C/filter%3E%3Crect width='128' height='128' filter='url(%23g)'/%3E%3C/svg%3E");

  /* ---- type ---------------------------------------------------------------- */
  /* Onest (self-hosted, see fonts/onest.css). The system stack stays as the fallback
     that renders while the woff2 loads. */
  --font:'Onest',-apple-system,BlinkMacSystemFont,"Segoe UI",system-ui,Roboto,
         "Helvetica Neue",Arial,sans-serif;
  /* ЛЕСТНИЦА ТЕКСТА (blox51 #3, заход 4). Ступеней девять, и они не выбираются «на глаз»
     каждый раз: до этого в style.css лежало 225 размеров числом — ВОСЕМНАДЦАТЬ разных
     значений от 10 до 38, включая 12.5 и 13.5. Это не шкала, а россыпь: глаз не находит
     ритма, потому что ритма нет, и экран читается как «аккуратно, но без системы».
     Промежуточные значения СХЛОПНУТЫ, а не узаконены: 13 и 14 рядом различаются на глаз
     не как две ступени, а как ошибка. Направление схлопывания выбиралось по РОЛИ, а не по
     близости числа: подписи, метки и кнопки ушли вниз в --fs-sm, а то, что человек читает
     предложениями (текст ошибки, пустое состояние, предупреждение, тост), — вверх в --fs-md. */
  --fs-2xs:11px; --fs-xs:12px; --fs-sm:13px; --fs-md:15px; --fs-lg:17px;
  --fs-xl:20px;  --fs-2xl:24px; --fs-3xl:30px; --fs-4xl:38px;
  /* ПОЛЕ ВВОДА — 16px это НЕ ступень лестницы, а заслон: Safari на iOS зумит страницу при
     фокусе в поле со шрифтом меньше 16px и обратно не отзумливает. Ниже по файлу тот же
     заслон стоит глобально на @media (pointer:coarse), этот токен держит тот же размер и
     на десктопе, чтобы поле не прыгало между устройствами. Отдельное имя — чтобы никто не
     «причесал» 16 к 15 ради красоты лестницы и не сломал ввод на телефоне молча. */
  --fs-input:16px;
  /* ИКОНКИ-ГЛИФЫ. Часть «размеров шрифта» в проекте — вовсе не текст, а размер эмодзи или
     знака (× закрыть, ⋯ меню, ▶ play, стрелка карусели). Их нельзя ставить на текстовую
     лестницу: подпись и знак живут по разным законам — подпись должна читаться, знак должен
     попадать в свою кнопку. Три ступени, шаг 4px. Векторные иконки (.ic) сюда не относятся:
     они меряются в em и следуют за своей подписью сами. */
  --ic-sm:14px; --ic-md:18px; --ic-lg:22px;
  /* КНИЖНЫЙ ВЕС (blox52 #6, пятая пачка судьи). В наборе не было «читательского» веса вообще:
     сто с лишним правил в 700, шесть десятков в 800 и ровно три в 400 — экран читался как
     афиша, а не как документ, потому что «это читают» и «на это нажимают» были написаны
     ОДНИМ весом. Onest переменный (100…900), лишний вес ничего не стоит по весу страницы.
     450, а не 400: 400 у переменного шрифта — это то, что браузер и так ставит по умолчанию,
     то есть НЕ выбор, а его отсутствие; полступени вверх заметно держат мелкий кегль на
     бумаге и не дают строке «поплыть» в ночной схеме, где светлая буква на тёмном визуально
     тоньше. Кому он достаётся — закрытый реестр в tools/check.js (секция «книжный вес»):
     абзацы согласия, описания плиток кабинета, текст задания, тело объявления, сообщение в
     чате, запись досье. Подписи, кнопки, заголовки и ярлыки остаются жирными — иначе разница
     снова исчезнет, только в другую сторону.
     ЕСТЬ МЕСТО, ГДЕ ЕГО СОЗНАТЕЛЬНО НЕТ: текст, лежащий прямо на СТОЛЕ (у экрана согласия
     своей заливки нет). Там буква тоньше и фон темнее одновременно, поэтому подзаголовок
     .cs-sub оставлен на 600 — замеры в Blox_done52. */
  --fw-read:450;
  --lh-tight:1.2; --lh:1.45;
  --tracking-tight:-.015em;   /* iOS headings are slightly negative-tracked */
  --tracking-caps:.06em;

  /* ---- rhythm --------------------------------------------------------------- */
  --sp-1:4px; --sp-2:8px; --sp-3:12px; --sp-4:16px; --sp-5:20px; --sp-6:24px;
  --sp-7:32px; --sp-8:44px;

  /* ---- motion --------------------------------------------------------------- */
  --ease:cubic-bezier(.32,.72,0,1);       /* iOS-ish: fast out, gentle settle */
  /* ПРУЖИНА — кривая с ПЕРЕЛЁТОМ: элемент проскакивает конечную точку и мягко
     возвращается. Это и есть «сочность» отпускания: палец ушёл — поверхность
     отпрыгнула. Число взято из каталога silk-design («playful overshoot»),
     не подобрано на глаз. Применять ТОЛЬКО к отпусканию (возврату в покой):
     на само нажатие перелёт не ставят — вдавливание должно быть сухим и быстрым. */
  --ease-spring:cubic-bezier(.22,.68,0,1.2);
  --t-fast:.14s; --t:.22s; --t-slow:.34s;
  --t-press:.08s;   /* вдавливание — заметно быстрее возврата */
  --t-spring:.18s;  /* возврат с перелётом */

  /* ---- signature gradients --------------------------------------------------- */
  /* the playlist's identity: the full palette, left to right */
  --grad-playlist:linear-gradient(100deg,var(--sky-400) 0%,#a8b0ef 34%,var(--veil-300) 55%,var(--gf-400) 100%);
  --grad-playlist-v:linear-gradient(180deg,var(--sky-400),#a8b0ef,var(--veil-300),var(--gf-400));
  --grad-header:linear-gradient(135deg,var(--grape-600) 0%,var(--grape-800) 62%,var(--grape-900) 100%);
  --grad-primary:linear-gradient(180deg,var(--grape-600),var(--grape-700));
  /* button engine — «juicy» filled surfaces: a hair lighter at the top so the fill
     reads as a rounded, lit surface, settling to the role's solid at the bottom.
     DERIVED from the role token via color-mix, so they follow EVERY scheme on their
     own (no scheme-block copy — the §11 trap): --ok-solid is a fixed state colour
     (accept stays green everywhere). Kept subtle —
     text sits mid-height where the colour ≈ solid, so AA contrast holds. */
  --grad-accept:linear-gradient(180deg,color-mix(in srgb,var(--ok-solid) 88%,#fff),var(--ok-solid));
  /* ФАСКА ЗАЛИТОЙ КНОПКИ (blox52 #3, п.4). Был только светлый блик по ВЕРХНЕЙ кромке, а низ
     кнопки просто обрывался — предмет читался как прямоугольник с бликом, а не как объём.
     У настоящей кнопки, вдавленной в бумагу, низ ТЕМНЕЕ: свет падает сверху. Вторая строка
     и есть эта тёмная кромка — те же 1px, только снизу и чёрным.
     Почему чёрный, а не «свой тёмный» у каждой роли: кромка в 1px не читается как ЦВЕТ, она
     читается как тень. Проверено на всех заливках — баклажан, графит, Maya, ночной виноград,
     зелёная «Принять», ночная. Ни зелёную, ни красную не грязнит: .22 чёрного на 1px — это
     тот же край, что и снизу у любого напечатанного предмета. */
  --bevel:inset 0 1px 0 rgba(255,255,255,.18), inset 0 -1px 0 rgba(0,0,0,.22);
  /* точка рядом со словом Lingo — часть ЗНАКА, а не акцент интерфейса: базовая схема увела
     акцент в чёрный, и точка вместе с ним стала бы чёрной кляксой на баклажановой шапке.
     Синие схемы переопределяют её на свой Maya. */
  --brand-dot:var(--sky-400);
  /* the Lingo wordmark — the brand rainbow, deliberately FIXED across schemes */
  --grad-wordmark:linear-gradient(100deg,var(--sky-600),var(--veil-600) 55%,var(--gf-500));
}

/* ===========================================================================
   СИНИЕ СХЕМЫ LINGO (blox26 #4 + доп. запрос владельца) — «синяя база» с реального
   сайта школы lingo-school.com. Пять цветов палитры:  Jet Black #262e35 · Pale Sky
   #d0effe · Maya Blue #7bbeea · Alice Blue #f3f9fb · White.
   Их ДВЕ, и они делят одну палитру — различаются ТОЛЬКО «якорем» (во что окрашена
   шапка + первичные кнопки):
     • «Графитовая» (ключ scheme2) — тёмная ГРАФИТОВАЯ шапка, белый текст;
     • «Lingo» (ключ scheme3) — сам Maya Blue выходит В ШАПКУ, текст на ней белый.
   Имена в меню — из SCHEMES (public/settings.js); ключи scheme2/scheme3 менять НЕЛЬЗЯ,
   они лежат в localStorage и в users.ui_prefs у уже выбравших схему.
   Общая база (текст / фон / акцент / линии) — в сгруппированном правиле ниже; отличие
   каждой схемы — в её собственном коротком блоке.
   Зелёный «сделано» (--ok*), красный «внимание» (--alert* и --danger) и золото челленджа
   (--gold*) СОЗНАТЕЛЬНО НЕ трогаем — наследуются из :root, чтобы «сделано»/«тревога»/«приз»
   читались одинаково во всех схемах (на Alice-Blue фоне контраст тот же, что на белой карточке).
   Значения, которых в 5 цветах нет, ВЫВЕДЕНЫ из базы (затемнение/осветление) — помечены ниже.
   =========================================================================== */
:root[data-scheme="scheme2"],
:root[data-scheme="scheme3"]{
  /* текст: Jet Black как чернила; strong/muted/faint выведены затемнением/осветлением */
  --ink:#262e35;              /* Jet Black — заголовки и текст (12.96:1 на фоне)        */
  --ink-strong:#171c22;       /* выведен: тёмный Jet Black — одна громкая строка          */
  --muted:#566270;            /* выведен: сине-серый, 5.85:1 — вторичный текст            */
  --faint:#7c8894;            /* выведен: светлее — подсказки, таймстемпы, disabled       */

  /* фон и подложки: Alice Blue как основной фон; inset-панели выведены из него */
  /* СТОЛ синих схем (blox51 #3). Alice Blue #f3f9fb был фоном, но отличался от
     белой карточки на 1.17 — глазу этого мало, и после снятия заливки с .opane
     плашка (#e3f1fb) оказалась ТЕМНЕЕ фона, то есть читалась как вмятина.
     Выведен более глубокий стоп той же холодной базы: 1.32 к белому — ровно та
     же разница, что бумага/стол в базовой схеме. Alice Blue остался в --surface:
     он теперь не фон, а углубление В бумаге, где ему и место. */
  --bg:#d6e2ea;               /* выведен: СТОЛ — на нём лежит всё, 1.32 к бумаге          */
  --surface:#eaf3f8;          /* выведен: чуть темнее бумаги — вложенные панели           */
  --surface-2:#f3f9fb;        /* Alice Blue — мягкий inset внутри бумаги                  */
  --line:#cbe0ee;             /* выведен: сине-серая граница по умолчанию                  */
  --line-soft:#e0edf5;        /* выведен: волосяная линия / разделитель                    */
  --line-strong:#9ab4c6;      /* выведен: заметная граница                                 */

  /* акцент: Maya Blue как заливка/выделение; deep/ink/line выведены из него */
  --accent:#7bbeea;           /* Maya Blue — заливки, выделение (с --ink 6.82:1)          */
  --accent-ink:#12689e;       /* выведен: тёмная Maya — акцент ТЕКСТОМ на белом, 6.0:1     */
  --accent-deep:#2f8fd0;      /* выведен: средняя Maya — hover/ссылки                      */
  --accent-tint:#d0effe;      /* Pale Sky — акцентный фон                                  */
  --accent-line:#a9dbf6;      /* выведен: светлая Maya — акцентная граница                 */

  /* новые ролевые ярлыки (blox26) — выведены из той же базы (нейтраль Jet Black + акцент Maya).
     Состояния (--ok* и --alert*) НЕ трогаем: наследуются из :root, чтобы «сделано»/«тревога»
     читались одинаково во всех схемах.
     ОСТОРОЖНО: «звёздочка/слэш» в тексте комментария (как в старой записи «ок-звёздочка/
     алерт») ЗАКРЫВАЕТ комментарий досрочно, и парсер съедает всё до ближайшей «;» — так эта
     самая запись молча глотала --muted-strong с момента своего появления (найдено blox52 #13;
     теперь это стережёт проверка «комментарии CSS» в tools/check.js). */
  /* ОБЪЯВЛЕНИЕ — В СЕМЬЕ АКЦЕНТА (blox52 #13). Лавандовая заметка из :root была на детском
     экране синих схем ЧЕТВЁРТЫМ цветовым семейством (Maya + нейтраль + зелёный + вуаль) —
     оба судьи второго прогона сошлись, что здесь плашка должна жить в акценте схемы. Рецепт
     фона — тот же, что у :root (бумага + 12% пигмента), пигмент — Maya; линия — --frame-line
     (рамка темы своей схемы: в Графитовой графит, в «Lingo» светлый край шапки), заголовок
     «ОБЪЯВЛЕНИЕ» — якорь схемы. Замер 06.09.2026: --ink на фоне 12.7, заголовок-якорь
     12.7 (scheme2) / 5.6 (scheme3). Базовую лаванду и ночь НЕ трогаем: в базовой схеме
     судьи разошлись — оставлено как есть (дешевле), помечено в отчёте blox52 #13. */
  --note-bg:color-mix(in srgb, var(--accent) 12%, var(--card));
  --note-line:var(--frame-line);
  --note-ink:var(--anchor);
  --muted-strong:#3b4653;     /* выведен: между --ink и --muted                            */
  --fill-soft:#e0edf5;        /* = --line-soft: та же светлая подложка, роль «заливка»      */
  --line-mid:#b6cfe0;         /* выведен: между --line и --line-strong                     */
  --primary:#262e35;          /* якорь-заливка = Jet Black (как --ink), белый текст 12.96:1 */
  --primary-strong:#171c22;   /* тёмная заливка чрома (тосты/ридаут)                        */
  --anchor:#12689e;           /* ЯКОРЬ: глубокий Maya под белый текст (= --accent-ink)      */
  --accent-fill:#bce4fb;      /* выведен: светлая Maya-заливка, темнее --accent-tint        */
  --brand-dot:#7bbeea;        /* точка знака — Maya (в базовой схеме она небесная)          */
  /* рельсы тасков по типу: нейтральный = нейтраль схемы; «нужна сдача» = Maya. Без этого
     grape-500/sky-500 из :root не следовали бы за синей схемой (остаточная утечка). */
  --task-plain:#566270; --task-sub:#2f8fd0;
  /* ссылка в окне проводника — акцентные чернила СВОЕЙ схемы (они уже синие), а не
     sky-700 базовой: иначе холодная схема несла бы чужой оттенок синего (blox51 #10) */
  --exp-link:var(--accent-ink);

  /* ЗАГЛУШКИ ПРОТИВ УТЕЧКИ ТЁПЛОЙ БУМАГИ (blox51 #2). Эти четыре токена раньше
     не переопределялись здесь и брались из :root. После перевода базовой схемы на
     бумагу они принесли бы бежевый в синие схемы — карточки, плашки, подписи и
     тени стали бы тёплыми на холодном фоне. Значения — прежнее поведение схем,
     байт в байт: карточка белая, плашка = --surface-2 (как и раньше через :root),
     подпись на светлом фоне = --muted, тень в тон Jet Black. */
  --card:#ffffff;              /* БУМАГА синих схем — белая, а не бежевая            */
  --task-plaque:var(--card);   /* плашка таска — тоже бумага (правило слоёв общее)   */
  --on-bg:var(--muted);        /* текст на столе: --faint на #d6e2ea дал бы 2.4:1     */
  --sh-rgb:38,46,53;           /* тень в тон Jet Black, а не тёплая                   */
  --emb-lo:rgba(8,16,24,.28);  /* дно канавки — холодное; тёплое читалось бы пятном */

  /* ФОКУС-КОЛЬЦО и ВЫДЕЛЕНИЕ — по общему рецепту (см. :root), но своим цветом.
     Контур кольца — акцентные ЧЕРНИЛА (глубокая Maya): 6.0:1 на белой карточке и
     4.55 на столе против 1.35 и 1.21 у прежнего полупрозрачного Maya.
     Выделение — сам Maya: рецепт «акцент 26% в бумагу» тут не годится, бумага белая
     и светлый Maya в ней растворяется (1.2:1). Чистый Maya даёт 2.02:1 к белому,
     а --ink на нём 6.82:1 — те самые цифры, под которые он и заведён. */
  --ring-c:var(--accent-ink);
  --sel-bg:var(--accent);
}

/* ── «Графитовая» (scheme2): тёмный ГРАФИТОВЫЙ якорь ─────────────────────────────────
   Шапка и первичные кнопки — тёмный Jet Black вместо винограда (иначе на синей базе
   верхняя панель осталась бы фиолетовой). Оттенки выведены из #262e35. */
:root[data-scheme="scheme2"]{
  --grad-header:linear-gradient(135deg,#323c46 0%,#1e252c 62%,#141920 100%);
  --grad-primary:linear-gradient(180deg,#323c46,#262e35);
  --anchor:#262e35;          /* ЯКОРЬ схемы — тот же графит, что в шапке (белый 12.96:1) */
  --frame-line:var(--ink);   /* тёмный графитовый контур рамки темы — как якорь схемы */
  /* blox28 #3: рельс обычного таска (без сдачи) — ЧИСТО нейтральный светло-серый,
     а не сине-серый #566270 из общего блока (тот остаётся для scheme3 «голубоватой»). */
  --task-plain:#a6a6a4;
  /* blox28 #3 (уточнение): само ТЕЛО плашки таска на мониторе (.oent) — светло-серое
     в тон рельсу, а не голубоватый --surface-2 (#e3f1fb). В scheme3 тело остаётся голубым. */
  /* blox51 #3: тело плашки остаётся НЕЙТРАЛЬНЫМ (не голубым) — как решил владелец
     в blox28 #3, — но теперь это бумага, а не полупрозрачная подложка: под ней
     больше нет белой панели, сквозь которую она просвечивала. */
  --task-plaque:#fbfbfa;
}

/* ── «Lingo» (scheme3): сам Maya Blue выходит в ШАПКУ (БЕЛЫЙ текст) ───────────────
   Владелец хотел видеть бренд-цвет Maya Blue именно наверху, а не только в акцентах,
   и чтобы текст на шапке остался БЕЛЫМ. Ограничение: белый на светлом Maya Blue
   #7bbeea нечитаем (1.9:1). Поэтому «якорь» шапки — ГЛУБОКИЙ Maya Blue (из того же
   семейства, не графит как в «Графитовой»), затемнённый ровно настолько, чтобы белый текст
   прошёл AA: самый светлый стоп #1a75b0 даёт с белым 5.0:1, центр #12689e — 6.0:1.
   Белый текст, полупрозрачно-белые подложки и Maya-точка логотипа работают как в
   базовой тёмной шапке — поэтому НИКАКИХ переопределений chrome тут не нужно. */
:root[data-scheme="scheme3"]{
  --grad-header:linear-gradient(135deg,#1a75b0 0%,#12689e 58%,#0d5077 100%);  /* глубокий Maya Blue, белый текст ≥5:1 */
  /* ВЕРХНИЙ СТОП ЗАТЕМНЁН (blox52 #10): было #2f8fd0 — белый текст на нём 3.52:1, и даже в
     верхней точке самой СТРОКИ ТЕКСТА (t≈.31 от высоты кнопки) выходило 4.12:1 при норме 4.5.
     Пока градиент носила одна «Отправить учителю», этого никто не мерил; теперь он на каждой
     кнопке-решении. #1c78b5 даёт белому 4.77:1 уже на самом верхнем крае кнопки (замер по
     ХУДШЕЙ точке, не по середине — урок --hdr-sheen-a выше: 4.52 это округление от провала),
     и остаётся светлее верхнего стопа шапки #1a75b0 — кнопки по-прежнему выделяются. */
  --grad-primary:linear-gradient(180deg,#1c78b5,#12689e);
  --frame-line:#1a75b0;   /* ЛЕВЫЙ (светлый) край шапки — рамка темы в тон, но легче */
  /* ТОЧКА ЗНАКА СВЕТЛЕЕ — только в этой схеме. Во всех остальных точка (Maya #7bbeea
     или небесная #5cc8ff) лежит на ТЁМНОЙ шапке: на графите и на баклажане это 4.2–8.8:1.
     Здесь же в шапку вышел сам Maya, и точка оказалась Maya на Maya — 2.47:1 к светлому
     краю шапки, то есть знак «Lingo» терял свою точку ровно в схеме своего имени.
     Сдвиг на два стопа вверх по той же небесной лестнице: 3.77:1 на светлом краю
     шапки, 4.55 в центре, 6.55 на тёмном. Цвет остаётся из палитры, чужого не заводим. */
  --brand-dot:var(--sky-200);
  /* СВЕТ В УГЛУ ШАПКИ — ВПОЛСИЛЫ, и это замер, а не вкус (blox52 #5). Три другие шапки
     тёмные: белый текст держит на них 8–13:1, и полные 8% белого им ничего не стоят.
     Здесь же в шапку вышел сам Maya, самый светлый её стоп #1a75b0 даёт белому 4.98:1
     при норме 4.5 — запаса ноль. Полные 8% уводили угол на 4.52, а левый край на
     телефоне на 4.87: формально проход, фактически округление от провала. .05 держит
     угол на 4.69 и край на 4.96, и пятно на шапке при этом видно. */
  --hdr-sheen-a:.05;
}

/* ===========================================================================
   ТЁМНАЯ СХЕМА (ключ dark, blox51 #11) — ЧЕТВЁРТАЯ схема, а не отдельный
   переключатель поверх трёх. Владелец: «тёмная тема — одна или по-разному
   ляжет на каждую? если одна — делай».
   ПОЧЕМУ ОДНА. Схем формально три, но нейтралей у них ДВЕ: тёплая бумага
   базовой и холодный Alice Blue у синих; scheme2/scheme3 делят одну палитру и
   различаются только шапкой. Тёмная ночь стирает именно нейтраль — «тёплый
   светлый» и «холодный светлый» на тёмном фоне перестают различаться, и три
   тёмных палитры оказались бы тремя копиями одной. Осью (день/ночь × 3 схемы)
   это стоило бы шести комбинаций в каждой проверке контраста навсегда и трёх
   значений у каждого нового токена. Плата за «одну»: выбравший «Lingo» на ночь
   уходит из «Lingo», а не гасит её. Если это когда-нибудь помешает — ось
   достраивается поверх этого блока тремя короткими правилами (только --anchor
   и --grad-header), переписывать палитру не придётся.
   ЧТО ЗДЕСЬ ПЕРЕВЕРНУТО, а что нет:
     • ПРАВИЛО СЛОЁВ живёт как есть, только меняет направление: уровня по-прежнему
       два и они чередуются, но теперь СТОЛ ТЕМНЕЕ бумаги (в светлых схемах —
       наоборот), а колодец (--surface) по-прежнему темнее листа. Шаг стол↔бумага
       1.27 — тот же порядок, что 1.32 в светлых: на тёмном разница сжимается,
       поэтому стол уведён почти в чёрный.
     • ЯКОРЬ ОСТАЛСЯ ТЁМНОЙ ЗАЛИВКОЙ ПОД БЕЛЫМ ТЕКСТОМ — это и есть причина, по
       которой тёмная схема обошлась без ломки: возьми якорь светлым, и --on-dark
       перестал бы быть белым во всём приложении (21 место). Взят grape-500:
       белый на нём 5.33:1, а от стола он отделяется на 3.66 — кнопка читается
       как приподнятая, а не как дыра.
     • СОСТОЯНИЯ СОХРАНЯЮТ СВОИ СПЛОШНЫЕ ЗАЛИВКИ (--ok-solid, --alert-solid,
       --alert-strong наследуются из :root): «сделано» и «тревога» обязаны
       выглядеть одинаково во всех схемах, и на тёмном столе они держатся —
       зелёный 6.24:1 с белым и 3.10 к столу, красный 4.89 и 3.96. Переопределены
       только их ЧЕРНИЛА, ТИНТЫ и ЛИНИИ: бледные стопы на тёмной бумаге исчезают.
     • АКЦЕНТ БАЗОВОЙ СХЕМЫ — её собственные чернила (blox51 #3). Ночью чернила
       светлые, значит и акцент светлый; рецепт «тинт = бумага + N% пигмента»
       переживает переворот сам собой, потому что основа у него --card.
   =========================================================================== */
:root[data-scheme="dark"]{
  /* ЕДИНСТВЕННАЯ строка, которую нельзя заменить токеном: она говорит САМОМУ БРАУЗЕРУ,
     что страница тёмная. Без неё полоса прокрутки, галочки, ползунки, выпадашки и
     подсветка автозаполнения остаются светлыми — на снимке ленты уроков белая полоса
     скролла била по глазам сильнее всего остального вместе взятого. */
  color-scheme:dark;

  /* текст: ночная бумага — светлая, с виноградным подмесом, а не чистый белый */
  --ink:#ece8f2;              /* 12.8:1 на бумаге, 16.2:1 на столе                */
  --ink-strong:#ffffff;       /* одна громкая строка                             */
  --muted:#a89fb8;            /* вторичный текст, 6.1:1                          */
  --faint:#958ca6;            /* подсказки, таймстемпы, disabled, 4.83:1         */
  --muted-strong:#c6bed3;     /* на тон гуще --muted, 8.6:1                      */
  /* текст НА СТОЛЕ. В светлых схемах стол темнее бумаги и подпись на нём
     приходилось УСИЛИВАТЬ; ночью стол темнее ВСЕГО, поэтому там контраста больше,
     а не меньше — хватает обычного --muted (7.7:1). */
  --on-bg:var(--muted);

  /* слои: стол почти чёрный, бумага приподнята, колодец утоплен обратно */
  --bg:#0e0b14;               /* СТОЛ                                            */
  --card:#272233;             /* БУМАГА — карточки, плашки, шторки, 1.27 к столу */
  --task-plaque:var(--card);
  --surface:#1d1926;          /* колодец В бумаге — темнее листа, как и в свете   */
  --surface-2:#221d2d;        /* мягкий inset                                    */
  --line:#3d3750;             /* граница по умолчанию                            */
  --line-soft:#332e44;        /* волосок                                         */
  --line-mid:#4a4360;         /* поле ввода, заметная граница                    */
  /* НЕЙТРАЛЬНАЯ ЗАЛИВКА (дорожка вкладок, лунка на ховере, чип «Nope»). Пропустить её
     здесь — самая дешёвая версия §11-ловушки: токен просто остаётся бежевым из :root, и
     посреди ночного монитора горят светлые пилюли. Ровно это и случилось на первом снимке.
     Значение = --line-soft, как и в синих схемах: «та же светлая подложка, роль заливка». */
  --fill-soft:#332e44;        /* 1.19 к бумаге; --muted-strong на нём 7.3:1       */
  --line-strong:#5d5474;

  /* акцент = светлые чернила схемы (в базовой он чёрный — ночью тот же приём) */
  --accent:#d9d2e4;           /* обводки, выделение, 10.5:1 на бумаге            */
  --accent-ink:#f4f1f8;       /* акцент ТЕКСТОМ — гуще корпуса                   */
  --accent-deep:#d9d2e4;
  --accent-line:#5d5474;
  --accent-tint:color-mix(in srgb, #d9d2e4 9%, var(--card));   /* 1.25 к бумаге  */
  --accent-fill:color-mix(in srgb, #d9d2e4 16%, var(--card));  /* 1.50, ::selection */

  /* якорь и тёмные заливки хрома */
  --anchor:#786388;                 /* grape-500: белый 5.33:1, к столу 3.66     */
  --anchor-ink:var(--grape-300);    /* якорь ЧЕРНИЛАМИ — светлый виноград, 7.7:1 */
  --primary:#564a68;                /* заливка под белым текстом, 8.16:1         */
  --primary-strong:#675a7b;         /* тосты, ридаут перетаскивания, 6.32:1      */
  --grad-header:linear-gradient(135deg,#3a2b46 0%,#2a1f33 62%,#1e1626 100%);
  --grad-primary:linear-gradient(180deg,#8a729c,#786388);
  --brand-dot:var(--sky-400);       /* точка знака — как в базовой               */

  /* состояния: заливки НЕ трогаем, чернила/тинты/линии — на светлые стопы.
     Тинт по тому же рецепту (бумага + 12% среднего стопа), только пигмент светлее:
     на тёмной бумаге бледный стоп даёт меньше 1.06 и состояния не слышно. */
  --ok:var(--cel-400);   --ok-ink:var(--cel-300);   --ok-line:#3d6238;
  --ok-tint:color-mix(in srgb, var(--cel-400) 12%, var(--card));
  --ok-fill:color-mix(in srgb, var(--cel-400) 22%, var(--card));
  --alert:var(--gf-400); --alert-ink:var(--gf-300); --alert-line:#7a3336;
  --alert-tint:color-mix(in srgb, var(--gf-400) 12%, var(--card));
  --alert-fill:color-mix(in srgb, var(--gf-400) 22%, var(--card));
  --danger:var(--gf-400); --danger-ink:var(--gf-300);
  --draft:var(--veil-400); --draft-ink:var(--veil-300); --draft-line:#6b4574;
  /* штриховка черновика ночью — СВЕТЛАЯ: --sh-rgb ночью 0,0,0, и чёрный штрих по
     тёмной подложке не увидит никто (та же логика, что у обрезного края). */
  --draft-hatch:rgba(255,255,255,.035);
  --draft-tint:color-mix(in srgb, var(--veil-400) 12%, var(--card));
  --note-bg:color-mix(in srgb, var(--veil-400) 12%, var(--card));
  --note-line:#6b4574; --note-ink:var(--veil-300);
  /* золото: #b07d16 подбиралось под бумагу и на тёмном тонет (1.9:1) — поднято */
  --gold:#d9a83a; --gold-ink:#e8c473; --gold-line:#6b5218;
  --gold-tint:color-mix(in srgb, var(--gold) 12%, var(--card));

  /* рельсы тасков: иерархия та же — «нужна сдача» ГРОМЧЕ «просто сделать».
     Ночью громким становится сам небесно-синий (8.2:1), а нейтральный рельс тише (3.3). */
  --task-plain:#7a7186; --task-sub:var(--sky-400);

  /* ОКНО ПРОВОДНИКА ТОЖЕ ГАСНЕТ. Граница blox51 #10 («поверхность чужая»)
     сохранена, но чужое ≠ обязательно белое: у самого Я.Диска есть тёмная тема,
     а белый прямоугольник посреди ночного приложения выжигает глаз сильнее, чем
     любая потеря узнаваемости. Чужим окно остаётся тем, чем и было по существу, —
     красной «Я», плоским списком и серой обвязкой. Различается оно с нашей
     бумагой теперь ТОНОМ: диск нейтрально-серый, наша бумага виноградная.
     Ссылка остаётся синей (решение владельца), но светлой: sky-300 даёт 10.7:1
     на тёмной области файлов, тогда как sky-700 базовой дал бы 1.4. */
  --ya-surface:#1c1b20; --ya-soft:#141317; --ya-line:#33323a;
  --exp-link:var(--sky-300);

  /* ФОКУС-КОЛЬЦО и ВЫДЕЛЕНИЕ отдельных значений НЕ требуют: общий рецепт (:root)
     переворачивается сам. Контур кольца = --ring-c = var(--accent), а ночью акцент
     светлый — 10.5:1 на бумаге, 13.3 на столе; внутренний зазор = --card, то есть
     ночная бумага. Выделение = «акцент 26% в бумагу» = 1.99:1 к листу при --ink 6.4. */

  /* ГЛУБИНА. Тень на тёмном почти не работает — разделяют СЛОИ, а не тени;
     оставляем их чёрными и слабыми, чтобы край листа всё же читался.
     ТИСНЕНИЕ переворачивается: 95%-белый бортик, который ночью был бы сияющей
     полосой по верхней грани каждой плашки, ослаблен до .08; дно канавки
     наоборот углублено — на тёмной бумаге тень видна хуже, чем на светлой. */
  --sh-rgb:0,0,0;
  /* НОЧЬЮ ВОЛНА НЕ УМНОЖАЕТ. Умножение — это «краска в бумагу», и работает оно, пока
     бумага светлее краски. Ночью наоборот: бумага почти чёрная, а чернила (--ink)
     светлые, и multiply дал бы чёрное на чёрном — то есть отклик на касание исчез бы
     ровно там, где он и заведён, на телефоне. Ночью волна остаётся светлым следом. */
  --ripple-blend:normal;
  --emb-hi:rgba(255,255,255,.08);
  --emb-hi-soft:rgba(255,255,255,.05);
  --emb-lo:rgba(0,0,0,.55);
  --emb-edge:rgba(0,0,0,.35);
  /* ОБРЕЗНОЙ КРАЙ НОЧЬЮ ПЕРЕВОРАЧИВАЕТСЯ. Днём торец листа темнее и бумаги, и
     стола — тень в тон. Ночью стол ТЕМНЕЕ листа, и чёрный торец просто растворился
     бы в столе: край листа исчез бы ровно там, где он и нужен. Поэтому ночью торец
     ловит свет — тем же белым, что и бортик, только ещё тише. */
  --sheet-edge:0 0 0 .5px rgba(255,255,255,.06);
  /* blox53 #27 — ЛИНИЯ КОНТАКТА ШАПКИ ПЕРЕВОРАЧИВАЕТСЯ ПО ТОЙ ЖЕ ПРИЧИНЕ. «Чёткая тёмная
     черта под кромкой» ночью не существует: --sh-rgb здесь 0,0,0, а стол под планкой почти
     чёрный (#0e0b14) — планку от стола отделяла ОДНА разница тона (1.08), и край шапки
     читался обрывом заливки. Судья первого прогона это и назвал: «ночью нужен светлый
     волосок». Ставим ровно его — той же белой нитью, что торец листа, только чуть громче:
     это НЕ тень (тень ночью бесполезна), а торец планки. Тень (--plank-cast) намеренно
     оставлена чёрной и невидимой: слоёв в --plank и --plank-flat должно быть поровну, иначе
     переход по прокрутке пойдёт рывком. */
  --plank-line:0 1px 0 rgba(255,255,255,.10);
  /* ЗЕРНО НОЧЬЮ ПОЧТИ ГАСНЕТ. Шум — это светлые точки на тёмном, и на почти чёрном
     столе те же 3.5% читаются не картоном, а цифровым шумом дешёвой матрицы.
     СВЕТ КОМНАТЫ, наоборот, усилен: ночная бумага отличается от ночного стола всего
     на 1.27, и лампа в дневной силе на почти чёрном столе просто не читается. */
  --grain-o:.012;
  --room-o:26%;
  /* СВЕТ В УГЛУ ШАПКИ — ПОЛНОЙ СИЛЫ, и сказано это здесь ВСЛУХ. Ночная шапка тёмная
     (белый на ней 14.9:1), запас у неё огромный, и гасить свет незачем: вполсилы он
     стоит только у «Lingo», где белому тесно. Строка не лишняя — без неё §11-гейт
     справедливо ругается, что число перекрыто одной схемой и молчит в другой. */
  --hdr-sheen-a:.08;
}

/* ---- icons (see icons.svg / icons.js) ---------------------------------------
   One stroked family, coloured by the text around it. Sized in em so an icon always
   matches its label. .ic-lg for the hub tiles, .ic-xl for empty states.

   ПЕРО ЗНАКА = ПЕРО ШРИФТА (blox52 #3, п.5). Иконка нарисована в квадрате 24×24 и сжимается
   вместе с подписью — значит вместе с ней ужимался и ШТРИХ: рядом с подписью в 11-13px
   (а они почти все жирные, 700-800) штрих выходил 0.9-1.1px и знак был БЛЕДНЕЕ соседней
   буквы. В типографике толщина знака равна толщине шрифта, поэтому штриху нужен ПОЛ.
   Одним числом это не решается: толщина задаётся в единицах картинки, а сжатие зависит
   от кегля подписи — делить длину на длину CSS не умеет. Поэтому штрих переведён на
   vector-effect:non-scaling-stroke (см. icons.svg): он перестаёт сжиматься вместе с
   картинкой, и его толщина пишется прямо в пикселях экрана. Дальше max() и делает пол:
     .084em — ровно та толщина, что была (1.75 × 1.15em ÷ 24), поэтому у крупного знака
              не меняется НИЧЕГО: 20px подписи → 1.68px и до, и после;
     1.35px — пол: включается только при подписи мельче ~16px (13px → 1.09 стало 1.35).
   У .ic-lg и .ic-xl картинка крупнее при том же кегле, поэтому коэффициент у них свой —
   иначе плитки хаба и пустые состояния ПОХУДЕЛИ бы. Прежний stroke-width на .ic-xl был
   мёртвой строкой: правило symbol{} внутри icons.svg ближе к фигуре и всегда его било.
   ОБА значения едут ОТСЮДА переменными, и это страховка: icons.svg подключён внешней ссылкой,
   а браузеры по-разному пускают наши переменные внутрь чужого документа. Где не пустят —
   не приедет ни выключатель --ic-ve, ни толщина --icw, и иконка нарисуется ровно как до этой
   правки (запасные значения внутри icons.svg — прежние). */
.ic{width:1.15em;height:1.15em;flex:0 0 auto;vertical-align:-.17em;
    fill:none;stroke:currentColor;stroke-linecap:round;stroke-linejoin:round;
    --ic-ve:non-scaling-stroke; --icw:max(1.35px,.084em)}
.ic-lg{width:1.7em;height:1.7em;vertical-align:-.3em;--icw:max(1.35px,.124em)}
.ic-xl{width:2em;height:2em;vertical-align:-.35em;--icw:max(1.35px,.146em)}

/* ---- base ------------------------------------------------------------------- */
*{box-sizing:border-box}
/* ПОЛОСА ПРОКРУТКИ В ТОН. Chrome/Safari красит её через ::-webkit-scrollbar (так сделана
   лента дней, .ncar), Firefox такого не понимает вовсе и слушает только scrollbar-color —
   поэтому в Firefox все полосы приложения оставались системно-серыми поверх бумаги и
   ночного стола. Два значения: ползунок = заметная линия схемы, дорожка прозрачная (фон
   виден насквозь, лишней светлой колеи не появляется). Свойство наследуется, так что
   одного объявления на корне хватает на каждую прокручиваемую область. */
html{-webkit-text-size-adjust:100%;scrollbar-color:var(--line-strong) transparent}
body{
  margin:0;
  font-family:var(--font);
  font-size:var(--fs-md);
  line-height:var(--lh);
  /* ТАБЛИЧНЫЕ ЦИФРЫ ВЕЗДЕ (blox51 #3, заход 6). В Onest пропорциональная единица ВТРОЕ уже
     нуля: замер на 20px — «1111» занимает 28px, «0000» — 52px. Значит любое число, которое
     меняется на месте (таймер плеера, счётчик «к проверке», «5/8», номер дня в ленте) при
     каждом обновлении дёргает соседей на несколько пикселей, а числа в столбик не
     выстраиваются в столбик. Свойство наследуется, поэтому одного объявления на body хватает
     на всё приложение — курировать список счётчиков не нужно, и новый счётчик получит
     табличные цифры сам. В прозе они чуть шире, и это осознанная плата: текста с числами в
     приложении почти нет, а числа есть на каждом экране. Стережёт проба «цифры не дёргаются». */
  font-variant-numeric:tabular-nums;
  /* КЕРНИНГ ЯВНО (blox52 #6, п.2). У Onest пары вроде «Го», «АV», «Ту» описаны в самом файле
     шрифта, но по умолчанию браузер включает их не всегда: `auto` разрешает движку отключить
     кернинг ради скорости — на мелком кегле именно это и происходило. `normal` требует его
     всегда. Свойство наследуется, поэтому одного объявления на body хватает на приложение. */
  font-kerning:normal;
  color:var(--ink);
  background:var(--bg);
  -webkit-font-smoothing:antialiased;
  -moz-osx-font-smoothing:grayscale;
}
/* ЗЕРНО И СВЕТ КОМНАТЫ — ДВА ПРИБИТЫХ К ЭКРАНУ СЛОЯ ПОВЕРХ СТОЛА (blox52 #4, пп. 4-5).
   Зачем два псевдоэлемента, а не один: у зерна и у света разная сила, и ночь гасит одно и
   усиливает другое — на одном слое их одной непрозрачностью не развести. Зерно живёт на
   html::before, а не на body::after, потому что body::after занят дев-инспектором
   (inspector.css) и в его режиме зерно бы пропадало.
   z-index:-1 — слои лежат ПОД всем содержимым и НАД заливкой стола. Работает это так:
   у html своей заливки нет, поэтому фон body по правилу CSS уезжает на холст страницы,
   а сам body остаётся прозрачным — и отрицательный слой оказывается поверх холста.
   ЕСЛИ КОГДА-НИБУДЬ ЗАДАТЬ html СВОЙ background — оба слоя окажутся под ним и исчезнут
   молча; это и стережёт проба «материал бумаги» (она меряет разброс пикселей на снимке,
   а не наличие правила в CSS).
   pointer-events:none — слой не имеет права перехватить ни одного касания; та же проба
   бьёт по этому факту отдельно, потому что ломается он тихо и целиком. */
html::before{content:"";position:fixed;inset:0;z-index:-1;pointer-events:none;
  background-image:var(--grain-img);background-size:128px 128px;opacity:var(--grain-o)}
body::before{content:"";position:fixed;inset:0;z-index:-1;pointer-events:none;
  background:radial-gradient(150% 115% at 50% 0%,
    color-mix(in srgb, var(--card) var(--room-o), transparent) 0%, transparent 66%)}
/* печать: зерно и виньетка — свойство ЭКРАНА, на бумаге это просто серый налёт поверх текста */
@media print{ html::before,body::before{display:none} }
/* ЗАГОЛОВОК ЛОМАЕТСЯ ПО СМЫСЛУ, А НЕ ПО СЛУЧАЙНОМУ СЛОВУ (blox52 #6, п.2). До этого во всём
   продукте стояло РОВНО ОДНО правило красивой разбивки строк (.estate-t) — остальные заголовки
   рвались там, где кончилась ширина, и на телефоне регулярно оставляли одно слово на второй
   строке. `balance` выравнивает длину строк заголовка между собой. Действует только на короткие
   блоки (браузер применяет его до нескольких строк), поэтому длинному абзацу он не повредит, а
   там, где свойства нет, строка ломается ровно как раньше — деградация без вреда. */
h1,h2,h3,h4{letter-spacing:var(--tracking-tight);line-height:var(--lh-tight);text-wrap:balance}
/* поля и кнопки не наследуют шрифт от body сами (UA-стили), поэтому и семейство, и
   табличные цифры передаём им явно: в поле ввода PIN-кода это особенно заметно. */
/* ...и кернинг тоже: UA-стиль задаёт кнопке свой шрифт целиком, поэтому font-kerning:normal с
   body до неё не доезжает — описание плитки кабинета лежит ВНУТРИ <button>, и без этой строки
   единственный длинный читаемый текст с кернингом оставался бы «auto» (blox52 #6). */
button,input,select,textarea{font-family:inherit;font-variant-numeric:inherit;font-kerning:inherit}
/* МИГАЮЩИЙ КУРСОР В ПОЛЕ — цветом схемы, а не системным. Системный курсор в Chrome
   чёрный, в тёмной схеме на почти чёрной бумаге его попросту не видно, а в дневных
   схемах он единственная деталь ввода, которая не слушалась палитры. Берём акцентные
   ЧЕРНИЛА: они тёмные в светлых схемах и светлые в ночной, то есть контрастны бумаге
   в каждой из четырёх. Курсор ставится только полям — у кнопок его нет. */
input,textarea{caret-color:var(--accent-ink)}
/* СИСТЕМНЫЕ ГАЛОЧКА, РАДИО, ПОЛЗУНОК И ПОЛОСА ЗАГРУЗКИ. Их рисует сам браузер, и без
   accent-color они синие (Chrome) или серые — включая галочку на воротах согласия, где
   это первый управляющий элемент, который человек видит в приложении. --anchor — тёмная
   сплошная заливка СВОЕЙ схемы (баклажан · графит · Maya · ночной виноград), та же, что
   под белым текстом кнопки: белая галочка на ней читается по построению. Ночная схема
   берёт свой якорь автоматически, отдельного правила не нужно. */
input[type=checkbox],input[type=radio],input[type=range],progress{accent-color:var(--anchor)}
/* Safari на iOS зумит страницу, когда фокус попадает в поле со шрифтом меньше 16px, и обратно
   уже не отзумливает — приложение остаётся «съехавшим» вправо даже после ухода с экрана
   (blox11 #3, поле чата было 15px). На тач-экранах держим все поля ровно на 16px. !important —
   потому что точечные правила компонентов задают свой font-size и иначе перебьют это. */
@media (pointer:coarse){
  input,select,textarea{font-size:16px !important}
}
:focus-visible{outline:none;box-shadow:var(--ring)}
/* выделение текста идёт за акцентом СВОЕЙ схемы (blox51 #3, заход 3.2). Раньше базовая брала
   sky-200 напрямую, а обе синих повторяли Pale Sky каждая у себя — три места на один факт,
   и после ухода базового акцента в чёрный первое из них осталось бы синим. --accent-fill
   уже есть, уже светлый в каждой схеме и уже стережётся пробой «акцентные поверхности». */
/* blox52 #2: заливка --accent-fill давала выделению 1.34:1 к бумаге — протащить мышью по
   абзацу и не увидеть, что выделено. Теперь у выделения свой токен --sel-bg (см. theme
   выше), а --accent-fill остался тем, чем был, — поверхностью. */
::selection{background:var(--sel-bg);color:var(--ink)}
