/* =============================================================================
   v11 «Точки» (점군) — ветка «Скан» из research/17-modern.md.
   Холодная бумага 백자 + один тёплый акцент. Линия почти отсутствует:
   структуру держат выключка, воздух и тон. Шкала — 7 ступеней, ритм 8px.
   Контрасты посчитаны и подписаны (§8 п.7).
   ========================================================================== */

:root{
  /* шкала (§3.1): 360 · 768 · 1440 · 1920 */
  --fs-d1:clamp(44px,23.7px + 5.64vw,132px);  /* 44.0 · 67.0 · 104.9 · 132.0 */
  --fs-d2:clamp(32px,22.8px + 2.56vw,72px);   /* 32.0 · 42.5 ·  59.7 ·  72.0 */
  --fs-d3:clamp(22px,19.2px + .77vw,34px);    /* 22.0 · 25.1 ·  30.3 ·  34.0 */
  --fs-t1:clamp(19px,17.4px + .45vw,26px);    /* 19.0 · 20.9 ·  23.9 ·  26.0 */
  --fs-t2:clamp(17px,16.3px + .19vw,20px);    /* 17.0 · 17.8 ·  19.1 ·  20.0 */
  --fs-t3:clamp(15px,14.5px + .13vw,17px);    /* 15.0 · 15.5 ·  16.4 ·  17.0 */
  --fs-m1:clamp(12px,11.7px + .10vw,13.5px);  /* 12.1 · 12.5 ·  13.1 ·  13.6 */

  /* пространство (§4.1) */
  --sp-1:4px;--sp-2:8px;--sp-3:12px;--sp-4:16px;--sp-5:24px;--sp-6:32px;
  --sp-7:48px;--sp-8:64px;--sp-9:96px;--sp-10:128px;--sp-11:192px;
  --gutter:clamp(16px,3.2vw,48px);
  --page:min(100% - var(--gutter) * 2,1512px);
  --post:clamp(48px,5.2vw,96px);
  --sp-section:clamp(96px,10vw,192px);
  --sp-block:clamp(32px,3.2vw,48px);
  --hair:1px; --top-h:64px;

  /* гарнитуры (§3.6 B — «Скан») */
  --font-display:'Unbounded','Onest',system-ui,sans-serif;
  --font-ui:'Manrope','Onest',system-ui,sans-serif;
  --font-mono:'JetBrains Mono',ui-monospace,monospace;
  --font-kr:'Noto Sans KR','Manrope',sans-serif;
}
@media (min-resolution:2dppx){ :root{ --hair:.5px; } }

/* --------------------------------------------- палитра B (§5.2): 백자 + 팥 */
:root[data-palette="scan"]{
  --bg:#F3F4F1;          /* oklch(96.6% .004 122) — L ≥ 94 ✅ C ≤ .020 ✅ */
  --bg-2:#E9EAE6;        /* 1.09:1 к bg — тоновое поле без рамки и тени */
  --surface:#FAFBF9;     /* 1.06:1 к bg — светлее фона ✅ */
  --ink:#20221F;         /* /bg 14.52 · /bg-2 13.26 · /surface 15.44 — AAA */
  --ink-2:#3F433F;       /* /bg  9.12 · /bg-2  8.33 · /surface  9.70 — AAA */
  --muted:#5F655F;       /* /bg  5.41 · /bg-2  4.95 · /surface  5.76 — AA  */
  --accent:#8A4A38;      /* /bg  6.10 · /bg-2  5.57 · /surface  6.49 — AA+ */
  --line:#E2E4DF;        /* 1.16:1 к bg — декоративный шов, намеренно */
  --line-strong:#7D837C; /* /bg  3.52 · /bg-2  3.21 · /surface  3.74 — ≥3:1 */
  --accent-hover:#753E2F;/* /bg  7.65 */
  --accent-press:#613326;/* /bg  9.46 */
  --accent-wash:color-mix(in oklab,var(--accent) 6%,var(--bg));
  /* тон обесцвеченной модели (§5.3): хрома = хроме бумаги, пол светлоты L58 */
  --tone-1:#F1F2EF; --tone-2:#E0E2DE; --tone-3:#CDCECB;
  --tone-4:#B6B8B5; --tone-5:#9A9C99; --tone-6:#797B78; /* /bg 3.87 — модель светлее текста */
}

/* ------------------------------------------------------------------- база */
*,*::before,*::after{ box-sizing:border-box; }
html{
  -webkit-text-size-adjust:100%; scrollbar-gutter:stable;
  hanging-punctuation:first last;
}
body{
  margin:0;
  font-family:var(--font-ui); font-size:var(--fs-t2); font-weight:400; line-height:1.58;
  color:var(--ink); background:var(--bg);
  font-variant-numeric:proportional-nums lining-nums;
  -webkit-font-smoothing:antialiased; text-rendering:optimizeLegibility;
}
img,canvas,svg{ display:block; max-width:100%; }
img{ height:auto; image-rendering:auto; }

