/* ============================================================================
   СУПРЕМУМ · theory-paper.css — страницы теории на новом фундаменте
   ============================================================================
   СОБРАН АВТОМАТИЧЕСКИ: python tools\design_system\bridge_theory.py build-paper
   Руками не правится.

   Склеен из трёх частей:
     1. sup-tokens-paper.css — токены оформления, тональность «тушь и бумага»
     2. sup-compat.css  — перевод старых имён переменных на новые токены
     3. theory.css      — канон правил 512 страниц, БЕЗ блоков переменных

   Блоки :root и [data-theme="dark"] из канона вырезаны: значения теперь
   приходят из слоя токенов. Остальные правила канона не тронуты — они
   опираются на те же имена переменных, что и раньше, и мост их подставляет.

   Поэтому страницу теории достаточно переключить с theory.css на этот файл.
   Разметка не меняется ни на одной из 512 страниц.

   ПЕРЕВОД СТРАНИЦЫ — ДВЕ СТРОКИ, А НЕ ОДНА. С тех пор как оформление
   выбирает ученик в кабинете, рядом со ссылкой на стили ставится ещё одна:

       <link rel="stylesheet" href="/assets/theory-paper.css">
       <script src="/assets/sup-tone.js"></script>

   Обычным тегом, без defer: он ставит выбранные тему и тональность на <html>
   до первого кадра. Без него страница теории откроется в базовой палитре
   и перекрасится на глазах — либо не перекрасится вовсе.
   ============================================================================ */

/* ─── 1/4 ТОКЕНЫ ─────────────────────────────────────────── */
/* ============================================================================
   СУПРЕМУМ · sup-tokens-paper.css — токены тональностей «Тушь и бумага»
   ============================================================================
   СОБРАН АВТОМАТИЧЕСКИ: python tools\design_system\palette.py write-paper
   Руками не правится — правь PAPER_RAW / PAPER_FIX в palette.py: генератор
   проверит условия приёмки (контраст на композитных стеклянных подложках,
   различимость при дальтонизме) и перезапишет этот файл.

   Источник значений — холст Claude Design «СУПРЕМУМ Темы» (утверждён
   2026-08-20). Тональность выбирается атрибутом data-tone на <html>:
     (нет)                «Тушь и бумага» — 5–6 класс, витрина, кабинет
     data-tone="graphite" «Графит»        — 7–9 класс
     data-tone="news"     «Газета»        — 10–11 класс и ЕГЭ
   Светлая/тёмная — data-theme (ключ localStorage geo-theme, менять нельзя).
   ============================================================================ */

/* ── ТИПОГРАФИКА · общая для тональностей ─────────────────
   База 20px (на ≤720px база опускается до 18px в paper-base.css —
   иначе мера строки на телефоне падает ниже 30 знаков). */
:root {
  --font-display: 'Literata', Georgia, 'Times New Roman', serif;
  --font-body: 'IBM Plex Sans', system-ui, -apple-system, sans-serif;
  --font-mono: 'IBM Plex Mono', ui-monospace, 'Cascadia Mono', monospace;
  --font-math: 'KaTeX_Math', 'CMU Serif', 'Times New Roman', serif;

  --fs-root: 20px;
  --fs-3xl: clamp(1.6rem, 5.2vw, 2.5rem);
  --fs-2xl: clamp(1.3rem, 3.6vw, 1.75rem);
  --fs-xl: clamp(1.15rem, 2.4vw, 1.35rem);
  --fs-lg: 1.15rem;
  --fs-md: 1rem;
  --fs-sm: 0.875rem;
  --fs-xs: 0.775rem;

  --lh-3xl: 1.12; --lh-2xl: 1.22; --lh-xl: 1.32; --lh-lg: 1.45;
  --lh-md: 1.55; --lh-sm: 1.5; --lh-xs: 1.45;

  /* Веса ограничены файлами шрифтов: Plex Sans 400…600 (700 даст фальшивый
     жирный), Plex Mono только 500, Literata 200…900. */
  --fw-normal: 400; --fw-medium: 500; --fw-semi: 600;
  --fw-bold: 600; --fw-display: 700; --fw-mono: 500;
}

/* ── РАЗМЕРЫ · шкала 4px ── */
:root {
  --sp-1: 4px; --sp-2: 8px; --sp-3: 12px; --sp-4: 16px; --sp-5: 20px;
  --sp-6: 24px; --sp-8: 32px; --sp-10: 40px; --sp-12: 48px;
  --sp-16: 64px; --sp-20: 80px; --sp-24: 96px;

  --measure: 34.9rem;   /* 66 знаков; НЕ в ch — ширина ch зависит от шрифта */
  --page-max: 1180px;
  --page-pad: clamp(var(--sp-4), 4vw, var(--sp-12));
  --tap: 44px;
  --radius-pill: 999px;
}

/* ── ДВИЖЕНИЕ · интерфейс, а не презентация ── */
:root {
  --dur-instant: 80ms; --dur-fast: 150ms; --dur-base: 240ms; --dur-slow: 420ms;
  --ease-out: cubic-bezier(.2, .8, .3, 1);
  --ease-in-out: cubic-bezier(.6, 0, .3, 1);
  --stagger: 60ms;
  --ring-width: 2px; --ring-offset: 2px;
}

/* ── СЛОИ ── */
:root {
  --z-header: 50; --z-sticky: 40; --z-overlay: 80; --z-modal: 90; --z-toast: 100;
}

/* ── ФАКТУРА · миллиметровка ── */
:root {
  --grid-line: color-mix(in oklab, var(--n-5) 34%, transparent);
  --grid-step: 24px;
  --grid-step-fine: 6px;
}

/* Маркер живости файла для линтера сборки. */
:root { --sup-paper: 1; }


/* ── Тушь и бумага · светлая ── */
html:root {
  color-scheme: light;
  --n-0: #fffefb;
  --n-2: #eae7e0;
  --n-3: #ded9d0;
  --n-5: #c0ad98;
  --bg: #f3f1ec;
  --bg-sunken: #e7e3da;
  --surface: rgba(255,254,251,.90);
  --surface-2: rgba(255,254,251,.72);
  --sunken: rgba(35,33,29,.05);
  --text: #23211d;
  --text-strong: #14120f;
  --text-soft: #67645e;
  --text-faint: #858179;
  --border: rgba(35,33,29,.15);
  --border-strong: rgba(35,33,29,.30);
  --rule: rgba(35,33,29,.22);
  --accent: #2b2823;
  --accent-hover: #14120f;
  --accent-fg: #fbfaf7;
  --accent-soft: rgba(35,33,29,.07);
  --accent-line: rgba(35,33,29,.28);
  --pen: #a04a3c;
  --ok: #3f6b4f;
  --err: #9c4038;
  --warn: #8a6a22;
  --info: #3e5574;
  --ok-soft: rgba(63,107,79,.11);
  --err-soft: rgba(156,64,56,.10);
  --warn-soft: rgba(138,106,34,.12);
  --info-soft: rgba(62,85,116,.10);
  --ok-fg: #2c4d38;
  --err-fg: #722d27;
  --warn-fg: #5f4915;
  --info-fg: #2a4052;
  --fig-1: #23211d;
  --fig-2: #3c5a72;
  --fig-3: #3f6b4f;
  --fig-4: #8a6a22;
  --fig-5: #6f587b;
  --fig-6: #b55f48;
  --ring: #2b2823;
  --glass: rgba(255,254,251,.66);
  --glass-strong: rgba(255,254,251,.90);
  --glass-border: rgba(255,255,255,.78);
  --glass-top: rgba(255,255,255,.90);
  --glass-hover: rgba(255,254,251,.99);
  --hair: rgba(35,33,29,.12);
  --sh: rgba(35,33,29,.13);
  --solid: #fffefb;
  --bloom: rgba(255,255,255,.85);
  --shadow-raised: 0 1px 2px rgba(35,33,29,.06);
  --shadow-float: 0 8px 32px rgba(35,33,29,.13);
  --radius-sm: 10px;
  --radius-md: 12px;
  --radius-lg: 18px;
  --radius-xl: 22px;
  --radius-xs: 6px;
  --fill-1: rgba(35,33,29,0.20);
  --fill-2: rgba(60,90,114,0.20);
  --fill-3: rgba(63,107,79,0.20);
  --fill-4: rgba(138,106,34,0.20);
  --fill-5: rgba(111,88,123,0.20);
  --fill-6: rgba(181,95,72,0.20);
}
html:root:where([data-theme="light"]) {
  color-scheme: light;
  --n-0: #fffefb;
  --n-2: #eae7e0;
  --n-3: #ded9d0;
  --n-5: #c0ad98;
  --bg: #f3f1ec;
  --bg-sunken: #e7e3da;
  --surface: rgba(255,254,251,.90);
  --surface-2: rgba(255,254,251,.72);
  --sunken: rgba(35,33,29,.05);
  --text: #23211d;
  --text-strong: #14120f;
  --text-soft: #67645e;
  --text-faint: #858179;
  --border: rgba(35,33,29,.15);
  --border-strong: rgba(35,33,29,.30);
  --rule: rgba(35,33,29,.22);
  --accent: #2b2823;
  --accent-hover: #14120f;
  --accent-fg: #fbfaf7;
  --accent-soft: rgba(35,33,29,.07);
  --accent-line: rgba(35,33,29,.28);
  --pen: #a04a3c;
  --ok: #3f6b4f;
  --err: #9c4038;
  --warn: #8a6a22;
  --info: #3e5574;
  --ok-soft: rgba(63,107,79,.11);
  --err-soft: rgba(156,64,56,.10);
  --warn-soft: rgba(138,106,34,.12);
  --info-soft: rgba(62,85,116,.10);
  --ok-fg: #2c4d38;
  --err-fg: #722d27;
  --warn-fg: #5f4915;
  --info-fg: #2a4052;
  --fig-1: #23211d;
  --fig-2: #3c5a72;
  --fig-3: #3f6b4f;
  --fig-4: #8a6a22;
  --fig-5: #6f587b;
  --fig-6: #b55f48;
  --ring: #2b2823;
  --glass: rgba(255,254,251,.66);
  --glass-strong: rgba(255,254,251,.90);
  --glass-border: rgba(255,255,255,.78);
  --glass-top: rgba(255,255,255,.90);
  --glass-hover: rgba(255,254,251,.99);
  --hair: rgba(35,33,29,.12);
  --sh: rgba(35,33,29,.13);
  --solid: #fffefb;
  --bloom: rgba(255,255,255,.85);
  --shadow-raised: 0 1px 2px rgba(35,33,29,.06);
  --shadow-float: 0 8px 32px rgba(35,33,29,.13);
  --radius-sm: 10px;
  --radius-md: 12px;
  --radius-lg: 18px;
  --radius-xl: 22px;
  --radius-xs: 6px;
  --fill-1: rgba(35,33,29,0.20);
  --fill-2: rgba(60,90,114,0.20);
  --fill-3: rgba(63,107,79,0.20);
  --fill-4: rgba(138,106,34,0.20);
  --fill-5: rgba(111,88,123,0.20);
  --fill-6: rgba(181,95,72,0.20);
}