h1,h2,h3{ margin:0; text-wrap:balance; }
h1{
  font-family:var(--font-display); font-weight:300; font-size:var(--fs-d1);
  line-height:1.02; letter-spacing:-.03em; max-width:22ch;
  /* «конфиденциальности» не влезало в 320–480 и срезалось overflow:clip */
  overflow-wrap:break-word; hyphens:auto;
}
h2,.h2{
  font-family:var(--font-display); font-weight:400; font-size:var(--fs-d2);
  line-height:1.1; letter-spacing:-.026em; max-width:18ch;
}
h3{
  font-family:var(--font-ui); font-weight:500; font-size:var(--fs-d3);
  line-height:1.18; letter-spacing:-.008em;
}
h1,h2,.h2,h3,.btn{ text-box:trim-both cap alphabetic; }
@supports not (text-box:trim-both cap alphabetic){
  h1{ margin-block-start:-.09em; } h2,.h2{ margin-block-start:-.07em; }
}
p{ margin:0 0 var(--sp-4); max-width:66ch; text-wrap:pretty; }
p:last-child{ margin-bottom:0; }
li,dd{ text-wrap:pretty; }
.lead{
  font-size:var(--fs-t1); line-height:1.42; letter-spacing:-.006em;
  color:var(--ink-2); max-width:48ch;
}
.t3{ font-size:var(--fs-t3); line-height:1.5; letter-spacing:.002em; font-weight:450; }
.body p{ font-size:var(--fs-t2); }
:lang(ko){ word-break:keep-all; }
.kr{ font-family:var(--font-kr); font-weight:500; font-feature-settings:"palt" 0; }
s{ color:var(--muted); }
.vh{
  position:absolute; width:1px; height:1px; overflow:hidden; clip-path:inset(50%);
  white-space:nowrap;
}
.nw{ white-space:nowrap; }

/* --------------------------------------------------- цифры и моно-подписи */
.tnum,table,.price,.money{
  font-variant-numeric:tabular-nums slashed-zero lining-nums;
  font-feature-settings:"tnum" 1,"zero" 1;
}
.cap{
  font-family:var(--font-mono); font-weight:500; font-size:var(--fs-m1);
  line-height:1.4; letter-spacing:.01em; color:var(--muted); max-width:40ch;
  margin:0 0 var(--sp-4);
}
.cap--wide{ max-width:52ch; }
.cap--over{
  text-transform:uppercase; letter-spacing:.07em; margin-inline-end:-.07em;
  color:var(--ink-2); margin-bottom:var(--sp-4);
}
.money{ font-family:inherit; }
.ref{ color:var(--muted); text-decoration:none; padding-inline:.15em; }

/* ------------------------------------------------------ ссылки, состояния */
a{ color:inherit; }
.link{
  color:var(--ink); text-decoration:none;
  background-image:linear-gradient(currentColor,currentColor);
  background-size:100% var(--hair); background-repeat:no-repeat;
  background-position:0 calc(100% - .08em);
  transition:background-size 140ms ease,color 140ms ease;
}
@media (hover:hover){ .link:hover{ color:var(--accent); background-size:100% 1px; } }
.link:active{ color:var(--accent-press); }
:focus-visible{ outline:2px solid var(--accent); outline-offset:3px; border-radius:2px; }

.btn{
  display:inline-flex; align-items:center; justify-content:center;
  min-height:48px; padding:14px 26px; border:0; border-radius:0;
  font-family:var(--font-ui); font-weight:500; font-size:var(--fs-t3); line-height:1;
  background:var(--accent); color:var(--surface);   /* 6.49:1 ✅ */
  text-decoration:none; cursor:pointer;
  transition:background-color 140ms ease;
}
@media (hover:hover){ .btn:hover{ background:var(--accent-hover); } }
.btn:active{ background:var(--accent-press); }
@supports not (text-box:trim-both cap alphabetic){ .btn{ padding-block:15px 13px; } }

.btn-text{
  display:inline-flex; gap:.5em; align-items:baseline;
  min-height:44px; align-content:center; flex-wrap:wrap;
  color:var(--ink); text-decoration:none; font-size:var(--fs-t3); font-weight:500;
  transition:color 140ms ease;
}
.btn-text::after{ content:'\2192'; transition:transform 140ms ease; }
@media (hover:hover){
  .btn-text:hover{ color:var(--accent); }
  .btn-text:hover::after{ transform:translateX(2px); }
}
.btn-text:active{ color:var(--accent-press); }
.cta{ display:flex; flex-wrap:wrap; align-items:center; gap:var(--sp-6); margin-bottom:var(--sp-5); }

::selection{ background:var(--accent-wash); color:var(--ink); }
::marker{ color:var(--muted); }
abbr[title]{ text-decoration:underline dotted var(--line-strong); text-underline-offset:3px; }

.skip{
  position:absolute; left:-9999px; top:0; z-index:9;
  background:var(--accent); color:var(--surface); padding:var(--sp-3) var(--sp-4);
  font-size:var(--fs-t3);
}
.skip:focus{ left:var(--gutter); }

/* ---------------------------------------------------------- сетка 칸 (§4.2) */
.page{ position:relative; overflow:clip; }
/* Вложенный .kan (li.route.kan, li.tier.kan) не должен повторно сужаться до
   var(--page): это давало карточкам двойной гуттер — 32/32 вместо 16/16. */
.kan .kan{ width:100%; }
.kan{
  display:grid; width:var(--page); margin-inline:auto;
  grid-template-columns:[post] var(--post) [c1] repeat(12,minmax(0,1fr)) [end];
  column-gap:0; row-gap:var(--sp-block);
}
.bay{ padding-inline:0 var(--sp-6); min-width:0; }
.bay--a{ grid-column:c1 / span 5; }
.bay--b{ grid-column:span 4; }
.bay--c{ grid-column:span 3; padding-inline-end:0; }
.bay--wide{ grid-column:c1 / span 9; }
.bay--full{ grid-column:c1 / end; padding-inline-end:0; }
.bay--solo{ grid-column:c1 / span 7; }
.bay--off{ grid-column:6 / span 6; }

/* сквозные стойки: единственные линии, которые идут сквозь всю страницу */

/* Маргиналия на столбике [post]. Селектор намеренно строго дочерний: контракт §4
   отдаёт имя `.post` карточке ленты (article.post внутри .feed__grid), а карточки
   никогда не лежат прямо в .kan — так два «поста» не пересекаются. */
.kan > .post{
  grid-column:post; align-self:start;
  display:flex; flex-direction:column; gap:var(--sp-3);
  font-family:var(--font-mono); font-weight:500; font-size:var(--fs-m1);
  line-height:1.4; letter-spacing:.01em; color:var(--muted);
  padding-inline-end:var(--sp-4);
}
.post__n{ margin-inline-start:-.04em; color:var(--ink-2); }
.post__kr{
  writing-mode:vertical-rl; font-size:var(--fs-t3); letter-spacing:.06em;
  color:var(--ink-2);
}
.post__gloss{ writing-mode:vertical-rl; }

/* ------------------------------------------------------------------ шапка */
.top{
  position:sticky; top:0; z-index:5; background:var(--bg);
  width:100%; min-height:var(--top-h);
  display:grid; grid-template-columns:1fr auto auto; align-items:center;
  gap:var(--sp-6); padding:var(--sp-3) var(--gutter);
  border-bottom:var(--hair) solid var(--line);
}
.brand{
  font-size:var(--fs-t3); font-weight:450; text-decoration:none; letter-spacing:.002em;
}
.brand b{ font-weight:500; }
/* ссылка на канал в шапке: та же моно-подпись, что у навигации, без стрелки */
.top__tg{
  font-family:var(--font-mono); font-weight:500; font-size:var(--fs-m1);
  text-transform:uppercase; letter-spacing:.07em; margin-inline-end:-.07em;
  color:var(--ink-2); min-height:44px;   /* 9.12:1 ✅ */
}
.top__tg::after{ content:none; }
.navbtn{
  font-family:var(--font-mono); font-weight:500; font-size:var(--fs-m1);
  text-transform:uppercase; letter-spacing:.07em; margin-inline-end:-.07em;
  min-height:44px; padding:0 var(--sp-2); border:0; border-radius:0;
  background:transparent; color:var(--ink-2); cursor:pointer;
  transition:color 140ms ease;
}
@media (hover:hover){ .navbtn:hover{ color:var(--accent); } }
.navbtn:active{ color:var(--accent-press); }
.navbtn[aria-expanded="true"]{ color:var(--accent); }
.menu{
  grid-column:1 / -1; background:var(--bg); padding:var(--sp-5) 0 var(--sp-4);
}
.menu ol{
  list-style:none; margin:0; padding:0;
  display:grid; grid-template-columns:repeat(auto-fit,minmax(15ch,1fr)); gap:var(--sp-4) var(--sp-6);
}
.menu a{
  display:flex; gap:var(--sp-3); align-items:baseline; min-height:44px;
  align-content:center; text-decoration:none; font-size:var(--fs-t3); font-weight:450;
  transition:color 140ms ease;
}
@media (hover:hover){ .menu a:hover{ color:var(--accent); } }
.menu a:active{ color:var(--accent-press); }
.menu a[aria-current]{ color:var(--accent); }
.menu .cap{ margin:0; }

/* ---------------------------------------------- 00 сцена: облако осаждается */
.scan{ position:relative; }
.scan__stage{
  position:sticky; top:var(--top-h); z-index:0;
  height:calc(100svh - var(--top-h)); width:100%;
}
.scan__stage canvas{ width:100%; height:100%; }
.poster{
  position:absolute; inset:0; display:grid; place-items:center;
  /* Постер — ТОЛЬКО фолбэк для «WebGL недоступен». По умолчанию скрыт:
     раньше он показывался на каждой загрузке и мигал точечным фасадом,
     пока грузилась сцена. Показывается через body[data-scene="off"]. */
  color:var(--tone-6); opacity:0; transition:opacity 160ms ease;
  padding:var(--sp-9) var(--gutter) var(--sp-7);
}
.poster__svg{ width:min(96%,1100px); height:auto; }
.poster__field{ color:var(--tone-5); }
body[data-scene="off"] .poster{ opacity:1; }
.scan__flow{ position:relative; z-index:2; margin-top:calc(var(--top-h) - 100svh); }
.hero{
  min-height:calc(100svh - var(--top-h)); align-content:center;
  padding-block:var(--sp-9) var(--sp-7);
}
.hero__main .cap--over{ max-width:none; }
.hero h1{ margin-bottom:var(--sp-5); }
.hero .lead{ margin-bottom:var(--sp-7); }
/* Лид лежит прямо поверх облака и заходит на пигмент 기둥 석간주 #B97C66.
   К нему --ink-2 даёт всего 2,94:1, поэтому в герое (и только в нём) лид идёт
   на --ink: 4,69:1 к самому «трудному» пигменту и 14,52:1 к бумаге. Замер по
   реальным пикселям — в NOTES.md. */