/* ── Тушь и бумага · тёмная (явный выбор) ── */
html:root:where([data-theme="dark"]) {
  color-scheme: dark;
  --n-0: #262421;
  --n-2: #262421;
  --n-3: #332f2a;
  --n-5: #5b5349;
  --bg: #1c1b18;
  --bg-sunken: #141311;
  --surface: rgba(38,36,32,.88);
  --surface-2: rgba(50,47,42,.78);
  --sunken: rgba(0,0,0,.26);
  --text: #e8e5de;
  --text-strong: #fbf9f5;
  --text-soft: #a6a197;
  --text-faint: #857f75;
  --border: rgba(240,236,228,.14);
  --border-strong: rgba(240,236,228,.26);
  --rule: rgba(240,236,228,.18);
  --accent: #e8e5de;
  --accent-hover: #fbf9f5;
  --accent-fg: #1c1b18;
  --accent-soft: rgba(232,229,222,.13);
  --accent-line: rgba(232,229,222,.30);
  --pen: #d98b7e;
  --ok: #7fb894;
  --err: #e0918a;
  --warn: #cfb370;
  --info: #97b1d3;
  --ok-soft: rgba(127,184,148,.13);
  --err-soft: rgba(224,145,138,.13);
  --warn-soft: rgba(207,179,112,.13);
  --info-soft: rgba(151,177,211,.13);
  --ok-fg: #b6d9c3;
  --err-fg: #f0c2bd;
  --warn-fg: #ecd7ac;
  --info-fg: #c4d8e6;
  --fig-1: #e8e5de;
  --fig-2: #93b3cc;
  --fig-3: #7fb894;
  --fig-4: #d4b071;
  --fig-5: #bb9ac0;
  --fig-6: #be7a68;
  --ring: #e8e5de;
  --glass: rgba(46,44,40,.60);
  --glass-strong: rgba(38,36,32,.88);
  --glass-border: rgba(240,236,228,.11);
  --glass-top: rgba(240,236,228,.09);
  --glass-hover: rgba(54,51,46,.94);
  --hair: rgba(251,249,245,.10);
  --sh: rgba(0,0,0,.40);
  --solid: #262421;
  --bloom: rgba(240,236,228,.06);
  --shadow-raised: none;
  --shadow-float: 0 10px 34px rgba(0,0,0,.45);
  --radius-sm: 10px;
  --radius-md: 12px;
  --radius-lg: 18px;
  --radius-xl: 22px;
  --radius-xs: 6px;
  --fill-1: rgba(232,229,222,0.22);
  --fill-2: rgba(147,179,204,0.22);
  --fill-3: rgba(127,184,148,0.22);
  --fill-4: rgba(212,176,113,0.22);
  --fill-5: rgba(187,154,192,0.22);
  --fill-6: rgba(190,122,104,0.22);
}

/* ── Графит · светлая ── */
html:root:where([data-tone="graphite"]) {
  color-scheme: light;
  --n-0: #fcfdfe;
  --n-2: #e6e9eb;
  --n-3: #d8dcdf;
  --n-5: #aab2b7;
  --bg: #eff1f2;
  --bg-sunken: #e3e6e8;
  --surface: rgba(252,253,254,.90);
  --surface-2: rgba(252,253,254,.72);
  --sunken: rgba(30,35,38,.05);
  --text: #1e2326;
  --text-strong: #0f1315;
  --text-soft: #5e676c;
  --text-faint: #7c858a;
  --border: rgba(30,35,38,.15);
  --border-strong: rgba(30,35,38,.30);
  --rule: rgba(30,35,38,.22);
  --accent: #232a2e;
  --accent-hover: #0f1315;
  --accent-fg: #fbfcfd;
  --accent-soft: rgba(30,35,38,.07);
  --accent-line: rgba(30,35,38,.28);
  --pen: #3d6478;
  --ok: #35695a;
  --err: #96413c;
  --warn: #7d6524;
  --info: #3a517a;
  --ok-soft: rgba(53,105,90,.11);
  --err-soft: rgba(150,65,60,.10);
  --warn-soft: rgba(125,101,36,.12);
  --info-soft: rgba(58,81,122,.10);
  --ok-fg: #254b41;
  --err-fg: #6d2f2b;
  --warn-fg: #584718;
  --info-fg: #274050;
  --fig-1: #1e2326;
  --fig-2: #37556d;
  --fig-3: #35695a;
  --fig-4: #7d6524;
  --fig-5: #685e80;
  --fig-6: #6c3c4b;
  --ring: #232a2e;
  --glass: rgba(252,253,254,.66);
  --glass-strong: rgba(252,253,254,.90);
  --glass-border: rgba(255,255,255,.80);
  --glass-top: rgba(255,255,255,.92);
  --glass-hover: rgba(252,253,254,.99);
  --hair: rgba(30,35,38,.12);
  --sh: rgba(30,35,38,.13);
  --solid: #fcfdfe;
  --bloom: rgba(255,255,255,.88);
  --shadow-raised: 0 1px 2px rgba(30,35,38,.06);
  --shadow-float: 0 8px 32px rgba(30,35,38,.13);
  --radius-sm: 10px;
  --radius-md: 12px;
  --radius-lg: 18px;
  --radius-xl: 22px;
  --radius-xs: 6px;
  --fill-1: rgba(30,35,38,0.20);
  --fill-2: rgba(55,85,109,0.20);
  --fill-3: rgba(53,105,90,0.20);
  --fill-4: rgba(125,101,36,0.20);
  --fill-5: rgba(104,94,128,0.20);
  --fill-6: rgba(108,60,75,0.20);
}
html:root:where([data-tone="graphite"][data-theme="light"]) {
  color-scheme: light;
  --n-0: #fcfdfe;
  --n-2: #e6e9eb;
  --n-3: #d8dcdf;
  --n-5: #aab2b7;
  --bg: #eff1f2;
  --bg-sunken: #e3e6e8;
  --surface: rgba(252,253,254,.90);
  --surface-2: rgba(252,253,254,.72);
  --sunken: rgba(30,35,38,.05);
  --text: #1e2326;
  --text-strong: #0f1315;
  --text-soft: #5e676c;
  --text-faint: #7c858a;
  --border: rgba(30,35,38,.15);
  --border-strong: rgba(30,35,38,.30);
  --rule: rgba(30,35,38,.22);
  --accent: #232a2e;
  --accent-hover: #0f1315;
  --accent-fg: #fbfcfd;
  --accent-soft: rgba(30,35,38,.07);
  --accent-line: rgba(30,35,38,.28);
  --pen: #3d6478;
  --ok: #35695a;
  --err: #96413c;
  --warn: #7d6524;
  --info: #3a517a;
  --ok-soft: rgba(53,105,90,.11);
  --err-soft: rgba(150,65,60,.10);
  --warn-soft: rgba(125,101,36,.12);
  --info-soft: rgba(58,81,122,.10);
  --ok-fg: #254b41;
  --err-fg: #6d2f2b;
  --warn-fg: #584718;
  --info-fg: #274050;
  --fig-1: #1e2326;
  --fig-2: #37556d;
  --fig-3: #35695a;
  --fig-4: #7d6524;
  --fig-5: #685e80;
  --fig-6: #6c3c4b;
  --ring: #232a2e;
  --glass: rgba(252,253,254,.66);
  --glass-strong: rgba(252,253,254,.90);
  --glass-border: rgba(255,255,255,.80);
  --glass-top: rgba(255,255,255,.92);
  --glass-hover: rgba(252,253,254,.99);
  --hair: rgba(30,35,38,.12);
  --sh: rgba(30,35,38,.13);
  --solid: #fcfdfe;
  --bloom: rgba(255,255,255,.88);
  --shadow-raised: 0 1px 2px rgba(30,35,38,.06);
  --shadow-float: 0 8px 32px rgba(30,35,38,.13);
  --radius-sm: 10px;
  --radius-md: 12px;
  --radius-lg: 18px;
  --radius-xl: 22px;
  --radius-xs: 6px;
  --fill-1: rgba(30,35,38,0.20);
  --fill-2: rgba(55,85,109,0.20);
  --fill-3: rgba(53,105,90,0.20);
  --fill-4: rgba(125,101,36,0.20);
  --fill-5: rgba(104,94,128,0.20);
  --fill-6: rgba(108,60,75,0.20);
}

/* ── Графит · тёмная (явный выбор) ── */
html:root:where([data-tone="graphite"][data-theme="dark"]) {
  color-scheme: dark;
  --n-0: #22262a;
  --n-2: #22262a;
  --n-3: #2d3237;
  --n-5: #59636a;
  --bg: #16191b;
  --bg-sunken: #101314;
  --surface: rgba(34,38,42,.88);
  --surface-2: rgba(46,51,56,.78);
  --sunken: rgba(0,0,0,.26);
  --text: #e4e9eb;
  --text-strong: #f8fbfc;
  --text-soft: #9aa4aa;
  --text-faint: #7d868c;
  --border: rgba(228,233,235,.14);
  --border-strong: rgba(228,233,235,.26);
  --rule: rgba(228,233,235,.18);
  --accent: #e4e9eb;
  --accent-hover: #f8fbfc;
  --accent-fg: #16191b;
  --accent-soft: rgba(228,233,235,.13);
  --accent-line: rgba(228,233,235,.30);
  --pen: #8fb3c4;
  --ok: #6fae98;
  --err: #e0918a;
  --warn: #ceb67c;
  --info: #97b3d6;
  --ok-soft: rgba(111,174,152,.13);
  --err-soft: rgba(224,145,138,.13);
  --warn-soft: rgba(206,182,124,.13);
  --info-soft: rgba(151,179,214,.13);
  --ok-fg: #a9d3c4;
  --err-fg: #f0c2bd;
  --warn-fg: #e6d3ae;
  --info-fg: #c1d7e0;
  --fig-1: #e4e9eb;
  --fig-2: #8bb3ca;
  --fig-3: #6fae98;
  --fig-4: #cfb079;
  --fig-5: #b69abf;
  --fig-6: #e87044;
  --ring: #e4e9eb;
  --glass: rgba(42,47,51,.60);
  --glass-strong: rgba(34,38,42,.88);
  --glass-border: rgba(228,233,235,.11);
  --glass-top: rgba(228,233,235,.09);
  --glass-hover: rgba(48,54,58,.94);
  --hair: rgba(248,251,252,.10);
  --sh: rgba(0,0,0,.40);
  --solid: #22262a;
  --bloom: rgba(228,233,235,.06);
  --shadow-raised: none;
  --shadow-float: 0 10px 34px rgba(0,0,0,.45);
  --radius-sm: 10px;
  --radius-md: 12px;
  --radius-lg: 18px;
  --radius-xl: 22px;
  --radius-xs: 6px;
  --fill-1: rgba(228,233,235,0.22);
  --fill-2: rgba(139,179,202,0.22);
  --fill-3: rgba(111,174,152,0.22);
  --fill-4: rgba(207,176,121,0.22);
  --fill-5: rgba(182,154,191,0.22);
  --fill-6: rgba(232,112,68,0.22);
}