.hero .lead{ color:var(--ink); }
.hero__hint{ margin:0; }


/* ------------------------------------------------------------------ секции */
.sec{ padding-block:var(--sp-section) 0; scroll-margin-top:var(--top-h); }
.sec__head h2{ margin-bottom:var(--sp-5); }
.sec__head .lead{ margin-bottom:var(--sp-4); }
.sec__head{ margin-bottom:var(--sp-7); }
.ticks{ list-style:none; padding:0; margin:0 0 var(--sp-4); }
.ticks li{
  font-size:var(--fs-t3); line-height:1.5; font-weight:450;
  padding-inline-start:1.4em; text-indent:-1.4em; margin-bottom:var(--sp-2);
}
.ticks li::before{ content:'—'; color:var(--muted); margin-inline-end:.7em; }
.ticks--no li::before{ content:'\00D7'; }

/* тоновое поле — единственный разрешённый способ «утопить» блок (§4.4 п.2) */
.field{ background:var(--bg-2); padding:var(--sp-7) var(--sp-7) var(--sp-7) var(--sp-6); }
.todo{
  display:block; background:var(--bg-2); color:var(--ink);
  border-left:2px solid var(--accent);
  padding:var(--sp-2) var(--sp-3); margin-block:var(--sp-2);
  font-size:var(--fs-t3);
}
.todo b{
  display:block; font-family:var(--font-mono); font-weight:500; font-size:var(--fs-m1);
  text-transform:uppercase; letter-spacing:.07em; color:var(--ink-2);
}

/* цитата канала: дисплейная гарнитура вне заголовков — самый лёгкий вес
   Unbounded (300), чтобы цитата не спорила с H2 того же семейства (§3.6) */
.quote{ margin:0; }
.quote blockquote{
  margin:0 0 var(--sp-3);
  font-family:var(--font-display); font-weight:300; font-size:var(--fs-t1);
  line-height:1.42; letter-spacing:-.022em; color:var(--ink);
  max-width:34ch;
}
.quote figcaption{ font-style:italic; margin:0; }
.quote-bay{ align-self:end; }
.quote-bay--top{ align-self:start; }

/* фотографии (§6.6): ни рамки, ни паспарту, ни радиуса.
   V11-FIX §1: фото идут В ЦВЕТЕ. Сняты grayscale(1), contrast/brightness и
   mix-blend-mode:multiply — multiply на светлой бумаге гасил светлые тона, и кадры
   читались тёмными. Здесь и ниже по файлу на фотографиях нет ни одного
   filter / mix-blend-mode / opacity: тон кадра — это тон кадра.
   LQIP-фон и aspect-ratio (их выдаёт build.mjs инлайном на .fig__box) остаются —
   бокс занимает место до загрузки, сдвига макета нет (CLS). */
.fig{ margin:0; }
.fig__box{
  display:block; overflow:hidden; background-size:cover; background-position:50% 50%;
  background-color:var(--bg-2);   /* подложка, если LQIP не пришёл */
}
.fig picture{ display:block; height:100%; }
/* Стойки-линии с фона сняты по правке владельца. z-index у кадров оставлен:
   он же держит их над липкой сценой, когда та проезжает под контентом. */
.fig__box,.post__media{ position:relative; z-index:1; }
.fig img{ width:100%; height:100%; object-fit:cover; border-radius:0; }
.fig figcaption{ margin-top:var(--sp-3); }
.fig--key .fig__box{ margin-bottom:var(--sp-2); }

/* Кадр внутри текстового блока — не «картинка на сдачу», а первая строка блока:
   квадрат в карточке формата, 4:3 в тарифе. Ни рамки, ни тени, ни радиуса. */
.fig--fmt,.fig--tier{ display:block; margin-bottom:var(--sp-4); }

/* ------------------------------------------------------------------- 01 мы */
.proofs{ padding-block:var(--sp-5) 0; }
.proofs__list{
  margin:0; display:grid; grid-template-columns:repeat(3,minmax(0,1fr));
  column-gap:var(--sp-6); row-gap:var(--sp-6);
}
.proof dt{
  font-size:var(--fs-t2); font-weight:500; margin-bottom:var(--sp-2);
  display:flex; gap:var(--sp-3); align-items:baseline;
}
.proof__n{ font-family:var(--font-mono); font-size:var(--fs-m1); color:var(--muted); }
.proof dd{ margin:0; font-size:var(--fs-t3); line-height:1.5; font-weight:450; }
.proof__kr{ display:block; margin:var(--sp-2) 0 0; }

/* -------------------------------------------------------------- 02 форматы */
.fmt h3{ margin-block:var(--sp-2) var(--sp-3); }
.fmt .cap{ margin-bottom:var(--sp-2); }

/* ------------------------------------------------------------- 03 маршруты */
.routes,.tiers{ grid-column:post / end; }
.months{ grid-column:c1 / end; }
.routes,.tiers{ list-style:none; margin:0; padding:0; }
.route,.tier{ padding-block:var(--sp-7); }
.route + .route,.tier + .tier{ border-top:var(--hair) solid var(--line); }
.route__id h3{ margin-block:var(--sp-2) var(--sp-3); }
.routes__note{ color:var(--ink-2); }
.ev{
  display:inline-flex; gap:.6em; align-items:center; margin-bottom:var(--sp-3);
  font-family:var(--font-mono); font-weight:500; font-size:var(--fs-m1);
  letter-spacing:.07em; text-transform:uppercase;
}
/* два разных честных ярлыка: заливка — «были сами», пунктир — «можем поехать» */
.ev i{ width:.5em; height:.5em; }
.ev--were{ color:var(--ink-2); }
.ev--were i{ background:var(--ink-2); }
.ev--can{ color:var(--muted); }
.ev--can i{ border:1px dashed var(--line-strong); width:.66em; height:.66em; }

/* ---------------------------------------------------------------- 04 горы */
.tbl{
  width:100%; border-collapse:collapse; margin-block:var(--sp-7) 0;
  font-size:var(--fs-t3); line-height:1.45;
  font-variant-numeric:tabular-nums slashed-zero lining-nums;
}
.tbl th{
  font-family:var(--font-mono); font-weight:500; font-size:var(--fs-m1); line-height:1.4;
  letter-spacing:.07em; text-transform:uppercase; color:var(--ink-2);
  text-align:left; vertical-align:bottom; white-space:nowrap;
  /* Липкая шапка: без верхнего отступа строки таблицы проезжали вплотную под
     текстом заголовка. Отступ + непрозрачный фон дают чистую отбивку. */
  padding:var(--sp-3) var(--sp-5) var(--sp-2) 0;
  border-bottom:1px solid var(--line-strong);
  position:sticky; top:var(--top-h); background:var(--bg);
}
.tbl td{ padding:var(--sp-3) var(--sp-5) var(--sp-3) 0; vertical-align:baseline; border:0; }
.tbl tbody th{
  position:static; border-bottom:0; vertical-align:baseline; text-transform:none; letter-spacing:.002em;
  font-family:var(--font-ui); font-size:var(--fs-t3); font-weight:500; color:var(--ink);
  white-space:normal; padding:var(--sp-3) var(--sp-5) var(--sp-3) 0;
}
.tbl tbody tr + tr th,.tbl tbody tr + tr td{ border-top:var(--hair) solid var(--line); }
.tbl .num{ text-align:right; padding-right:var(--sp-6); }
.tbl .num--lead{ font-size:var(--fs-t2); }
.levels__list{ margin:0; }
.levels__list dt{ font-size:var(--fs-t3); font-weight:500; margin-top:var(--sp-4); }
.levels__list dd{ margin:0; font-size:var(--fs-t3); line-height:1.5; font-weight:450; color:var(--ink-2); }

/* ---------------------------------------------------------------- 05 цены */
.tier__id h3{ margin-bottom:var(--sp-2); }
.price{ font-size:var(--fs-d3); line-height:1.18; margin-bottom:var(--sp-2); }
.price .cap{ display:inline; margin:0; }
.addons,.terms{ margin:0; }
.addon dt,.terms dt{
  font-size:var(--fs-t3); font-weight:500; margin-top:var(--sp-4);
}
.addon dd,.terms dd{
  margin:0; font-size:var(--fs-t3); line-height:1.5; font-weight:450; color:var(--ink-2);
  max-width:66ch;
}
.addon .cap,.addon b{ display:inline; margin:0; font-weight:500; }
.terms dd{ margin-bottom:var(--sp-3); }
.field .btn{ margin-top:var(--sp-5); }

/* ----------------------------------------------------------------- 06 день */
/* «Как проходит день» был колонкой голых абзацев. Теперь у каждого шага кадр слева,
   текст справа: изображение и текст читаются одним блоком, а не по очереди.
   Разметку не трогаем — раскладку держит grid по порядку детей
   (figure.fig--step, p.cap, h3, p.t3): кадр занимает всю высоту левой колонки,
   остальные три ребёнка автопотоком встают в правую. */
.day{ list-style:none; margin:0; padding:0; }
.dstep{ padding-block:var(--sp-5); max-width:52ch; }
.dstep + .dstep{ border-top:var(--hair) solid var(--line); }
.dstep h3{ font-size:var(--fs-t2); font-weight:500; letter-spacing:0; margin-bottom:var(--sp-2); }
.dstep__t{ margin-bottom:var(--sp-2); color:var(--ink-2); }
.dstep .fig--step{ margin-bottom:var(--sp-3); }
/* Двухколонье — только от 701px: ниже мобильная раскладка целиком за css/mobile.css (A6),
   и стопка «кадр сверху, текст снизу» там остаётся дефолтом без переопределений. */
@media (min-width:701px){
  .dstep{
    max-width:none;
    display:grid; grid-template-columns:minmax(0,34%) minmax(0,1fr);
    column-gap:var(--sp-5); row-gap:0; align-items:start;
  }
  .dstep > .fig--step{ grid-area:1 / 1 / span 3 / 2; margin:0; align-self:start; }
  .dstep .t3{ max-width:46ch; }
  /* шаг без кадра (кадра нет в манифесте) не должен оставлять пустую колонку */
  .dstep:not(:has(> .fig--step)){ grid-template-columns:minmax(0,1fr); max-width:52ch; }
}