/* ── Газета · светлая ── */
html:root:where([data-tone="news"]) {
  color-scheme: light;
  --n-0: #ffffff;
  --n-2: #efece7;
  --n-3: #e2ded7;
  --n-5: #b6b1a9;
  --bg: #faf8f4;
  --bg-sunken: #efece7;
  --surface: rgba(255,255,255,.94);
  --surface-2: rgba(255,255,255,.80);
  --sunken: rgba(19,19,19,.04);
  --text: #1b1b1a;
  --text-strong: #131313;
  --text-soft: #5e5c58;
  --text-faint: #807d78;
  --border: rgba(19,19,19,.18);
  --border-strong: rgba(19,19,19,.38);
  --rule: rgba(19,19,19,.28);
  --accent: #131313;
  --accent-hover: #000000;
  --accent-fg: #faf8f4;
  --accent-soft: rgba(19,19,19,.06);
  --accent-line: rgba(19,19,19,.32);
  --pen: #b3261e;
  --ok: #2f6b45;
  --err: #b3261e;
  --warn: #7a5a10;
  --info: #2b4f7d;
  --ok-soft: rgba(47,107,69,.10);
  --err-soft: rgba(179,38,30,.09);
  --warn-soft: rgba(122,90,16,.11);
  --info-soft: rgba(43,79,125,.09);
  --ok-fg: #1f4b30;
  --err-fg: #801a14;
  --warn-fg: #543e0b;
  --info-fg: #1e3958;
  --fig-1: #131313;
  --fig-2: #2b4f7d;
  --fig-3: #2f6b45;
  --fig-4: #7a5a10;
  --fig-5: #60486a;
  --fig-6: #9e335f;
  --ring: #131313;
  --glass: rgba(255,255,255,.74);
  --glass-strong: rgba(255,255,255,.94);
  --glass-border: rgba(19,19,19,.10);
  --glass-top: rgba(255,255,255,.90);
  --glass-hover: #ffffff;
  --hair: rgba(19,19,19,.14);
  --sh: rgba(19,19,19,.10);
  --solid: #ffffff;
  --bloom: rgba(255,255,255,.75);
  --shadow-raised: 0 1px 2px rgba(19,19,19,.05);
  --shadow-float: 0 6px 24px rgba(19,19,19,.10);
  --radius-sm: 6px;
  --radius-md: 8px;
  --radius-lg: 10px;
  --radius-xl: 12px;
  --radius-xs: 4px;
  --fill-1: rgba(19,19,19,0.20);
  --fill-2: rgba(43,79,125,0.20);
  --fill-3: rgba(47,107,69,0.20);
  --fill-4: rgba(122,90,16,0.20);
  --fill-5: rgba(96,72,106,0.20);
  --fill-6: rgba(158,51,95,0.20);
}
html:root:where([data-tone="news"][data-theme="light"]) {
  color-scheme: light;
  --n-0: #ffffff;
  --n-2: #efece7;
  --n-3: #e2ded7;
  --n-5: #b6b1a9;
  --bg: #faf8f4;
  --bg-sunken: #efece7;
  --surface: rgba(255,255,255,.94);
  --surface-2: rgba(255,255,255,.80);
  --sunken: rgba(19,19,19,.04);
  --text: #1b1b1a;
  --text-strong: #131313;
  --text-soft: #5e5c58;
  --text-faint: #807d78;
  --border: rgba(19,19,19,.18);
  --border-strong: rgba(19,19,19,.38);
  --rule: rgba(19,19,19,.28);
  --accent: #131313;
  --accent-hover: #000000;
  --accent-fg: #faf8f4;
  --accent-soft: rgba(19,19,19,.06);
  --accent-line: rgba(19,19,19,.32);
  --pen: #b3261e;
  --ok: #2f6b45;
  --err: #b3261e;
  --warn: #7a5a10;
  --info: #2b4f7d;
  --ok-soft: rgba(47,107,69,.10);
  --err-soft: rgba(179,38,30,.09);
  --warn-soft: rgba(122,90,16,.11);
  --info-soft: rgba(43,79,125,.09);
  --ok-fg: #1f4b30;
  --err-fg: #801a14;
  --warn-fg: #543e0b;
  --info-fg: #1e3958;
  --fig-1: #131313;
  --fig-2: #2b4f7d;
  --fig-3: #2f6b45;
  --fig-4: #7a5a10;
  --fig-5: #60486a;
  --fig-6: #9e335f;
  --ring: #131313;
  --glass: rgba(255,255,255,.74);
  --glass-strong: rgba(255,255,255,.94);
  --glass-border: rgba(19,19,19,.10);
  --glass-top: rgba(255,255,255,.90);
  --glass-hover: #ffffff;
  --hair: rgba(19,19,19,.14);
  --sh: rgba(19,19,19,.10);
  --solid: #ffffff;
  --bloom: rgba(255,255,255,.75);
  --shadow-raised: 0 1px 2px rgba(19,19,19,.05);
  --shadow-float: 0 6px 24px rgba(19,19,19,.10);
  --radius-sm: 6px;
  --radius-md: 8px;
  --radius-lg: 10px;
  --radius-xl: 12px;
  --radius-xs: 4px;
  --fill-1: rgba(19,19,19,0.20);
  --fill-2: rgba(43,79,125,0.20);
  --fill-3: rgba(47,107,69,0.20);
  --fill-4: rgba(122,90,16,0.20);
  --fill-5: rgba(96,72,106,0.20);
  --fill-6: rgba(158,51,95,0.20);
}

/* ── Газета · тёмная (явный выбор) ── */
html:root:where([data-tone="news"][data-theme="dark"]) {
  color-scheme: dark;
  --n-0: #242321;
  --n-2: #242321;
  --n-3: #31302d;
  --n-5: #5c5a55;
  --bg: #191817;
  --bg-sunken: #111110;
  --surface: rgba(36,35,33,.90);
  --surface-2: rgba(48,46,43,.80);
  --sunken: rgba(0,0,0,.28);
  --text: #f2f0ec;
  --text-strong: #ffffff;
  --text-soft: #a3a09a;
  --text-faint: #827f79;
  --border: rgba(242,240,236,.16);
  --border-strong: rgba(242,240,236,.34);
  --rule: rgba(242,240,236,.22);
  --accent: #f2f0ec;
  --accent-hover: #ffffff;
  --accent-fg: #191817;
  --accent-soft: rgba(242,240,236,.12);
  --accent-line: rgba(242,240,236,.32);
  --pen: #e0645a;
  --ok: #6fae8b;
  --err: #e88a80;
  --warn: #e8b45f;
  --info: #8fb0d4;
  --ok-soft: rgba(111,174,139,.13);
  --err-soft: rgba(232,138,128,.13);
  --warn-soft: rgba(232,180,95,.13);
  --info-soft: rgba(143,176,212,.13);
  --ok-fg: #a8d4bd;
  --err-fg: #f4bfb8;
  --warn-fg: #f0d7a6;
  --info-fg: #c2d6e8;
  --fig-1: #f2f0ec;
  --fig-2: #8fb0d4;
  --fig-3: #6fae8b;
  --fig-4: #e8b45f;
  --fig-5: #bb9ab9;
  --fig-6: #e36157;
  --ring: #f2f0ec;
  --glass: rgba(44,42,40,.62);
  --glass-strong: rgba(36,35,33,.90);
  --glass-border: rgba(242,240,236,.12);
  --glass-top: rgba(242,240,236,.08);
  --glass-hover: rgba(52,50,47,.95);
  --hair: rgba(255,255,255,.10);
  --sh: rgba(0,0,0,.42);
  --solid: #242321;
  --bloom: rgba(242,240,236,.05);
  --shadow-raised: none;
  --shadow-float: 0 8px 28px rgba(0,0,0,.45);
  --radius-sm: 6px;
  --radius-md: 8px;
  --radius-lg: 10px;
  --radius-xl: 12px;
  --radius-xs: 4px;
  --fill-1: rgba(242,240,236,0.22);
  --fill-2: rgba(143,176,212,0.22);
  --fill-3: rgba(111,174,139,0.22);
  --fill-4: rgba(232,180,95,0.22);
  --fill-5: rgba(187,154,185,0.22);
  --fill-6: rgba(227,97,87,0.22);
}