/* -------------------------------------------------------------- 07 сезоны */
.months{
  display:grid; grid-template-columns:repeat(4,minmax(0,1fr));
  column-gap:var(--sp-6); row-gap:var(--sp-6);
}
.mo__h{
  display:flex; gap:var(--sp-2); align-items:baseline; flex-wrap:wrap;
  font-size:var(--fs-t3); font-weight:500; margin-bottom:var(--sp-2);
}
.mo__h b{ font-family:var(--font-mono); font-size:var(--fs-m1); color:var(--muted); font-weight:500; }
.rate{ display:inline-flex; gap:3px; }
.rate i{ width:6px; height:6px; background:var(--line-strong); }
.rate i.on{ background:var(--ink-2); }

/* ------------------------------------------------------------- 08 вопросы */
/* линия здесь одна на весь список: строки разводит номер, кегль и воздух */
.qs{ border-top:var(--hair) solid var(--line); }
.q summary{
  display:flex; gap:var(--sp-4); align-items:baseline; cursor:pointer;
  padding-block:var(--sp-5); list-style:none;
  font-size:var(--fs-d3); line-height:1.18; letter-spacing:-.008em; font-weight:500;
  transition:color 140ms ease;
}
.q summary::-webkit-details-marker{ display:none; }
@media (hover:hover){ .q summary:hover{ color:var(--accent); } }
.q summary:active{ color:var(--accent-press); }
.q__n{ margin:0; flex:none; }
.q__t{ flex:1 1 auto; max-width:34ch; }
.q__i{
  flex:none; width:16px; height:16px; position:relative; color:var(--accent);
  align-self:center;
}
.q__i::before,.q__i::after{
  content:''; position:absolute; inset:50% 0 auto; height:1px; background:currentColor;
}
.q__i::after{ transform:rotate(90deg); transition:transform 140ms ease; }
.q[open] .q__i::after{ transform:rotate(0deg); }
.q__a{ padding-bottom:var(--sp-5); }
.q__a p{ max-width:66ch; }

/* =========================================================== 09 лента канала
   Контракт классов — V11-FIX §4, имена не переименовываются.
   Дисциплина раунда 3 (research/17-modern.md §5–§7) в силе: второго хроматического
   токена нет, box-shadow ноль, радиус только 0, кегли — из тех же 7 ступеней.
   Карточка не «плитка в рамочке»: её держат волосяная линейка сверху, кадр и
   выключка. Каждая 4-я карточка (.post--wide) идёт на две колонки и раскладывается
   кадр|текст — ритм ленты задаёт она, а не фон.
   Контрасты: .post__date --ink-2 9.12:1 · № --muted 5.41:1 · .post__title --ink
   14.52:1 · .post__excerpt --ink-2 9.12:1 · .post__link --ink 14.52:1,
   на hover --accent 6.10:1 — всё ≥ 4.5:1. */
.feed{ width:var(--page); margin-inline:auto; }
.feed__head{ margin-bottom:var(--sp-8); max-width:74ch; }
.feed__head h2{ margin-bottom:var(--sp-5); }
.feed__head .lead{ margin-bottom:var(--sp-4); }
.feed__head .todo{ margin-block:var(--sp-2) var(--sp-3); }

.feed__grid{
  display:grid; grid-template-columns:repeat(3,minmax(0,1fr));
  column-gap:var(--sp-6); row-gap:var(--sp-8);
  align-items:start;
}

.feed__grid > .post{
  min-width:0; display:grid; grid-template-rows:auto 1fr; gap:var(--sp-4);
  border-top:var(--hair) solid var(--line-strong); padding-top:var(--sp-3);
}

/* кадр: aspect-ratio держит место до загрузки (LQIP-фон приходит инлайном
   из build.mjs), поэтому сдвига макета нет. Никаких фильтров — фото в цвете. */
.post__media{
  display:block; overflow:hidden;
  aspect-ratio:4 / 3; background-color:var(--bg-2);
  background-size:cover; background-position:50% 50%;
}
.post__media picture{ display:block; height:100%; }
.post__media img{ width:100%; height:100%; object-fit:cover; border-radius:0; }
/* кадра ещё нет в assets/opt — тоновая полоса вместо «битой» картинки;
   высота меньше, чтобы заглушка не притворялась фотографией */
.post__media--none{ aspect-ratio:16 / 5; }

.post__body{ display:grid; align-content:start; gap:var(--sp-3); min-width:0; }
.post__date{ margin:0; color:var(--ink-2); }      /* 9.12:1 ✅ */
.post__id{ color:var(--muted); }                   /* 5.41:1 ✅ */
.post__title{
  font-family:var(--font-ui); font-size:var(--fs-t1); font-weight:500;
  line-height:1.24; letter-spacing:-.006em; color:var(--ink); max-width:26ch;
}
.post__excerpt{
  margin:0; font-size:var(--fs-t3); line-height:1.55; font-weight:450;
  color:var(--ink-2); max-width:44ch;
  /* цитаты из канала разной длины: обрезаем по строкам, чтобы лента держала ритм.
     Полный текст — по ссылке в карточке, о чём прямо сказано в подводке секции. */
  display:-webkit-box; -webkit-box-orient:vertical; -webkit-line-clamp:7; line-clamp:7;
  overflow:hidden;
}
.post__excerpt .cap{ display:inline; margin:0; font-family:var(--font-kr); color:var(--muted); }
.post__link{
  justify-self:start; align-self:end;
  display:inline-flex; align-items:center; min-height:44px;
  font-size:var(--fs-t3); font-weight:500; color:var(--ink); text-decoration:none;
  background-image:linear-gradient(currentColor,currentColor);
  background-size:0 var(--hair); background-repeat:no-repeat;
  background-position:0 calc(100% - 12px);
  transition:background-size 140ms ease,color 140ms ease;
}
@media (hover:hover){ .post__link:hover{ color:var(--accent); background-size:100% var(--hair); } }
.post__link:active{ color:var(--accent-press); }