/* Пользователь не выбирал тему — идём за системой. */
@media (prefers-color-scheme: dark) {
  html:root:where(:not([data-theme="light"])) {
    color-scheme: dark;
    --n-0: #262421;
    --n-2: #262421;
    --n-3: #332f2a;
    --n-5: #5b5349;
    --bg: #1c1b18;
    --bg-sunken: #141311;
    --surface: rgba(38,36,32,.88);
    --surface-2: rgba(50,47,42,.78);
    --sunken: rgba(0,0,0,.26);
    --text: #e8e5de;
    --text-strong: #fbf9f5;
    --text-soft: #a6a197;
    --text-faint: #857f75;
    --border: rgba(240,236,228,.14);
    --border-strong: rgba(240,236,228,.26);
    --rule: rgba(240,236,228,.18);
    --accent: #e8e5de;
    --accent-hover: #fbf9f5;
    --accent-fg: #1c1b18;
    --accent-soft: rgba(232,229,222,.13);
    --accent-line: rgba(232,229,222,.30);
    --pen: #d98b7e;
    --ok: #7fb894;
    --err: #e0918a;
    --warn: #cfb370;
    --info: #97b1d3;
    --ok-soft: rgba(127,184,148,.13);
    --err-soft: rgba(224,145,138,.13);
    --warn-soft: rgba(207,179,112,.13);
    --info-soft: rgba(151,177,211,.13);
    --ok-fg: #b6d9c3;
    --err-fg: #f0c2bd;
    --warn-fg: #ecd7ac;
    --info-fg: #c4d8e6;
    --fig-1: #e8e5de;
    --fig-2: #93b3cc;
    --fig-3: #7fb894;
    --fig-4: #d4b071;
    --fig-5: #bb9ac0;
    --fig-6: #be7a68;
    --ring: #e8e5de;
    --glass: rgba(46,44,40,.60);
    --glass-strong: rgba(38,36,32,.88);
    --glass-border: rgba(240,236,228,.11);
    --glass-top: rgba(240,236,228,.09);
    --glass-hover: rgba(54,51,46,.94);
    --hair: rgba(251,249,245,.10);
    --sh: rgba(0,0,0,.40);
    --solid: #262421;
    --bloom: rgba(240,236,228,.06);
    --shadow-raised: none;
    --shadow-float: 0 10px 34px rgba(0,0,0,.45);
    --radius-sm: 10px;
    --radius-md: 12px;
    --radius-lg: 18px;
    --radius-xl: 22px;
    --radius-xs: 6px;
    --fill-1: rgba(232,229,222,0.22);
    --fill-2: rgba(147,179,204,0.22);
    --fill-3: rgba(127,184,148,0.22);
    --fill-4: rgba(212,176,113,0.22);
    --fill-5: rgba(187,154,192,0.22);
    --fill-6: rgba(190,122,104,0.22);
  }
  html:root:where([data-tone="graphite"]:not([data-theme="light"])) {
    color-scheme: dark;
    --n-0: #22262a;
    --n-2: #22262a;
    --n-3: #2d3237;
    --n-5: #59636a;
    --bg: #16191b;
    --bg-sunken: #101314;
    --surface: rgba(34,38,42,.88);
    --surface-2: rgba(46,51,56,.78);
    --sunken: rgba(0,0,0,.26);
    --text: #e4e9eb;
    --text-strong: #f8fbfc;
    --text-soft: #9aa4aa;
    --text-faint: #7d868c;
    --border: rgba(228,233,235,.14);
    --border-strong: rgba(228,233,235,.26);
    --rule: rgba(228,233,235,.18);
    --accent: #e4e9eb;
    --accent-hover: #f8fbfc;
    --accent-fg: #16191b;
    --accent-soft: rgba(228,233,235,.13);
    --accent-line: rgba(228,233,235,.30);
    --pen: #8fb3c4;
    --ok: #6fae98;
    --err: #e0918a;
    --warn: #ceb67c;
    --info: #97b3d6;
    --ok-soft: rgba(111,174,152,.13);
    --err-soft: rgba(224,145,138,.13);
    --warn-soft: rgba(206,182,124,.13);
    --info-soft: rgba(151,179,214,.13);
    --ok-fg: #a9d3c4;
    --err-fg: #f0c2bd;
    --warn-fg: #e6d3ae;
    --info-fg: #c1d7e0;
    --fig-1: #e4e9eb;
    --fig-2: #8bb3ca;
    --fig-3: #6fae98;
    --fig-4: #cfb079;
    --fig-5: #b69abf;
    --fig-6: #e87044;
    --ring: #e4e9eb;
    --glass: rgba(42,47,51,.60);
    --glass-strong: rgba(34,38,42,.88);
    --glass-border: rgba(228,233,235,.11);
    --glass-top: rgba(228,233,235,.09);
    --glass-hover: rgba(48,54,58,.94);
    --hair: rgba(248,251,252,.10);
    --sh: rgba(0,0,0,.40);
    --solid: #22262a;
    --bloom: rgba(228,233,235,.06);
    --shadow-raised: none;
    --shadow-float: 0 10px 34px rgba(0,0,0,.45);
    --radius-sm: 10px;
    --radius-md: 12px;
    --radius-lg: 18px;
    --radius-xl: 22px;
    --radius-xs: 6px;
    --fill-1: rgba(228,233,235,0.22);
    --fill-2: rgba(139,179,202,0.22);
    --fill-3: rgba(111,174,152,0.22);
    --fill-4: rgba(207,176,121,0.22);
    --fill-5: rgba(182,154,191,0.22);
    --fill-6: rgba(232,112,68,0.22);
  }
  html:root:where([data-tone="news"]:not([data-theme="light"])) {
    color-scheme: dark;
    --n-0: #242321;
    --n-2: #242321;
    --n-3: #31302d;
    --n-5: #5c5a55;
    --bg: #191817;
    --bg-sunken: #111110;
    --surface: rgba(36,35,33,.90);
    --surface-2: rgba(48,46,43,.80);
    --sunken: rgba(0,0,0,.28);
    --text: #f2f0ec;
    --text-strong: #ffffff;
    --text-soft: #a3a09a;
    --text-faint: #827f79;
    --border: rgba(242,240,236,.16);
    --border-strong: rgba(242,240,236,.34);
    --rule: rgba(242,240,236,.22);
    --accent: #f2f0ec;
    --accent-hover: #ffffff;
    --accent-fg: #191817;
    --accent-soft: rgba(242,240,236,.12);
    --accent-line: rgba(242,240,236,.32);
    --pen: #e0645a;
    --ok: #6fae8b;
    --err: #e88a80;
    --warn: #e8b45f;
    --info: #8fb0d4;
    --ok-soft: rgba(111,174,139,.13);
    --err-soft: rgba(232,138,128,.13);
    --warn-soft: rgba(232,180,95,.13);
    --info-soft: rgba(143,176,212,.13);
    --ok-fg: #a8d4bd;
    --err-fg: #f4bfb8;
    --warn-fg: #f0d7a6;
    --info-fg: #c2d6e8;
    --fig-1: #f2f0ec;
    --fig-2: #8fb0d4;
    --fig-3: #6fae8b;
    --fig-4: #e8b45f;
    --fig-5: #bb9ab9;
    --fig-6: #e36157;
    --ring: #f2f0ec;
    --glass: rgba(44,42,40,.62);
    --glass-strong: rgba(36,35,33,.90);
    --glass-border: rgba(242,240,236,.12);
    --glass-top: rgba(242,240,236,.08);
    --glass-hover: rgba(52,50,47,.95);
    --hair: rgba(255,255,255,.10);
    --sh: rgba(0,0,0,.42);
    --solid: #242321;
    --bloom: rgba(242,240,236,.05);
    --shadow-raised: none;
    --shadow-float: 0 8px 28px rgba(0,0,0,.45);
    --radius-sm: 6px;
    --radius-md: 8px;
    --radius-lg: 10px;
    --radius-xl: 12px;
    --radius-xs: 4px;
    --fill-1: rgba(242,240,236,0.22);
    --fill-2: rgba(143,176,212,0.22);
    --fill-3: rgba(111,174,139,0.22);
    --fill-4: rgba(232,180,95,0.22);
    --fill-5: rgba(187,154,185,0.22);
    --fill-6: rgba(227,97,87,0.22);
  }
}

/* ─── 2/4 МОСТ СТАРЫХ ИМЁН ───────────────────────────────── */
/* ============================================================================
   СУПРЕМУМ · sup-compat.css — мост от старых имён к новым токенам
   ============================================================================
   Требует sup-tokens.css. Подключается СРАЗУ ПОСЛЕ него и ПЕРЕД
   theory.css / practice.css / exam.css / app-shell.css / supremum.css.

   ЗАЧЕМ. На сайте 512 страниц теории, 56 страниц практики и 4 экзаменационных.
   В их разметке и во встроенных стилях зашиты старые имена переменных:
   --glass-bg, --glass-border, --muted, --c-blue, --shadow-md и ещё 64 штуки.
   Переписать их означало бы править 572 файла. Этот файл переводит все старые
   имена на новые токены, поэтому страницы получают новое оформление
   БЕЗ ЕДИНОЙ ПРАВКИ РАЗМЕТКИ.

   Файл переходный. Порядок вывода из работы описан в плане (фаза 8): по мере
   того как раздел переводится на новые имена, соответствующие строки отсюда
   удаляются. Пустой файл = миграция закончена.

   ВАЖНО ПРО ПОРЯДОК. У страниц теории встроенный <style> идёт ПОСЛЕ ссылки
   на CSS и перебивает его. Если на странице остался свой --accent или свой
   фон body, он победит этот мост. Такие остатки ищет
   tools\design_system\audit_inline.py — он же считает, сколько их осталось.
   ============================================================================ */

/* СПЕЦИФИЧНОСТЬ. Блок намеренно html:root, а не голый :root. Слой токенов
   (sup-tokens-paper.css) выровнен на (0,1,1) во всех шести сочетаниях
   тональность × тема — иначе базовая тональность проигрывала палитре v1
   в supremum.css (html[data-theme="dark"], тоже (0,1,1)). Мост обязан
   оставаться ПОСЛЕДНИМ словом для старых имён: три из них — --glass,
   --glass-strong, --glass-border — он намеренно переводит на плотные
   поверхности. При голом :root (0,1,0) мост проигрывал бы токенам, и
   полупрозрачность вернулась бы под учебный текст. */
html:root {
  /* ── Подложки и поверхности ──────────────────────────────────────────────
     Раньше это было «стекло»: полупрозрачный белый плюс backdrop-filter.
     Стало непрозрачной поверхностью. Полупрозрачность убрана сознательно:
     на ней невозможно гарантировать контраст текста — он зависит от того,
     что оказалось под ней, и WCAG-замер на стекле нарушался легче всего. */
  --bg-base: var(--bg);
  --glass: var(--surface);
  --glass-bg: var(--surface);
  --glass-strong: var(--surface);
  --card: var(--surface);
  --tile-bg: var(--n-2);
  --viz-bg: var(--surface);
  --open-pt-fill: var(--surface);
  --ui-surface: var(--surface);
  --ui-surface-strong: var(--n-2);
  --ui-track: var(--n-3);

  /* ── Границы и линии ── */
  --glass-border: var(--border);
  --ui-border: var(--border);

  /* ── ЧЕРТЁЖНАЯ ПУНКТИРНАЯ ЛИНИЯ ≠ ВОЛОСЯНАЯ ЛИНЕЙКА ──────────────────────
     Здесь стояло --c-dashed: var(--rule), и это была подмена роли. --rule —
     разделительная линейка вёрстки, ей положено быть еле заметной; --c-dashed
     на 289 страницах рисует вспомогательное построение — и не только штрихом:
     264 страницы берут её из JS и красят ею ПОДПИСЬ («a», «D»), то есть текст.
     Замер на «сумме углов треугольника»: подпись «a» к холсту 2.00 → 1.57
     в светлой теме и 2.25 → 1.67 в тёмной при пороге 4.5. Единственное место,
     где перевод сделал читаемость хуже, чем была.

     Ведём на --text-soft — роль «текст второго плана», у которой генератор
     палитры проверяет ≥ 4.5 на каждой подложке во всех шести сочетаниях
     тональность × тема (tools\design_system\palette.py, check_paper, п. 1).
     Стало 5.63…6.67. Она нейтральная — вспомогательная линия остаётся
     подчинённой, ровно как исходный #94a3b8, а не превращается во второй
     чернильный объект.

     Почему не --fig-1: контраст был бы 15.8, но fig-1 — это те же чернила,
     что и --c-base, которым нарисована сама фигура (расстояние 0.000), то есть
     построение слилось бы с построенным на КАЖДОЙ странице. Остаток: до
     --fig-5 нейтраль отходит на 0.051…0.077 при пороге различимости линий
     0.075 — принято, потому что пунктир отличается от сплошной штрихом,
     а не только цветом. */
  --c-dashed: var(--text-soft);

  /* ── Текст ── */
  --muted: var(--text-soft);
  --gray: var(--text-soft);
  --c-base: var(--text);
  --text-lh: var(--lh-md);

  /* ── Градиентные пятна на body: ВЫКЛЮЧЕНЫ ────────────────────────────────
     Три радиальных градиента pink/blue/purple лежали на body и в theory.css,
     и в supremum.css. Это самый узнаваемый штамп ИИ-вёрстки, и на странице
     теории они были почти вдвое насыщеннее, чем в хабе (.55 против .28) —
     то есть половины сайта расходились даже по фону. Правила, рисующие
     их, никуда не делись, но красить им теперь нечем: прозрачное.
     Взамен фактура из мира предмета — клетка, см. sup-base.css. */
  --glow-1: transparent;
  --glow-2: transparent;
  --glow-3: transparent;
  --glow1: transparent;
  --glow2: transparent;
  --glow3: transparent;

  /* ── Тени ────────────────────────────────────────────────────────────────
     Было три ступени в theory.css плюс одна безымянная --shadow в остальных
     файлах. Сведены к возвышению из токенов: сначала граница, тень только
     у того, что действительно висит над страницей. */
  --shadow: var(--shadow-raised);
  --shadow-sm: var(--shadow-raised);
  --shadow-md: var(--shadow-float);
  --shadow-lg: var(--shadow-modal);
  --glass-shadow: var(--shadow-float);
  --ui-shadow: var(--shadow-raised);
  --ui-shadow-lift: var(--shadow-float);

  /* ── Радиусы ─────────────────────────────────────────────────────────────
     Было 14 разных значений в practice.css, 12 в exam.css, 11 в app-shell.css
     и 22px литералом в supremum.css. Стало шесть ступеней из токенов. */
  --ui-radius: var(--radius-md);
  --ui-radius-card: var(--radius-lg);
  --radius-md-sb: var(--radius-md);
  --radius-lg-sb: var(--radius-lg);

  /* ── Движение и фокус ── */
  --ui-ease: var(--ease-out);
  --ease-out-sb: var(--ease-out);
  --ui-ring: var(--ring);
  --shadow-sm-sb: var(--shadow-raised);

  /* ── Раскладка ── */
  --hdr: 64px;
  --sbw: 260px;      /* ширина сайдбара оболочки */

  /* ── Смысловые цвета под старыми именами ─────────────────────────────────
     Здесь ничего не «переименовано ради красоты»: старые имена --green/--red/
     --amber/--blue означали ровно роли «верно / ошибка / внимание / факт»
     и теперь ведут на смысловые токены. */
  --green: var(--ok);
  --red: var(--err);
  --amber: var(--warn);
  --blue: var(--info);

  --def-bg: var(--ok-soft);
  --def-border: var(--ok);
  --exmp-bg: var(--info-soft);
  --exmp-border: var(--info);
  --memo-bg: var(--warn-soft);
  --memo-border: var(--warn);
  --mist-bg: var(--err-soft);
  --mist-border: var(--err);
  --mistake-bg: var(--err-soft);
  --mistake-border: var(--err);

  /* Мягкие подложки-«дымки» из старой системы */
  --f-green: var(--ok-soft);
  --f-red: var(--err-soft);
  --f-orange: var(--warn-soft);
  --f-blue: var(--info-soft);
  --f-purple: var(--accent-soft);

  /* ── ПАЛИТРА ЧЕРТЕЖА ─────────────────────────────────────────────────────
     Это НЕ смысловые цвета. Ими раскрашивают разные объекты одного чертежа:
     прямая a синяя, прямая b фиолетовая, дуга угла оранжевая. Задача здесь
     другая — чтобы линии отличались ДРУГ ОТ ДРУГА, а не от «ошибки».

     Сами значения --fig-* живут в sup-tokens.css: это НОВЫЕ имена, часть
     системы, а не совместимость. Здесь только перевод старых имён на них.

     Осторожно: на старых страницах дуги углов рисуются --c-red, и на чертеже
     это читается как «здесь ошибка», хотя значит «вот этот угол». Поэтому
     --c-red ведёт НЕ на смысловой красный, а на винный --fig-6: тёплый
     и заметный, но не кричащий «неверно».

     Свести --c-red и --c-orange в один цвет нельзя: 180 страниц из 516
     используют их ОДНОВРЕМЕННО, то есть различают этим два разных угла
     на одном чертеже. Проверено перебором по всем материалам.

     ── ПОЧЕМУ ИМЯ ВСЁ-ТАКИ ВАЖНО (пересмотрено 21.08.2026) ────────────────
     Сначала имена считались неважными: раз цвета лишь отличают объекты друг
     от друга, любая перестановка годится. Перебор по материалам это опроверг:
     99 страниц теории из 511 называют цвет СЛОВАМИ в тексте — «перетаскивай
     оранжевые точки», «потяни за вершину синего треугольника», «площади
     синего и зелёного квадратов». Всего 247 упоминаний. При прежней
     перестановке синий уезжал в чернила, а оранжевый в лиловый, и текст
     переставал описывать то, что ученик видит.

     Различимость от перестановки не страдает: все шесть --fig-* уже
     проверены генератором палитры на различимость, в том числе при
     дальтонизме. Поэтому имена сопоставлены по смыслу.

     Исключение — --c-teal: седьмого цвета в палитре нет, а бирюзовый
     встречается на 3 страницах и ни разу не назван словом в тексте
     (проверено). Он и уступает чернила, оставаясь отличимым от синего
     и зелёного, с которыми делит чертёж. */
  --c-blue: var(--fig-2);     /* синевато-серый  */
  --c-green: var(--fig-3);    /* зелёный         */
  --c-orange: var(--fig-4);   /* охра, тёплый    */
  --c-purple: var(--fig-5);   /* лиловый         */
  --c-red: var(--fig-6);      /* терракота       */
  --c-teal: var(--fig-1);     /* чернила, см. исключение выше */

  /* Акцент главы в практике: по умолчанию чернила. Разделы, где у главы свой
     оттенок, переопределяют эту переменную у себя — она для этого и заведена. */
  --chapter-accent: var(--accent);
}

/* ── ЧТО МОСТ ПОЧИНИТЬ НЕ МОЖЕТ ────────────────────────────────────────────
   Переменную он подменяет, а захардкоженное значение — нет. По переписи
   (tools\design_audit\token_census.py) литеральных цветов вне блоков токенов:
   practice.css — 57, exam.css — 40, theory.css — 24, app-shell.css — 19,
   supremum.css — 16. Их правят в самих файлах, раздел за разделом, и это
   и есть содержание задач 8.5–8.8 плана.

   Три места видны сразу и правятся первыми, потому что бьют по всем страницам:
   · body { font-family: 'Segoe UI', system-ui } в theory.css и
     -apple-system в supremum.css — шрифт мимо системы, страница выглядит
     по-разному на Windows и на Mac;
   · backdrop-filter: blur(...) на шапке, карточках и коробке интерактива;
   · transform: translateY(-2px) на наведении у кнопок, карточек и разделов.
   ──────────────────────────────────────────────────────────────────────── */

/* ─── 3/4 КАНОН ПРАВИЛ (без блоков переменных) ───────────── */
/* theory.css — общие стили страниц теории СУПРЕМУМ.
 * Собран автоматически: tools\theory_css\theory_css.py build
 * Источник канона — canon.json (порог: правило не реже чем в 15% из 512 страниц).
 * Руками не правим значения вслепую: страницы могут нести inline-override,
 * который идёт после <link> и перебивает этот файл. */