/* каждая 4-я — на две колонки, кадр крупнее и рядом с текстом */
.feed__grid > .post--wide{
  grid-column:span 2;
  grid-template-columns:minmax(0,1.15fr) minmax(0,1fr);
  grid-template-rows:auto;
  column-gap:var(--sp-6);
  border-top-color:var(--ink-2);
}
/* у широкой карточки кадр тянется на всю высоту текстовой колонки: разворот,
   а не «картинка сверху». min-height держит место до загрузки — сдвига нет.
   Только от 701px: одноколоночная лента ≤700 — территория css/mobile.css (A6). */
@media (min-width:701px){
  .post--wide .post__media{ aspect-ratio:auto; height:100%; min-height:clamp(260px,24vw,380px); }
  .post--wide .post__media--none{ aspect-ratio:auto; min-height:clamp(160px,14vw,220px); }
}
.post--wide .post__body{ align-content:center; gap:var(--sp-4); padding-block:var(--sp-2); }
.post--wide .post__title{
  font-family:var(--font-display); font-weight:400; font-size:var(--fs-d3);
  line-height:1.14; letter-spacing:-.026em; max-width:22ch;
}
.post--wide .post__excerpt{
  font-size:var(--fs-t2); line-height:1.5; max-width:52ch;
  -webkit-line-clamp:8; line-clamp:8;
}
.feed__grid > .post--empty{ grid-column:1 / -1; }

/* --------------------------------------------------------- финал и подвал */
.final{ padding-block:var(--sp-section) 0; }
.final h2{ margin-bottom:var(--sp-5); }
.foot{
  margin-top:var(--sp-section); padding-block:var(--sp-9) var(--sp-8);
  background:var(--bg-2); width:100%; padding-inline:calc((100% - var(--page)) / 2);
}
.foot__tag{
  font-family:var(--font-display); font-weight:400; font-size:var(--fs-d2);
  line-height:1.1; letter-spacing:-.026em; max-width:24ch; margin-bottom:var(--sp-5);
  overflow-wrap:break-word; hyphens:auto;   /* «сопровождение» вылезало на 320 */
}
.foot__links{ list-style:none; margin:0 0 var(--sp-6); padding:0; display:grid; gap:var(--sp-2); }
.foot__links a{ font-size:var(--fs-t3); }
.attrib summary{ cursor:pointer; color:var(--ink-2); }
.credits{ margin:var(--sp-4) 0 0; padding-inline-start:1.2em; display:grid; gap:var(--sp-2); }
.credits li{ max-width:66ch; }
.legal h3{ margin-top:var(--sp-6); margin-bottom:var(--sp-3); }