* {
  box-sizing: border-box;
}
a, button {
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
  font-family: inherit;
}
a:focus-visible, button:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px var(--bg-base),0 0 0 4px var(--ring);
  border-radius: var(--radius-sm);
}
body {
  font-family: 'Segoe UI',system-ui,sans-serif;
  color: var(--text);
  margin: 0;
  padding-top: var(--hdr);
  background: var(--bg-base);
  background-image: radial-gradient(ellipse 50% 60% at 15% 10%,var(--glow-1),transparent),radial-gradient(ellipse 55% 65% at 85% 15%,var(--glow-2),transparent),radial-gradient(ellipse 60% 70% at 50% 95%,var(--glow-3),transparent);
  background-attachment: fixed;
  transition: background .3s,color .3s;
}
header.page-header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: var(--hdr);
  z-index: 100;
  background: var(--glass-strong);
  backdrop-filter: blur(18px);
  border-bottom: 1px solid var(--glass-border);
  color: var(--text);
  display: flex;
  align-items: center;
  padding: 0 24px;
  gap: 16px;
}
.theme-toggle {
  margin-left: auto;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  border: 1px solid var(--glass-border);
  background: var(--tile-bg);
  color: var(--text);
  font-size: 1.1rem;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: transform .15s;
}
.theme-toggle:hover {
  transform: scale(1.08);
}
.page-split {
  display: block;
}
.theory-col {
  width: 50%;
  box-sizing: border-box;
  padding: 28px 32px 80px;
  min-height: calc(100vh - var(--hdr));
}
.interactive-col {
  position: fixed;
  right: 0;
  top: var(--hdr);
  width: 50%;
  height: calc(100vh - var(--hdr));
  z-index: 50;
  overflow: hidden;
  padding: 16px 20px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
}
.interactive-col svg, .interactive-col canvas, .interactive-col .viz-block {
  margin: 0 auto;
}
@keyframes cardFadeUp {to { opacity: 1; transform: translateY(0); }}
.card {
  background: var(--glass-bg);
  backdrop-filter: blur(14px);
  border: 1px solid var(--glass-border);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-sm);
  padding: 24px 26px;
  margin: 20px 0;
  color: var(--text);
  opacity: 0;
  transform: translateY(10px);
  animation: cardFadeUp .5s var(--ease-out) forwards;
}
.card h1 {
  font-size: 1.55rem;
  margin: 0 0 6px;
}
.card h2 {
  font-size: 1.3rem;
  margin: 0 0 12px;
  color: var(--text-soft);
  line-height: 1.3;
}
.card p, .card li, .definition, .highlight, .memo, .mistake {
  line-height: var(--text-lh);
}
.katex {
  font-size: 1.08em;
  vertical-align: middle;
}
.card p:has(> .katex-display:only-child) {
  text-align: center;
}
.katex-display {
  text-align: center;
  text-align-last: center;
}
.katex-display .katex {
  font-size: 1.25em;
}
.card p:has(> .katex:only-child), .card p:has(> .katex-display:only-child), .card li:has(> .katex:only-child), .definition:has(> .katex-display:only-child), .highlight:has(> .katex-display:only-child), .memo:has(> .katex-display:only-child), .mistake:has(> .katex-display:only-child) {
  text-align: center !important;
  text-align-last: center !important;
}
@keyframes fadeIn {from { opacity:0; } to { opacity:1; }}
@keyframes drawStroke {to { stroke-dashoffset: 0; }}
@keyframes fadeScaleIn {from { opacity:0; transform:scale(0.6); } to { opacity:1; transform:scale(1); }}
.card p:has(> .katex:only-child), .card p:has(> .katex-display:only-child), .card li:has(> .katex:only-child), .definition:has(> .katex:only-child), .definition:has(> .katex-display:only-child), .highlight:has(> .katex:only-child), .highlight:has(> .katex-display:only-child), .memo:has(> .katex:only-child), .memo:has(> .katex-display:only-child), .mistake:has(> .katex:only-child), .mistake:has(> .katex-display:only-child) {
  text-align: center !important;
  text-align-last: center !important;
}
.definition, .highlight, .memo, .mistake {
  gap: 12px;
  align-items: flex-start;
  border-radius: var(--radius-lg);
  padding: 14px 18px;
  margin: 20px 0;
  border: 1px solid transparent;
  color: var(--text);
  transition: background .3s,border-color .3s;
}
.definition {
  background: var(--def-bg);
  border-color: rgba(5,150,105,.25);
}
.highlight {
  background: var(--exmp-bg);
  border-color: rgba(37,99,235,.25);
}
.memo {
  background: var(--memo-bg);
  border-color: rgba(217,119,6,.25);
}
.mistake {
  background: var(--mist-bg);
  border-color: rgba(220,38,38,.25);
}
[data-theme="dark"] .mistake {
  background: rgba(248,113,113,.1);
  border-left-color: #f87171;
}
.definition .a-icon, .highlight .a-icon, .memo .a-icon, .mistake .a-icon {
  font-size: 1.05rem;
  line-height: 1.5;
  flex-shrink: 0;
}
.proof-step.step-visible {
  opacity: 1;
  transform: translateY(0);
}
.definition .a-body, .highlight .a-body, .memo .a-body, .mistake .a-body {
  font-size: .96rem;
  line-height: 1.55;
}
.proof-step {
  display: flex;
  gap: 14px;
  align-items: flex-start;
  padding: 12px 0;
  border-bottom: 1px solid var(--glass-border);
}
.btn {
  --h: 2.35rem;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 0 16px;
  border-radius: var(--radius-md);
  font-weight: 600;
  font-size: .88rem;
  cursor: pointer;
  border: 1px solid transparent;
  transition: background .18s,color .18s,border-color .18s,transform .12s var(--ease-out),box-shadow .18s;
}
.hl:hover {
  background: #fef3c7;
}
.definition .a-title, .highlight .a-title, .memo .a-title, .mistake .a-title {
  font-weight: 700;
  margin-bottom: 2px;
}
.btn:active {
  transform: scale(.96);
}
[data-theme="dark"] .hl:hover {
  background: rgba(251,191,36,.25);
}
.proof-step:last-child {
  border-bottom: none;
}
.btn:disabled {
  opacity: .55;
  cursor: default;
  transform: none !important;
}
.proof-step .num {
  background: var(--c-blue);
  color: white;
  border-radius: 50%;
  align-items: center;
  justify-content: center;
  font-weight: 700;
  flex-shrink: 0;
  font-size: .9rem;
}
.hl {
  cursor: pointer;
  border-bottom: 1.5px dashed #d97706;
  transition: background .1s;
}
.btn-outline {
  background: var(--glass-strong);
  color: var(--text);
  border-color: var(--glass-border);
}
.btn-outline:hover:not(:disabled) {
  background: var(--tile-bg);
  border-color: var(--accent);
}
.proof-step .txt {
  font-size: .96rem;
  line-height: 1.55;
}
.viz-inner {
  padding: 22px 22px 8px;
}
.step-btn:hover {
  background: var(--glass-strong);
  border-color: var(--accent);
}
.btn-outline.active, .btn-outline.active:hover:not(:disabled) {
  background: var(--accent);
  color: white;
  border-color: var(--accent);
}
.viz-block {
  background: var(--viz-bg);
  backdrop-filter: blur(16px);
  border: 1px solid var(--glass-border);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-md);
  overflow: hidden;
  margin: 24px 0;
  user-select: none;
  -webkit-user-select: none;
}
.tab-btn {
  background: var(--tile-bg);
  border: 1px solid var(--glass-border);
  border-radius: var(--radius-md);
  padding: 8px 14px;
  font-size: .84rem;
  font-weight: 600;
  cursor: pointer;
  color: var(--text);
  transition: all .15s var(--ease-out);
}
.tab-btn:hover {
  background: var(--glass-strong);
  border-color: var(--accent);
}
.viz-block canvas, .viz-block svg {
  touch-action: none;
  margin: 0 auto;
}
.btn-sm {
  --h: 1.95rem;
  padding: 0 12px;
  font-size: .8rem;
}
.tab-btn.active {
  background: var(--accent);
  color: #fff;
  border-color: var(--accent);
}
.viz-caption {
  padding: 10px 18px;
  font-size: 0.88rem;
  color: var(--gray);
  text-align: center;
  border-top: 1px solid var(--glass-border);
  background: var(--glass-bg);
}
.step-btn {
  --h: 2.1rem;
  align-items: center;
  justify-content: center;
  padding: 0 16px;
  border-radius: var(--radius-md);
  font-weight: 600;
  font-size: .85rem;
  cursor: pointer;
  border: 1px solid var(--glass-border);
  background: var(--accent);
  color: white;
  transition: background .2s ease,opacity .2s ease,transform .12s var(--ease-out);
}
.step-btn:disabled {
  opacity: .55;
  cursor: default;
}
.tab-row {
  gap: 8px;
  justify-content: center;
  padding: 10px 14px 0;
}
.formula-box {
  padding: 10px 18px;
  font-size: .92rem;
  text-align: center;
  border-top: 1px solid var(--glass-border);
  background: var(--glass-bg);
  color: var(--text);
  line-height: 1.6;
  min-height: 1.4em;
  transition: color .2s;
}
.formula-box b {
  color: var(--accent);
}
.step-btn:active {
  transform: scale(.96);
}
.status-badge {
  display: inline-block;
  margin-top: 6px;
  padding: 3px 12px;
  border-radius: 999px;
  font-size: 1rem;
  font-weight: 700;
}
.slider-row span.lbl {
  font-size: .85rem;
  color: var(--gray);
}
.slider-row {
  align-items: center;
  gap: 10px;
  padding: 10px 18px 0;
}
.slider-row span.val {
  font-size: .9rem;
  font-weight: 600;
  text-align: right;
  color: var(--text);
}
.viz-block svg circle, .viz-block svg line, .viz-block svg text, .viz-block svg rect, .viz-block svg polyline, .viz-block svg path {
  transition: stroke .2s ease,fill .2s ease,stroke-width .2s ease,opacity .2s ease;
}
.slider-row input[type=range] {
  accent-color: var(--accent);
}
.topic-nav {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: stretch;
  gap: 12px;
  margin-top: 48px;
}
.topic-nav-side {
  display: flex;
  flex-direction: column;
  gap: 2px;
  text-decoration: none;
  min-width: 0;
  overflow: hidden;
  width: fit-content;
  max-width: 100%;
  background: var(--glass-bg);
  backdrop-filter: blur(10px);
  border: 1px solid var(--glass-border);
  border-radius: var(--radius-lg);
  padding: 12px 16px;
  box-shadow: var(--shadow-sm);
  transition: transform .15s var(--ease-out),background .15s,box-shadow .15s;
}
.draw-in-stroke {
  animation: drawStroke .7s ease forwards;
}
.draw-in-fill {
  transform-box: fill-box;
  transform-origin: center;
  animation: fadeScaleIn .4s ease forwards;
}
.topic-nav-side:hover {
  transform: translateY(-2px);
  background: var(--tile-bg);
  box-shadow: var(--shadow-md);
}
.topic-nav-side:empty {
  background: none;
  border: none;
  padding: 0;
  width: auto;
  box-shadow: none;
}
.draw-in-fade {
  animation: fadeIn .5s ease forwards;
}
.topic-nav-prev {
  text-align: left;
  justify-self: start;
}
.topic-nav-next {
  text-align: right;
  justify-self: end;
}
.viz-block svg circle {
  transition: fill .2s ease,opacity .2s ease;
}
.topic-nav-meta {
  font-size: .8rem;
  color: var(--gray);
  white-space: nowrap;
}
.topic-nav-title {
  font-size: clamp(.74rem,1.55vw,.98rem);
  font-weight: 700;
  color: var(--accent);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
  display: block;
}
.topic-nav-all {
  justify-self: center;
  align-self: center;
  background: var(--accent);
  color: white;
  text-decoration: none;
  font-weight: 600;
  padding: 10px 22px;
  border-radius: var(--radius-md);
  font-size: .92rem;
  white-space: nowrap;
  box-shadow: var(--shadow-sm);
  transition: transform .15s var(--ease-out),box-shadow .15s;
}
.topic-nav-all:hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow-md);
}

@media (max-width: 720px) {
  .theory-col {
    width: 100%;
  }
}

@media (min-width: 1200px) {
  .card p, .card li, .definition, .highlight, .memo, .mistake {
    text-align: justify;
    text-align-last: left;
    hyphens: auto;
    -webkit-hyphens: auto;
  }
}

@media (prefers-reduced-motion: reduce) {
  .card {
    opacity: 1;
    transform: none;
  }
  .card, .viz-block svg *, .btn, .hl, .step-btn {
    animation: none !important;
    transition: none !important;
  }
  * {
    animation: none !important;
    transition: none !important;
  }
}

/* Дописывается в конец theory.css при сборке (theory_css.py build).
 * Сюда идут общие компоненты, которых нет ни на одной старой странице,
 * поэтому канон их вывести не может. */

/* Блок предпосылок на странице темы (роудмап, задача 5.5).
 * Ставится первым в theory-col: ученик видит, что нужно знать, до того как начнёт читать. */