/* ------------------------------------------------------------- адаптив */
@media (max-width:1100px){
  .proofs__list,.months{ grid-template-columns:repeat(2,minmax(0,1fr)); }
  .bay--off{ grid-column:c1 / span 8; }
  /* лента: 1440 — 3 колонки, 1024 — 2 (§4). Одна колонка ≤700 — в css/mobile.css (A6). */
  .feed__grid{ grid-template-columns:repeat(2,minmax(0,1fr)); }
}
@media (max-width:880px){
  /* Одна колонка — столбик [post] схлопывается в нуль (§4.2, правка центровки).
     Маргиналия на мобиле уже не стоит сбоку, а ложится строкой над байкой
     (grid-column:post / end ниже), поэтому отдельная колонка под неё только
     сдвигала ВЕСЬ контент на 44px вправо: слева 60px, справа 16px. Нулевая
     ширина сохраняет имена линий (post и c1 совпадают) — ни один селектор
     с `post /` или `c1 /` переписывать не нужно, и поля становятся 16/16. */
  :root{ --post:0px; }
  .bay,.bay--a,.bay--b,.bay--c,.bay--wide,.bay--full,.bay--solo,.bay--off{
    grid-column:c1 / end; padding-inline-end:0;
  }
  .kan > .post{
    grid-column:post / end; flex-direction:row; align-items:baseline; gap:var(--sp-3);
    padding-inline-end:0;
  }
  .post__kr,.post__gloss{ writing-mode:horizontal-tb; }
  /* Порядок чтения на мобиле: надзаголовок → H1 → ПАВИЛЬОН → лид → CTA → подпись.
     Правка владельца: храм должен стоять сразу под «Корея, которая объясняет
     себя сама», а не после кнопки. Дубля разметки нет: обёртки .scan__flow,
     .hero и .hero__main растворяются в display:contents, и надзаголовок, H1,
     лид, CTA и подпись становятся прямыми детьми сетки .scan наравне со сценой —
     только так сцену можно вклинить между H1 и лидом одним order. */
  .scan{
    display:grid; width:var(--page); margin-inline:auto;
    grid-template-columns:[post] var(--post) [c1] repeat(12,minmax(0,1fr)) [end];
    row-gap:0;
  }
  .scan__flow,.scan .hero,.scan .hero__main{ display:contents; }
  .scan > *,.scan .hero__main > *{ grid-column:c1 / end; }
  /* воздух под липкой шапкой — маргиналом текста, не полем секции */
  .scan .cap--over{ order:1; margin-block-start:var(--sp-7); }
  .scan h1{ order:2; margin-bottom:0; }
  /* Сцена — ФОН секции 00 во всю её площадь, а не полоса в потоке:
     камера на мобиле уведена вплотную, так что в кадре только угол павильона.
     Текст лежит поверх (z-index:1), сцена под ним (z-index:0).
     Поэтому у .scan НЕТ собственных полей: контейнером абсолютной сцены
     служит её грид-область, то есть padding-box, и любой padding у секции
     срезал бы подложку сверху — над ней вылезла бы полоса бумаги. Воздух
     над надзаголовком и под подсказкой набран маргиналами самих текстов
     (.cap--over / .hero__hint ниже). */
  .scan{ position:relative; }
  .scan__stage{
    /* НЕ задаём grid-column/grid-row: у абсолютного грид-элемента с явной
       позицией контейнером становится его грид-область, а `1 / -1` указывает
       на конец ЯВНОЙ сетки — строки здесь неявные, и область схлопывалась в
       первую строку (замер: высота 81px вместо всей секции). Без grid-позиции
       контейнером служит padding-box самой .scan — сцена накрывает секцию 00
       целиком, как и задумано. */
    /* full-bleed: .scan на мобиле сам стал колонкой (width:var(--page)), и
       подложка наследовала его гуттеры — канвас был у́же вьюпорта на 2×гуттер.
       Растягиваем на всю ширину экрана. */
    position:absolute; inset-block:0; left:50%; right:auto;
    width:100vw; margin-left:-50vw;
    height:auto; z-index:0; pointer-events:none; overflow:hidden;
  }
  /* Кадрируем сам канвас. Камера сцены смотрит на павильон сверху, и её пресеты
     на высоком мобильном канвасе всё равно прижимают модель к верхнему краю —
     подбором target это не лечится (проверено). Масштаб + сдвиг по канвасу дают
     ровно нужный кадр: крупный угол кровли, уходящий за правый край секции. */
  .scan__stage canvas{
    transform:none;
    transform-origin:62% 34%;
  }
  .scan > *:not(.scan__stage),
  .scan .hero__main > *{ position:relative; z-index:1; }
  .scan .lead{ order:4; }
  .scan .cta{ order:5; }
  /* снизу почти впритык: ритм до раздела 01 держит .sec{--sp-section} */
  .scan .hero__hint{ order:6; margin-block-end:var(--sp-2); }
  /* Текст героя лежит на живом облаке, поэтому светлые токены здесь запрещены:
     --muted над пигментом 기둥 даёт 2.08:1, --ink-2 над 지붕 — 2.90:1.
     Оба переведены на --ink: 4.62:1 к самому трудному пигменту (замер QA). */
  .scan .hero__hint,
  .scan .cap--over{ color:var(--ink); }
  .poster{ padding:var(--sp-4) var(--gutter); }
  .hero{ min-height:0; padding-block:var(--sp-5) var(--sp-7); }
  .hero h1{ margin-bottom:var(--sp-4); }
  .hero .lead{ margin-bottom:var(--sp-5); }
    .routes,.tiers{ grid-column:c1 / end; }
  .cta{ gap:var(--sp-5); }
  .field{ padding:var(--sp-6) var(--sp-5); }
  .top{ grid-template-columns:1fr auto auto; gap:var(--sp-4); }
}
@media (max-width:520px){
  /* Unbounded шире Playfair, поэтому коридор кеглей на мобиле сдвинут вниз:
     на 431–520 три строки H1 держит 38px (§8 п.2 — нижняя граница коридора). */
  :root{ --fs-d1:38px; }
  /* сцена — фон, высоту не режем: её задаёт сама секция */
  .hero{ padding-block:var(--sp-2) var(--sp-6); row-gap:var(--sp-4); }
  .hero .cta{ gap:var(--sp-4); }
}
@media (max-width:700px){
  .proofs__list,.months{ grid-template-columns:1fr; }
  /* таблица переразбирается в пары «ключ — значение», а не уезжает в скролл (§3.5) */
  .tbl,.tbl tbody,.tbl tr,.tbl td,.tbl tbody th{ display:block; width:100%; }
  .tbl thead{ position:absolute; width:1px; height:1px; overflow:hidden; clip-path:inset(50%); }
  .tbl tr{ padding:var(--sp-4) 0; border-top:var(--hair) solid var(--line); }
  .tbl td,.tbl tbody th{ display:grid; grid-template-columns:11ch 1fr; gap:var(--sp-3); padding:2px 0; }
  .tbl tbody tr + tr th,.tbl tbody tr + tr td{ border-top:0; }
  .tbl td::before,.tbl tbody th::before{
    content:attr(data-th);
    font-family:var(--font-mono); font-weight:500; font-size:var(--fs-m1); line-height:1.4;
    letter-spacing:.07em; text-transform:uppercase; color:var(--muted);
  }
  .tbl .num{ text-align:left; padding-right:0; }
}
@media (prefers-reduced-motion:reduce){
  *,::before,::after{ animation:none !important; transition:none !important; }
}