.prereq {
  margin: 0 0 18px;
  padding: 12px 16px;
  border-left: 3px solid var(--c-purple, #7c3aed);
  border-radius: var(--radius-md, .75rem);
  /* фиксированная фиолетовая дымка, а не переменная темы: часть страниц
   * переопределяет --f-purple только в одном режиме, и в другом получалось
   * светлое на светлом. Полупрозрачный акцент читается на любом фоне */
  background: rgba(124,58,237,.12);
  color: inherit;
  font-size: .95rem;
  line-height: 1.6;
}
.prereq-title {
  display: block;
  margin-bottom: 4px;
  font-weight: 600;
  opacity: .85;
}
.prereq a {
  color: inherit;
  text-decoration: underline;
  text-decoration-color: var(--c-purple, #7c3aed);
  text-underline-offset: 3px;
}
.prereq a + a::before {
  content: " · ";
  text-decoration: none;
  opacity: .5;
}
.prereq a:hover {
  text-decoration-thickness: 2px;
}

/* Куда эта тема ведёт на экзамене. Пара к .prereq: тот же приём с полосой
 * слева, но в конце теории и другого цвета — предпосылки смотрят назад,
 * этот блок вперёд. Цвет фиксированный, а не переменная темы: часть страниц
 * переопределяет акценты только в одном режиме (те же грабли, что у .prereq). */
.exam-link {
  margin: 22px 0 0;
  padding: 12px 16px;
  border-left: 3px solid var(--c-green, #059669);
  border-radius: var(--radius-md, .75rem);
  background: rgba(5, 150, 105, .12);
  color: inherit;
  font-size: .95rem;
  line-height: 1.6;
}
/* Тема может работать сразу на два экзамена — тогда строк две, и вторая
 * отбивается сверху, а не липнет к номерам первой. */
.exam-link-row + .exam-link-row {
  margin-top: 10px;
}
.exam-link-title {
  display: block;
  margin-bottom: 4px;
  font-weight: 600;
  opacity: .85;
}
.exam-link a {
  color: inherit;
  text-decoration: underline;
  text-decoration-color: var(--c-green, #059669);
  text-underline-offset: 3px;
  white-space: nowrap;
}
.exam-link a + a::before {
  content: " · ";
  text-decoration: none;
  opacity: .5;
}
.exam-link a:hover {
  text-decoration-thickness: 2px;
}

/* ═══════════════════════════════════════════════════════════════════════════
   МОБИЛЬНЫЕ ДЕФЕКТЫ СТРАНИЦ ТЕОРИИ. Замер 09.09.2026,
   tools\design_audit\audit_paper.py --gruppa teoriya --shirina 360:
   17 страниц из 48 распирали окно (до 591px при ширине 360), тач-цели 38×38
   при норме 44, кегль до 11.5px, навигация «пред./все/след.» стояла в три
   колонки и обрезала названия тем до ~63px.

   Правки лежат здесь, а не в поправках моста bridge_theory.py, сознательно:
   отсюда они попадают в канон theory.css и чинят все 511 страниц разом,
   а не только 48 переведённых на «тушь и бумагу». Дефект один — и лечится
   один раз.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── 1. ШИРОКОЕ СОДЕРЖИМОЕ ПРОКРУЧИВАЕТСЯ ВНУТРИ СЕБЯ ─────────────────────
   Кто именно распирал страницу (замер: самый глубокий предок, который шире
   своего клиента и не прокручивается) — .expr-display 59 случаев,
   .proof-step 85, врезки 17, абзац 7. Внутри везде одно и то же: формула
   KaTeX, которой страницы задают white-space: nowrap, и она честно не
   переносится. Обрезать её нельзя — ученик потеряет хвост разложения
   («96 = 2·2·2·2·2·3» на теме 19 обрывалось на четвёртой двойке); уменьшать
   кегль до нечитаемого — тоже. Значит блок с формулой получает собственную
   полосу: содержимое прокручиваемого контейнера имеет право быть шире экрана.

   Приём взят у .scroll-x из sup-base.css (на страницах теории того файла
   нет — подключён только theory.css, поэтому набор свойств повторён здесь,
   а не унаследован).

   overflow-y: hidden стоит не для красоты: при overflow-x: auto браузер всё
   равно вычисляет y как auto, и без явного значения появляется лишняя
   вертикальная полоса в один пиксель. Всплывающих подсказок, которые могло
   бы обрезать, в этих блоках нет — только текст, формула и таблица. */
.expr-display, .katex-display,
.definition, .highlight, .memo, .mistake,
.proof-step > :not(.num) {
  overflow-x: auto;
  overflow-y: hidden;
  overscroll-behavior-x: contain;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: thin;
  /* Шаг доказательства — flex-строка «кружок с номером + содержимое».
     Без min-width: 0 flex-элемент отказывается сжиматься уже содержимого,
     и прокрутка внутри него не включается вовсе. Содержимое бывает и <div>,
     и <span class="txt"> — во flex-контейнере оба блочные, поэтому селектор
     по «всё, кроме номера», а не по имени тега. */
  min-width: 0;
}

/* ЗАПАС ПО ВЫСОТЕ — ПЛАТА ЗА ГОРИЗОНТАЛЬНУЮ ПРОКРУТКУ, И ОН ОБЯЗАТЕЛЕН.
   overflow-x: auto заставляет браузер посчитать и вертикальную ось: visible
   там превращается в auto, и мы ставим hidden, чтобы не появлялась вторая,
   ненужная полоса. Но у KaTeX содержимое строки выше самой строки — дробь и
   корень вылезают за строчный бокс. Замер на 128 страницах: у .katex-display
   срезалось до 9px НАСТОЯЩИХ чернил (не распорок — считались только текстовые
   узлы и элементы с рамкой, то есть дробная черта и знак корня), у шага
   доказательства и абзаца до 5px.

   Поэтому блокам без собственных вертикальных полей дают внутренний запас, а
   внешние поля уменьшают ровно на столько же: место на странице то же, а
   формула цела. У врезок (.definition и соседи) и у .expr-display свои 10–14px
   padding уже есть — замер показал у них ноль потерь, их не трогаем.

   .formula-box в список прокручиваемых сознательно НЕ входит: распирающим
   страницу он ни разу не оказался, а padding в 10px не покрывает его 2px
   потерь — выгоды нет, а риск испортить полосу под интерактивом на 343
   страницах есть. */
.katex-display {
  padding-block: 10px;
  margin-block: calc(1em - 10px);   /* у KaTeX здесь margin: 1em 0 */
}
.proof-step > :not(.num) {
  /* Во flex поля не схлопываются, поэтому отрицательное поле гасит padding
     ровно: строка шага стоит там же, где стояла, и номер не разъезжается
     с текстом. В обычном потоке такой приём был бы опаснее. */
  padding-block: 8px;
  margin-block: -8px;
}

/* Абзац теории со «строчной» формулой. Прокрутка здесь — последнее средство
   и потому только на телефоне и только там, где формула действительно есть:
   на 360px строка вида «a · 10 = …» шире колонки, а перенести её нельзя
   (страницы задают .katex { white-space: nowrap }, и это правильно — формулу
   не рвут посередине). Обычные абзацы остаются обычным потоком: чем меньше
   блоков превращено в порт прокрутки, тем меньше поводов что-нибудь срезать. */
@media (max-width: 720px) {
  .theory-col p:has(.katex) {
    overflow-x: auto;
    overflow-y: hidden;
    overscroll-behavior-x: contain;
    scrollbar-width: thin;
    padding-block: 8px;
    margin-block: calc(1em - 8px);   /* поле абзаца по умолчанию 1em */
  }
  /* Пункт списка с формулой — то же самое, но поля у <li> нулевые, поэтому
     запас гасится отрицательным полем. Маркер списка рисуется вне основного
     бокса и прокруткой не срезается — проверено замером положения маркера. */
  .theory-col li:has(.katex) {
    overflow-x: auto;
    overflow-y: hidden;
    overscroll-behavior-x: contain;
    scrollbar-width: thin;
    padding-block: 8px;
    margin-block: -8px;
  }
}

/* Таблицы (43 страницы) стоят в разметке голым <table> без обёртки, поэтому
   прокрутить их можно только сделав блоком самим. На широком экране приём
   не нужен и меняет ширину таблицы, поэтому он включается только на телефоне.
   Честная починка — обёртка .scroll-x в разметке; она требует правки страниц. */
@media (max-width: 720px) {
  .theory-col table {
    display: block;
    max-width: 100%;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scrollbar-width: thin;
  }
}

/* ── 2. КОЛЬЦО ФОКУСА ────────────────────────────────────────────────────
   В каноне кольцо нарисовано двумя тенями при outline: none. Тень едет по
   transition кнопки (.18s) и обрезается любым предком с overflow — а мы его
   только что добавили пункту 1. Поэтому рядом ставится настоящий outline:
   он появляется в тот же кадр и наружу от рамки, как на главной и во всём
   остальном слое (sup-base.css). Тени не трогаем: по ним проверку ведёт
   probe.js, и убрать их значит получить ложную тревогу вместо починки. */
a:focus-visible, button:focus-visible,
summary:focus-visible, [tabindex]:focus-visible {
  outline: var(--ring-width, 2px) solid var(--ring, var(--accent));
  outline-offset: var(--ring-offset, 2px);
}

/* ── 3. КЕГЛЬ ПОДПИСЕЙ ───────────────────────────────────────────────────
   Базовый кегль этих страниц — 16px, и поднимать его целиком нельзя
   (решение записано в поправках моста: под 16px подобраны холсты 511 тем).
   Но подписи навигации жили на .72….92rem, то есть 11.5…14.7px — это ниже
   порога читаемости 15.5px. Поднимаем именно их: они вне интерактива,
   размеры холстов от этого не меняются. */
.topic-nav-all {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;       /* было 43 — не дотягивало до нормы касания ровно на пиксель */
  font-size: 1rem;
}
.topic-nav-title { font-size: 1.02rem; }   /* было clamp(.74rem,1.55vw,.98rem) → 11.8px */
.topic-nav-meta  { font-size: .98rem; }    /* было .8rem → 12.8px */
.proof-step .num { font-size: .98rem; }    /* было .9rem → 14.4px */
.viz-caption     { font-size: .98rem; }    /* было .88rem → 14.1px */
.prereq, .exam-link { font-size: .98rem; } /* было .95rem → 15.2px */

/* Рубрикатор «Предмет · класс · глава» набран .72rem в АТРИБУТЕ style —
   на всех 511 страницах одинаково. Атрибут перебивается только знаком
   важности; правка разметки 511 файлов ради одного объявления дороже. */
header.page-header > div > div:first-child {
  font-size: .98rem !important;
}

/* ── 4. ТАЧ-ЦЕЛИ И ОРГАНЫ УПРАВЛЕНИЯ НА ТЕЛЕФОНЕ ─────────────────────────
   Норма касания 44px. На столе кнопки специально остаются прежними: их
   размер держит раскладку интерактива на 511 страницах, а мышью попасть
   в 38px не проблема. Поэтому весь блок — под указателем пальца.

   --h правит и высоту, и ширину: круглые .btn-icon берут ширину из той же
   переменной (page-inline .btn-icon { width: var(--h) }), так что одного
   объявления хватает на обе стороны кнопки. */
@media (max-width: 720px), (pointer: coarse) {
  .btn, .btn-sm, .step-btn { --h: 2.75rem; min-height: var(--h); font-size: 1rem; }
  .tab-btn { min-height: 44px; font-size: .98rem; }
  /* Кружок смены темы: одной ширины мало — он стоит во flex-шапке и
     сжимался до 41px. Норму держит min-width плюс запрет на сжатие. */
  .theme-toggle {
    width: 44px; height: 44px; min-width: 44px;
    flex-shrink: 0; font-size: 1.25rem;
  }
  /* .mini-btn (40 страниц) объявлена во встроенном <style>, а он идёт после
     ссылки на общий файл — равная специфичность проиграет. Отсюда предок. */
  .interactive-col .mini-btn, .viz-block .mini-btn {
    min-height: 44px;
    min-width: 44px;   /* короткая подпись («56») давала кнопку в 41px по ширине */
    font-size: .95rem;
  }
  .interactive-col .stmt-desc, .viz-block .stmt-desc { font-size: .98rem; }

  /* Ещё три кнопки виджетов, объявленные во встроенном <style> страниц:
     .zoom-btn (74 страницы, кружки увеличения у чертежа), .scene-tab (20,
     переключение сцен) и .pill-btn (5). Все давали 26×26…39×21 при норме 44,
     то есть промах пальцем на каждом втором нажатии у младших. Предок в
     селекторе нужен по той же причине, что и у .mini-btn: встроенный <style>
     идёт после ссылки на общий файл и при равной специфичности побеждает. */
  .interactive-col .zoom-btn, .viz-block .zoom-btn,
  .interactive-col .scene-tab, .viz-block .scene-tab,
  .interactive-col .pill-btn, .viz-block .pill-btn,
  .interactive-col .num-chip, .viz-block .num-chip,
  .interactive-col .op-btn, .viz-block .op-btn,
  .interactive-col .mult-btn, .viz-block .mult-btn,
  .interactive-col .scale-btn, .viz-block .scale-btn {
    min-height: 44px;
    min-width: 44px;
    font-size: .95rem;
  }

  /* Ползунок (151 страница) отдавал 16px по высоте — это высота дорожки,
     а не зона пальца. Бегунок при этом крупнее, но попасть по нему мимо
     дорожки нельзя. Высоту задаём самому полю, вид дорожки не трогаем. */
  .interactive-col input[type="range"], .viz-block input[type="range"] {
    height: 44px;
  }

  /* Ссылки на номера экзамена (301 страница) — строка 30×21 в ряду, где
     между соседними ссылками около 4px. Поэтому зона растягивается
     псевдоэлементом ВВЕРХ и ВНИЗ, а вбок почти нет: расширить по горизонтали
     значило бы накрыть соседний номер, и нажатие по краю «№ 7» открывало бы
     «№ 8» — промах, который хуже мелкой цели. */
  .exam-link a {
    position: relative;
  }
  .exam-link a::after {
    content: "";
    position: absolute;
    inset: -12px -2px;
  }
}

/* ── 5. НАВИГАЦИЯ «ПРЕД. / ВСЕ ТЕМЫ / СЛЕД.» НА ТЕЛЕФОНЕ ────────────────
   Три колонки на 360px давали каждой боковой ссылке ~63px ширины, и
   название темы схлопывалось в «Пример…». Складываем в столбец: порядок в
   разметке уже правильный (пред. → все темы → след.), а название переводим
   в несколько строк — многоточие здесь скрывало ровно то, ради чего ссылка
   и нужна. */
@media (max-width: 720px) {
  .topic-nav { grid-template-columns: minmax(0, 1fr); }
  .topic-nav-side { width: auto; max-width: 100%; }
  .topic-nav-title {
    white-space: normal;
    overflow: visible;
    text-overflow: clip;
  }
  .topic-nav-meta { white-space: normal; }
}

/* ── 6. ЗАЛИТОЕ ВЫБРАННОЕ СОСТОЯНИЕ ПЕРЕКЛЮЧАТЕЛЕЙ (аудит 27.09.2026) ────
   Страницы тем пишут выбранную кнопку литералом: заливка var(--accent) или
   фигурный цвет var(--c-blue/--c-purple/…), подпись color: white / #fff.
   В тёмной теме эти заливки светлые — белое по светлому, контраст 1,26
   («Пример 1», «Объём», «Менелай», «Прямая»; 2,2 у «25» и «+»). Подпись
   берётся парой к заливке: --accent-fg светлеет днём и темнеет ночью вместе
   с чернилами и фигурными цветами. Префикс html поднимает вес над правилом
   страницы (оно подключено позже и того же веса). В список вошли ТОЛЬКО
   классы, у которых на всех страницах выбранное состояние — сплошная
   заливка (перепись правил по 511 страницам): .num-chip.active на шести
   темах 5 класса — обводка без заливки, поэтому его здесь нет.
   :not(.tab-btn) — кнопка, которая одновременно вкладка («Многоугольники»:
   .tab-btn.n-btn), выбранной рисуется светлой плашкой слоя, а не заливкой. */
html :is(.step-btn, .mini-btn, .btn-outline, .scene-tab, .scene-tab-btn, .preset-btn,
  .sub-tab-btn, .op-tab, .op-btn, .n-btn, .mag-btn, .value-tab, .target-btn, .sub-btn,
  .scale-btn, .mult-btn, .ladder-chip, .ladder-base-btn, .lab-prop-btn, .lab-base-btn,
  .eq-chip, .ctor-chip).active:not(.tab-btn),
html .step-btn.tab.active,   /* 0,3,1 — страница пишет .step-btn.tab.active (0,3,0) */
html .pipe-node.active .pipe-circle {
  color: var(--accent-fg);
}

/* ── 7. ЗНАЧОК СОСТОЯНИЯ ЧЕРТЕЖА (.status-badge) ─────────────────────────
   Две беды из аудита 27.09.2026.
   1) white-space: nowrap из общего значка: «✗ пока не выполнен — a и b
      не параллельны» на 390px уходил за край панели и обрезался.
   2) Подпись красилась фигурным цветом (--c-red, --c-orange) по бледной
      заливке того же тона — контраст 2,9–3,3 (нужно 4,5). Страницы задают
      цвет по-разному (.ok/.bad/.no/.neutral/.warn — у разных тем разный
      тон), поэтому цвет не переназначается по классу: заливка букв
      смешивается с собственным цветом значка и цветом основного текста.
      currentColor внутри -webkit-text-fill-color — это цвет самого значка,
      так что оттенок (зелёный, терракотовый, охра) сохраняется, а буквы
      темнеют днём и светлеют ночью до читаемого. */
html .status-badge {
  white-space: normal;
  max-width: 100%;
  -webkit-text-fill-color: color-mix(in oklab, currentColor 55%, var(--text-strong));
}

/* ── 8. СТРОКА ПОЛЗУНКА НА ТЕЛЕФОНЕ ──────────────────────────────────────
   Страницы фиксируют ширину подписи (.lbl { width: 172px; flex-shrink: 0 }),
   а у ползунка минимальная ширина по умолчанию — его собственная (≈130px).
   На 390px подпись + ползунок + число не помещались: число «8» и край
   ползунка уходили за панель. Подпись получает право переноситься,
   ползунок — сжиматься до разумного минимума. */
@media (max-width: 720px) {
  html .slider-row > .lbl { flex-shrink: 1; min-width: 0; }
  html .slider-row > input[type="range"] { min-width: 5rem; }
}

/* ── 9. НОМЕР В СПИСКЕ ПРАКТИКИ ТЕМЫ ─────────────────────────────────────
   Цифра --text-soft на подложке --glass-border давала 4,0–4,3 (нужно 4,5). */
html .pr-item:not(.is-main) .pr-num { color: var(--text); }

/* ── 10. ЦЕЛЬ НАЖАТИЯ КНОПОК ПАНЕЛИ НА ТЕЛЕФОНЕ ──────────────────────────
   Шаги, мини-кнопки и вкладки сцен стояли высотой 39–40px при норме 44
   (замер аудита 27.09.2026 на 390px). Добавляется высота, а не поля:
   подпись остаётся по центру, панель вырастает на 4–5px на ряд. */
@media (max-width: 720px) {
  html :is(.step-btn, .mini-btn, .scene-tab, .scene-tab-btn, .preset-btn) { min-height: var(--tap, 44px); }
}

/* ─── 4/4 ПОПРАВКИ К КАНОНУ ──────────────────────────────── */

/* БАЗОВЫЙ КЕГЛЬ НА ЭТИХ СТРАНИЦАХ ОСТАЁТСЯ 16px — ЭТО РЕШЕНИЕ, НЕ УПУЩЕНИЕ.
   Стандарт проекта — 20px, и он действует для новых страниц (sup-base.css
   ставит html { font-size: var(--fs-root) }). Здесь мы его сознательно НЕ
   применяем: 512 готовых страниц несут встроенный интерактив, размеры холстов
   и viewBox в котором подбирались при 16px. Подъём базы на 25% переложит
   каждую страницу и может поломать ровно то, что сейчас работает.

   Поэтому подъём кегля — отдельный, проверяемый шаг после сверки отпечатком
   (задача 8.6 плана), а не побочный эффект смены палитры. Включается строкой
       html { font-size: var(--fs-root); }
   и проверяется на разделе целиком, а не на одной странице. */

/* Шрифт. В каноне стоит body { font-family: 'Segoe UI', system-ui } —
   системный стек, из-за которого страница выглядит по-разному на Windows
   и на Mac. Заменяем на свои файлы. */
body {
  font-family: var(--font-body);
  font-size: var(--fs-md);
  line-height: var(--lh-md);
  font-synthesis-weight: none;
  background-image: none;   /* три радиальных пятна больше не рисуются вовсе */
  background-color: var(--bg);
  padding-top: 0;
}
h1, h2, h3, h4, .card h1, .card h2 {
  font-family: var(--font-display);
  font-optical-sizing: auto;
  color: var(--text-strong);
}

/* Размытие. Когда «стекло» у шапки, карточек и коробки интерактива разом,
   иерархии нет: всё выглядит одинаково важным. */
header.page-header, .card, .viz-block, .topic-nav-side, .viz-caption, .formula-box {
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}
header.page-header {
  position: sticky;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  height: auto;
  min-height: var(--hdr);
}

/* Подскок на наведении. Один и тот же жест был навешан на кнопки, карточки,
   разделы и переключатель темы — движение перестаёт что-либо значить.
   Взамен меняется граница и заливка. */
.topic-nav-side:hover, .topic-nav-all:hover, .theme-toggle:hover {
  transform: none;
  border-color: var(--accent);
}
.btn:active, .step-btn:active { transform: none; }

/* Текст на залитых чернилами элементах: днём бумажный, ночью чернильный.
   В каноне здесь стоит литеральный white — в тёмной теме это белое по белому. */
.tab-btn.active, .btn-outline.active, .btn-outline.active:hover:not(:disabled),
.step-btn, .topic-nav-all, .proof-step .num {
  color: var(--accent-fg);
  background: var(--accent);
  border-color: var(--accent);
}

/* Связь текст ↔ чертёж: в каноне подчёркивание и подсветка заданы литералами
   #d97706 и #fef3c7, мимо темы. */
.hl { border-bottom-color: var(--accent-line); }
.hl:hover { background: var(--accent-soft); border-bottom-color: var(--accent); }

/* Блок предпосылок: в каноне у него намеренно фиксированная фиолетовая дымка
   rgba(124,58,237,.12) — её ставили, потому что переменная темы работала
   только в одном режиме. С единым слоем токенов костыль не нужен. */
.prereq {
  background: var(--accent-soft);
  border-left-color: var(--accent-line);
  border-radius: var(--radius-md);
}
.prereq a { text-decoration-color: var(--accent); }

/* Врезки: скругление и толщина левой границы из токенов, знак обязателен */
.definition, .highlight, .memo, .mistake {
  border-radius: var(--radius-md);
  border-left-width: 3px;
}

/* Формула не должна выпирать за край на узком экране: в каноне у .katex
   стоит font-size 1.08em, а выключная формула не умеет прокручиваться. */
.katex { font-size: 1em; }
.katex-display { overflow-x: auto; overflow-y: hidden; overscroll-behavior-x: contain; }
.katex-display > .katex { font-size: 1.15em; }

/* Раскладка страницы темы: в каноне .theory-col задан width: 50% при
   .page-split { display: block } и .interactive-col { position: fixed }.
   Переводим на грид — фиксированная колонка перекрывала текст на узких
   экранах и мешала печати. */
.page-split {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  align-items: start;
}
.theory-col { width: auto; min-width: 0; }
/* Липкая колонка отсчитывается ОТ НИЗА ШАПКИ, а не от верха окна.
   top: 0 здесь уже стоял и стоил дорого: шапка тоже липкая (см. выше,
   position: sticky) и лежит выше по z-index (100 против 50 в каноне), так что
   верхние 64px интерактива уезжали под неё. Замер на теореме Пифагора при
   прокрутке 1200px: ряд вкладок оказывался на высоте 23…69px, и
   elementFromPoint по центру каждой из трёх кнопок возвращал header.page-header
   — клик по вкладкам физически не проходил. Ряд управления стоит первым
   элементом интерактива на 52 страницах из 511.

   Формула та же, что в sup-base.css: сначала фактическая высота шапки
   (--hdr-real, её пишет paper.js там, где он подключён), иначе объявленная
   --hdr, иначе 64px. Объявленной недостаточно: у шапки здесь height: auto
   и min-height, при другом кегле она выше 64px. */
.interactive-col {
  position: sticky;
  top: var(--hdr-real, var(--hdr, 64px));
  height: calc(100vh - var(--hdr-real, var(--hdr, 64px)));
  width: auto;
  min-width: 0;
}
@media (max-width: 900px) {
  .page-split { grid-template-columns: minmax(0, 1fr); }
  .interactive-col { position: static; height: auto; min-height: 60vh; }
}

@media print {
  .interactive-col, .topic-nav, header.page-header { display: none !important; }
  .page-split { grid-template-columns: 1fr; }
}

/* Заливки фигур --f-*. Мост вёл их на врезочные *-soft (7…13 %), и это
   подмена роли: soft — подложка под текст врезки, заливка — цвет области
   чертежа, которую ученик должен ОТЛИЧИТЬ от соседней. Замер 08.09.2026 на
   Пифагоре, простых числах и многогранниках (tools\design_audit, OKLab):
   среднее расстояние между пятью заливками поверх сцены — 0,012 (светлая)
   и 0,020 (тёмная) при 0,053 / 0,052 в каноне theory.css; три квадрата
   Пифагора на тёмной теме читались как один серый. Читаемость подписи
   внутри заливки при этом была в норме (--text поверх заливки ≥ 8,7) —
   страдала различимость областей, а не текст.

   Заливка = свой контурный цвет с прозрачностью: пара «контур/заливка» на
   180 страницах остаётся одного оттенка, а тональность (бумага/графит/газета)
   подхватывается сама. Значения --fill-N (литеральные rgba, 20 % днём и 22 %
   ночью) даёт palette.py: 94 страницы из 106 в разделе 5–6 кладут заливку
   в canvas.fillStyle через getComputedStyle, поэтому color-mix здесь нельзя.
   Соответствие то же, что у моста для --c-*: blue→2, green→3, orange→4,
   purple→5, red→6. Специфичность html:root (0,1,1) — как у моста, и блок
   стоит позже него. */
html:root {
  --f-blue:   var(--fill-2);
  --f-green:  var(--fill-3);
  --f-orange: var(--fill-4);
  --f-purple: var(--fill-5);
  --f-red:    var(--fill-6);
}
