/* =========================================================
   Евгения · художник фактуры — КАРКАС v2
   Мобильный первым. Слом миров — визуальный приём, скролл свободный.
   ========================================================= */

/* ---------- 1. Токены каркаса ---------- */
:root{
  /* типографическая шкала */
  /* эмодзи-фолбэки (А8 13.08): без них 😂/😍 пузырей рисовались
     монохромным контуром на части машин */
  --f-display: "Unbounded", "Golos Text", system-ui, sans-serif;
  --f-text: "Golos Text", system-ui, -apple-system, sans-serif,
            "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji";

  --t-opening: clamp(1.45rem, 6.2vw, 3rem);
  --t-title:   clamp(2.4rem, 11vw, 5.4rem);
  --t-lead:    clamp(1.05rem, 4.3vw, 1.45rem);
  --t-body:    clamp(0.98rem, 3.6vw, 1.06rem);
  /* минимумы подняты 12.08 (вердикт «мелкий текст плохо видно» + HIGH #2
     ревью 10.08): small не тоньше 14px, eyebrow ~12.8px */
  --t-small:   clamp(0.875rem, 3.4vw, 0.95rem);
  --t-eyebrow: 0.8rem;

  /* ритм */
  --pad-x: clamp(18px, 5.5vw, 76px);
  --sec-pad-y: clamp(84px, 13vh, 190px);
  --gap: clamp(20px, 4vw, 40px);
  --maxw: 1480px;

  /* нить и сломы */
  --thread-w: 3.6;
  --tear: 30px;
  --open-h: clamp(190px, 30svh, 360px);

  /* цвета интерфейса — переключаются JS на границе миров */
  --ui-ink: #23201C;      /* мир под шапкой */
  --ui-accent: #B4862F;
  --ui-bg: #EDE8DF;
  --rail-ink: #23201C;    /* мир на середине экрана */
  --rail-accent: #B4862F;

  --dur: 0.3s;
}
@media (min-width: 980px){
  :root{ --thread-w: 5.4; --tear: 54px; --dur: 0.55s; }
}
/* А3 ревью 13.08: десктопная ступень типо-шкалы. Все клампы упирались в
   потолок до 800px - 1280/1440/1920 рендерили одинаковые кегли, широкий
   экран получал только пустоту. Мобильные значения не тронуты (ступень
   отдельным брейкпоинтом, не правкой клампов). Заголовок мира 3 живёт
   на своём клампе (.w-hero, предел переноса) - токен его не задевает */
@media (min-width: 1440px){
  :root{
    --t-opening: 3.4rem;   /* 48 → 54.4px */
    --t-title:   6.5rem;   /* 86.4 → 104px */
    --t-lead:    1.7rem;   /* 23.2 → 27.2px */
    --t-body:    1.13rem;  /* 17 → 18.1px */
    --t-small:   1rem;     /* 15.2 → 16px */
  }
  /* элементные правила ступени живут в разделе 20 В КОНЦЕ файла:
     поставленные здесь, они проигрывали каскад более поздним базовым
     правилам той же специфичности (.k-lead и хиро-клампы миров) */
}

/* ---------- 2. Сброс ---------- */
*,*::before,*::after{ box-sizing:border-box; }
html{
  overflow-x: clip;              /* не hidden: hidden ломает sticky ниже по странице */
  scroll-behavior: auto;         /* никакого «плавного» нативного скролла поверх Lenis */
  -webkit-text-size-adjust:100%;
}
body{
  margin:0;
  overflow-x: clip;
  background: var(--ui-bg);
  color: var(--ui-ink);
  font-family: var(--f-text);
  font-size: var(--t-body);
  line-height: 1.55;
  transition: background-color .12s linear;   /* слом должен быть резким */
  -webkit-font-smoothing: antialiased;
}
img{ max-width:100%; display:block; }
h1,h2,h3,p,figure,ul,ol{ margin:0; }
ul,ol{ padding:0; list-style:none; }
a{ color:inherit; text-decoration:none; }
button,input{ font:inherit; color:inherit; }
::selection{ background: var(--ui-accent); color:#fff; }

/* Lenis (десктоп): минимально необходимое, без плагинов */
html.lenis, html.lenis body{ height:auto; }
.lenis.lenis-smooth{ scroll-behavior:auto !important; }
.lenis.lenis-stopped{ overflow:hidden; }

/* ---------- 3. Шапка ---------- */
.hdr{
  position: fixed; inset: 0 0 auto 0; z-index: 20;
  display:flex; align-items:center; justify-content:space-between;
  gap:12px;
  padding: 14px var(--pad-x);
  color: var(--ui-ink);
  font-size: var(--t-small);
  transition: color .12s linear;
  mix-blend-mode: normal;
  pointer-events:none;
}
.hdr > *{ pointer-events:auto; }
/* подложка цвета текущего мира + прогрессивный blur (А5 ревью 13.08:
   88%-градиента не хватало - буквы блоков физически наезжали на лого).
   mask гасит и заливку, и blur к нижней кромке - разделитель без черты */
.hdr::before{
  content:""; position:absolute; z-index:-1;
  left:0; right:0; top:0; height: 170%;
  background: linear-gradient(to bottom, color-mix(in srgb, var(--ui-bg) 92%, transparent), color-mix(in srgb, var(--ui-bg) 55%, transparent));
  -webkit-backdrop-filter: blur(9px);
  backdrop-filter: blur(9px);
  -webkit-mask-image: linear-gradient(to bottom, #000 58%, transparent);
  mask-image: linear-gradient(to bottom, #000 58%, transparent);
}
.hdr__mark{ display:flex; align-items:baseline; gap:.45em; letter-spacing:.01em;
             position:relative; }
/* 18.08: лого и «смотреть работы» были ~20-25px высотой. Зону нажатия
   расширяем псевдоэлементом - высота шапки и раскладка не меняются */
.hdr__mark::after{ content:""; position:absolute; inset:-12px -6px; }
.hdr__mark:hover .hdr__name{ color: var(--ui-accent); }
.hdr__name{ font-family: var(--f-display); font-weight:600; letter-spacing:-.02em; font-size:.94em; transition: color .18s ease; }
.hdr__dot{ opacity:.55; }
.hdr__role{ opacity:.72; }
/* «заявка» - пилюля ink-на-bg: пара цветов мира гарантирует контраст
   (А5 ревью 13.08: подчёркнутый accent давал 2.7:1 на светлых мирах) */
.hdr__cta{
  display:inline-flex; align-items:center;
  /* «эскиз бесплатно» длиннее прежней «заявки» - на телефоне пилюля ломалась
     на две строки (скрин Даниила 18.08) */
  white-space: nowrap;
  padding: .82em 1.15em; border-radius:999px;
  background: var(--ui-ink); color: var(--ui-bg);
  font-weight:500; letter-spacing:.02em;
  transition: background-color .18s ease, color .18s ease, transform .18s ease;
}
.hdr__cta:hover{ transform: translateY(-1px); background: color-mix(in srgb, var(--ui-ink) 78%, var(--ui-accent)); }
/* тумблер «без анимаций» (13.08): тихая иконка-волна перед «заявкой»;
   в anim-off волна перечёркнута. Тач-зона 40px при визуальных 17 */
/* переключатель-switch (14.08, вердикт Даниила: «тумблер чтобы вкл/выкл»,
   паттерн 21st.dev портирован руками): подпись + дорожка с бегунком.
   ВКЛ - дорожка акцентом мира, бегунок справа; ВЫКЛ - серая, слева */
.hdr__anim{
  margin-left:auto;
  display:flex; align-items:center; gap:9px;
  padding:11px 0; background:none; border:0; cursor:pointer;   /* 18.08: было 34px высоты */
  color: var(--ui-ink); opacity:.85;
  transition: opacity .18s ease;
}
.hdr__anim:hover{ opacity:1; }
.hdr__anim-label{
  font-size:.76rem; letter-spacing:.05em;
  font-family: var(--f-text); font-weight:500;
}
.hdr__anim-sw{
  position:relative; flex:0 0 auto;
  width:38px; height:22px; border-radius:999px;
  background: var(--ui-accent);
  box-shadow: inset 0 1px 2px rgba(0,0,0,.14);
  transition: background-color .22s ease;
}
.hdr__anim-sw i{
  position:absolute; top:2px; left:2px;
  width:18px; height:18px; border-radius:50%;
  background:#FFFDF8;
  box-shadow: 0 1px 3px rgba(31,24,14,.35);
  transform: translateX(16px);
  transition: transform .22s ease;
}
html.anim-off .hdr__anim-sw{ background: color-mix(in srgb, var(--ui-ink) 28%, transparent); }
html.anim-off .hdr__anim-sw i{ transform: translateX(0); }
html.anim-off .hdr__anim{ opacity:.85; }
@media (max-width: 439px){ .hdr__role, .hdr__dot{ display:none; } }
@media (max-width: 479px){
  /* на узком шапка делится на троих: имя, тумблер, кнопка - кнопке
     оставляем ровно столько, чтобы строка не переносилась */
  .hdr__cta{ font-size:.8rem; padding:1.15em .9em; }
}
@media (max-width: 359px){
  .hdr__cta{ font-size:.74rem; padding:1.2em .75em; }
}

/* полоса прогресса: на широких экранах длину показывает рельса, ниже 1440
   её нет - остаётся эта нитка под шапкой. Не анимация, а ориентир, поэтому
   живёт и в спокойном режиме */
.progress{ position:fixed; top:0; left:0; right:0; height:2px; z-index:60;
           background: color-mix(in srgb, var(--ui-ink) 12%, transparent);
           pointer-events:none; }
.progress i{ display:block; height:100%; width:0;
             background: var(--ui-accent, #B4862F); }
@media (min-width: 1440px){ .progress{ display:none; } }

/* подпись под колонкой соцсетей в подвале */
.foot__hint{ color:#8D7F6C; font-size:.78rem; max-width:26ch; margin:0 0 .3em !important }

/* ---------- 4. Индикатор блоков ---------- */
/* убран решением Даниила 06.08 («фигня справа»): скрыт целиком,
   механика активного мира в app.js продолжает работать вхолостую */
.rail{ display:none; }
.rail{
  position: fixed; z-index:18;
  right: 0; top:50%; transform: translateY(-50%);
  padding: 0 clamp(8px, 1.6vw, 22px) 0 0;
  pointer-events:none;
}
.rail__list{ display:flex; flex-direction:column; gap: clamp(10px, 1.7vh, 18px); align-items:flex-end; }
.rail__item{
  pointer-events:auto;
  display:flex; align-items:center; justify-content:flex-end; gap:10px;
  color: var(--rail-ink); opacity:.42;
  font-size:.7rem; letter-spacing:.14em; text-transform:lowercase;
  transition: opacity .18s linear, color .18s linear;
}
.rail__item i{ display:block; width:14px; height:1.5px; background: currentColor; transition: width .2s ease, background-color .18s linear; }
.rail__item span{ display:none; }
.rail__item.is-active{ opacity:1; color: var(--rail-accent); }
.rail__item.is-active i{ width:26px; }
.rail__item.is-active span{ display:block; }
@media (min-width: 980px){
  .rail__item span{ display:block; }
  .rail__item{ opacity:.34; }
  .rail__item:hover{ opacity:.8; }
  .rail__item.is-active span{ font-weight:500; }
}

/* ---------- 5. Атмосфера и нить ----------
   СЭНДВИЧ (снизу вверх): фон мира 0 → слом 1 → частицы атмосферы 2 →
   ТЕЛО НИТИ 3 → картины и кадры 4 → текст 5 → ГОЛОВА-КАПЛЯ 6 → индикатор 18 → шапка 20.
   Секции намеренно НЕ являются stacking context, иначе слои схлопнутся. */
.fx{
  position: fixed; inset:0; z-index:2;
  width:100%; height:100%;
  pointer-events:none;
}
.thread{
  position:absolute; top:0; left:0; z-index:3;
  width:100%; height:0;
  overflow: visible;
  pointer-events:none;
  /* НИТЬ ВРЕМЕННО УБРАНА ЦЕЛИКОМ (Даниил 06.08: «убери линию, вернёмся
     в конце»). thread.js продолжает работать — его геометрия питает
     сломы (SECTION_GEOM в app.js), скрыт только визуальный слой.
     Вернуть: удалить display:none + подключить nit-gl.js в index.html */
  display:none !important;
}
.thread--head{ z-index:6; }
#thSegs path{ stroke-linejoin: round; }

/* --- WebGL-тело нити блока 1 (nit-gl.js, проба за флагом ?nitgl=1) ---
   Канвас встаёт ровно на место SVG-тела: fixed на вьюпорт, тот же z-index 3
   (над атмосферой, ПОД контентом), голова-капля остаётся SVG на z6.
   Класс html.nitgl-on вешает сам модуль и только когда контекст поднялся:
   нет WebGL / потеря контекста / сильный зум — SVG-нить остаётся на месте.
   Имя класса корня НЕ совпадает с классом канваса намеренно: одинаковые
   имена положили бы position:fixed на сам <html> и убили скролл страницы. */
.nitgl{
  position:fixed; inset:0; z-index:3;
  width:100%; height:100%;
  pointer-events:none;
}
html.nitgl-on #thSegs .seg--float{ display:none !important; }  /* тело блока 1 рисует шейдер */
html.zoom-lite .nitgl{ display:none !important; }

/* --- 1 · пуховая лента: полупрозрачное золото, ворс, дышащая толщина --- */
/* пуховая лента (06.08): ворс гуще и заметнее, сердцевина тише —
   лента из пуха, а не золотая струна */
.fl-soft2{ fill:#B9871F; opacity:.09; }
.fl-soft1{ fill:#C08F2A; opacity:.15; }
.fl-body { fill:#BE8A24; opacity:.52; }
.fl-hair { fill:none; stroke:#B78E33; stroke-width:1; stroke-opacity:.46; stroke-linecap:round; }
.fl-core { fill:none; stroke:#FBECC2; stroke-width:1.4; stroke-opacity:.62; stroke-linecap:round; }

/* --- 2 · раскалённая струна: жар, языки пламени, белое ядро --- */
.fi-haze2{ fill:#FF3F0C; opacity:.055; }
.fi-haze1{ fill:#FF6A1E; opacity:.10; }
.fi-t3   { fill:#E33206; opacity:.40; }
.fi-t2   { fill:#FF7A16; opacity:.52; }
.fi-t1   { fill:#FFD25E; opacity:.70; }
.fi-glow { fill:none; stroke:#FF7C1A; stroke-width:9; stroke-opacity:.50; stroke-linecap:round; }
.fi-core { fill:none; stroke:#FFF4D6; stroke-width:2.6; stroke-linecap:round; }

/* --- 3 · чернильная строчка: тонкое перо, не кабель --- */
.ik-soft{ fill:#2B2937; opacity:.055; }
.ik-body{ fill:#35323F; opacity:.62; }
.ik-mark{ fill:none; stroke:#35323F; stroke-width:.9; stroke-opacity:.26; stroke-linecap:round; }
.ik-wet { fill:#8F8DA0; opacity:.22; }

/* --- 4 · зелёная лиана: стебель с узлами, усики, листья --- */
.st-shadow{ fill:#16300D; opacity:.20; }
.st-body  { fill:#3B6A21; }
.st-hi    { fill:none; stroke:#93BF5C; stroke-width:1.7; stroke-opacity:.55; stroke-linecap:round; }
.st-node  { fill:none; stroke:#224316; stroke-width:1.5; stroke-opacity:.55; }
.st-curl  { fill:none; stroke:#4E8129; stroke-width:1.7; stroke-opacity:.9; stroke-linecap:round; }
.st-leafB { fill:#2C5719; }
.st-leafF { fill:#4E8A29; }
.st-rib   { fill:none; stroke:#8CBB62; stroke-width:.9; stroke-opacity:.5; }

/* --- 5 · комета: ядро у головы + широкий светящийся веер хвоста --- */
.cm-veil{ fill:#7FB0FF; opacity:.05; }
.cm-far { fill:#8CBBFF; opacity:.085; }
.cm-mid { fill:none; stroke:#DCE9FF; stroke-width:1.4; stroke-opacity:.30; stroke-linecap:round; }
.cm-near{ fill:#FFF0C2; opacity:.22; }
.cm-line{ fill:none; stroke:#9CC4FF; stroke-width:6; stroke-opacity:.24; stroke-linecap:round; }
.cm-core{ fill:none; stroke:#FFF7DF; stroke-width:2; stroke-opacity:.92; stroke-linecap:round; }

/* --- 6 · расплавленный мёд: самая широкая и мягкая --- */
.ry-far { fill:#C08419; opacity:.085; }
.ry-mid { fill:#C68B1C; opacity:.13; }
.ry-in  { fill:#BC7F18; opacity:.22; }
.ry-body{ fill:#AC7317; opacity:.74; }
.ry-core{ fill:none; stroke:#FFEFC2; stroke-width:2.4; stroke-opacity:.7; stroke-linecap:round; }

/* --- 7 · подпись кистью --- */
.kn-soft{ fill:#D8A84A; opacity:.15; }
.kn-body{ fill:#D8A84A; }
.kn-hi  { fill:#FFE8AB; opacity:.5; }

@media (max-width: 979px){
  .fi-glow{ stroke-width:6; } .fi-core{ stroke-width:1.8; }
  .cm-line{ stroke-width:3.4; } .cm-core{ stroke-width:1.5; }
  .ry-core{ stroke-width:1.7; } .fl-core{ stroke-width:1.3; }
  .st-curl{ stroke-width:1.3; } .st-hi{ stroke-width:1.2; }
}

/* --- частицы вдоль нити --- */
.pt-fluff { fill:#E4D4B2; }
.pt-spark { fill:#FFB65A; }
.pt-ink   { fill:#2A2833; }
.pt-pollen{ fill:#DCF09E; }
.pt-dust  { fill:#E2ECFF; }
.pt-mote  { fill:#F7E0A8; }
.pt-gold  { fill:#F0C978; }

/* --- голова нити: единственный элемент поверх контента, потому мелкая --- */
.hd{ transform: scale(var(--hd-s, .56)); transform-origin: 0 0; }
@media (min-width: 980px){ .hd{ --hd-s: .82; } }
.hd__pulse{ transform-origin:0 0; animation: flypulse 2.8s ease-in-out infinite; }
@keyframes flypulse{ 0%,100%{ opacity:.55; transform:scale(.86); } 50%{ opacity:1; transform:scale(1.14); } }
#thHeadFlash{ transform-origin: 0 0; }
#thHeadFlash.is-flash{ animation: hflash .55s ease-out; }
@keyframes hflash{
  0%{ transform: scale(1); }
  20%{ transform: scale(2.15); }
  100%{ transform: scale(1); }
}

/* ---------- 6. Секция-мир ---------- */
.sec{
  position: relative;
  min-height: 100vh;
  min-height: 100svh;
  padding: var(--sec-pad-y) 0 calc(var(--sec-pad-y) * .78);
  color: var(--ink);
  isolation: auto;
}
.sec__world{
  position:absolute; inset:0; z-index:0;
  background: var(--bg);
}
/* «вторая» краска мира — мягкое поле, чтобы фон не был плоской заливкой */
.sec__world::after{
  content:""; position:absolute; inset:0;
  background: radial-gradient(120% 65% at var(--glow-x, 22%) var(--glow-y, 18%), var(--bg-2) 0%, transparent 62%);
  opacity: var(--glow-o, .85);
}
.sec__inner{
  position: relative;
  max-width: var(--maxw);
  margin-inline:auto;
  padding-inline: var(--pad-x);
  display:grid;
  gap: var(--gap);
}

/* заголовочный блок */
.sec__head{ position:relative; z-index:5; }
.opening{
  font-family: var(--f-display); font-weight:300;
  font-size: var(--t-opening); line-height:1.14; letter-spacing:-.03em;
  margin-bottom: clamp(56px, 12vh, 150px);
  max-width: 18ch;
}
.eyebrow{
  font-size: var(--t-eyebrow); letter-spacing:.22em; text-transform:uppercase;
  color: var(--ink-soft); font-weight:500;
  display:flex; align-items:center; gap:.9em;
  margin-bottom: .9em;
}
/* .eyebrow__num снят - нумерация блоков убрана вердиктом 12.08 */
.sec__title{
  font-family: var(--f-display); font-weight:600;
  font-size: var(--t-title); line-height:.94; letter-spacing:-.045em;
}
/* сквозной авторский жест: мазок мастихина под заголовком */
.stroke{ display:block; width: clamp(140px, 42vw, 320px); height:auto; margin-top:.7em; fill: var(--accent); opacity:.9; }
.stroke--2{ width: clamp(110px, 33vw, 260px); opacity:.8; }
.stroke--3{ width: clamp(170px, 52vw, 380px); opacity:.75; }

/* картина */
.plate{ position:relative; z-index:4; }
.plate img{ width:100%; height:auto; box-shadow: var(--plate-shadow, 0 26px 60px -34px rgba(0,0,0,.55)); }
.plate figcaption{
  margin-top: .85em;
  font-size: var(--t-small); color: var(--ink-soft);
  letter-spacing:.03em;
  display:flex; flex-wrap:wrap; gap:.6em; align-items:baseline;
}
.tag{
  font-size:.66rem; letter-spacing:.14em; text-transform:uppercase;
  border:1px solid currentColor; border-radius:2px; padding:.18em .5em; opacity:.6;
}

/* история */
.story{ position:relative; z-index:5; max-width: 38ch; }
.story__lead{ font-size: var(--t-lead); line-height:1.35; letter-spacing:-.01em; }
.story__note{ margin-top:1em; color: var(--ink-soft); }
.story__meta{
  margin-top:1.4em; font-size:.74rem; letter-spacing:.16em; text-transform:uppercase;
  color: var(--ink-soft); opacity:.8;
}

/* стопка доп. кадров внахлёст */
.stack{ position:relative; z-index:4; display:flex; align-items:flex-start; }
.frame{ position:relative; width:46%; }
.frame img{ width:100%; height:auto; border-radius:2px; box-shadow: var(--frame-shadow, 0 18px 40px -24px rgba(0,0,0,.6)); }
.frame--a{ transform: rotate(-1.6deg); }
.frame--b{ margin-left:-9%; margin-top:14%; transform: rotate(1.9deg); }

/* ---------- 7. Раскладка: мобильный / десктоп ---------- */
.sec__inner{ grid-template-columns: 1fr; }
.stack{ margin-top: -14%; padding-left: 6%; }

@media (min-width: 980px){
  .sec__inner{
    padding-right: clamp(112px, 10vw, 176px);   /* полоса под индикатор блоков */
    grid-template-columns: repeat(12, 1fr);
    column-gap: clamp(20px, 2.4vw, 44px);
    row-gap: clamp(28px, 4vh, 64px);
    align-items:start;
  }
  .sec__head{ grid-column: 1 / 10; grid-row: 1; }
  .plate{ grid-column: 1 / 8;  grid-row: 2; }
  .story{ grid-column: 8 / 13; grid-row: 2; padding-top: clamp(24px, 7vh, 90px); padding-left: clamp(16px, 2.6vw, 48px); }
  .stack{ grid-column: 7 / 13; grid-row: 3; margin-top: clamp(-260px, -18vh, -110px); padding-left:0; justify-self:end; width: 78%; }

  /* зеркальный вариант каркаса: сетка та же, стороны меняются местами */
  .sec--mirror .plate{ grid-column: 6 / 13; }
  .sec--mirror .story{ grid-column: 1 / 6; padding-left:0; padding-right: clamp(16px, 2.6vw, 48px); }
  .sec--mirror .stack{ grid-column: 1 / 7; justify-self:start; }
  .sec--mirror .sec__head{ grid-column: 3 / 13; text-align:right; }
  .sec--mirror .eyebrow{ justify-content:flex-end; }
  .sec--mirror .stroke{ margin-left:auto; }
}

/* ---------- 8. Палитры миров ---------- */
.sec--air{
  --bg:#EDE8DF; --bg-2:#F7F3EA; --ink:#23201C; --ink-soft:#6B6055; --accent:#B4862F;
  --glow-x:64%; --glow-y:12%;
  /* частицы блока 1 выключены (Даниил 06.08: «посмотрю как без них»);
     вернуть — density .8 */
  --particle-kind: fiber; --particle-color: #AC9C82; --particle-density: 0; --particle-speed: .22; --particle-alpha: .6; --particle-blend: normal;
}
.sec--drive{
  --bg:#0B0909; --bg-2:#241010; --ink:#F4EDE6; --ink-soft:#A2938A; --accent:#E23B2E;
  --glow-x:30%; --glow-y:76%;
  --plate-shadow: 0 30px 70px -30px rgba(0,0,0,.9);
  --frame-shadow: 0 20px 44px -24px rgba(0,0,0,.9);
  /* искры выключены (Даниил 08.08: «искры можно убрать») - мир держат
     головешки .d-fall, мелкая крупа поверх них только шумела;
     вернуть - density 1.15 */
  --particle-kind: spark; --particle-color: #FF6A38; --particle-density: 0; --particle-speed: 1.5; --particle-alpha: .8; --particle-blend: lighter;
}
.sec--words{
  --bg:#EFF0EC; --bg-2:#FBFBF8; --ink:#17161A; --ink-soft:#61606A; --accent:#E2465F;
  --glow-x:78%; --glow-y:30%;
  --particle-kind: crumb; --particle-color: #B9B7AC; --particle-density: .7; --particle-speed: .22; --particle-alpha: .55; --particle-blend: normal;
}
/* мир 4 «Место силы» (12.08): был светлым эскизом старой постройки, стал
   глубокой влажной зеленью под генерённую фактуру травы-пасты - тёмная
   стена ширмы слома раскрывается в родной ей мир */
.sec--wild{
  --bg:#0E1A0C; --bg-2:#1B2D14; --ink:#EFF3E2; --ink-soft:#A3B792; --accent:#B5D178;
  --glow-x:50%; --glow-y:12%;
  --plate-shadow: 0 30px 70px -30px rgba(0,0,0,.85);
  --frame-shadow: 0 20px 44px -24px rgba(0,0,0,.85);
  --particle-kind: leaf; --particle-color: #C9E09C; --particle-density: .6; --particle-speed: .5; --particle-alpha: .45; --particle-blend: normal;
}
.sec--deep{
  --bg:#140F1D; --bg-2:#2C1F42; --ink:#EDE7F5; --ink-soft:#9C90B4; --accent:#C8A64B;
  --glow-x:70%; --glow-y:64%;
  --plate-shadow: 0 30px 70px -30px rgba(0,0,0,.95);
  --frame-shadow: 0 20px 44px -24px rgba(0,0,0,.95);
  --particle-kind: star; --particle-color: #D9CEF3; --particle-density: 1.0; --particle-speed: .28; --particle-alpha: .75; --particle-blend: lighter;
}
/* мир 6 «Золотое древо» (13.08): был светлым закатом старой постройки,
   стал тёплым золотом на глубокой умбре - материя самой работы
   (тёмно-коричневый холст, крона-монеты, корни поталью) */
.sec--warm{
  --bg:#1A1108; --bg-2:#2F2010; --ink:#F6ECD9; --ink-soft:#C4AC85; --accent:#D9A441;
  --glow-x:50%; --glow-y:16%;
  --plate-shadow: 0 30px 70px -30px rgba(0,0,0,.9);
  --frame-shadow: 0 20px 44px -24px rgba(0,0,0,.9);
  --particle-kind: gold; --particle-color: #D9A441; --particle-density: .6; --particle-speed: .3; --particle-alpha: .55; --particle-blend: lighter;
}
.sec--offer{
  --bg:#1D1610; --bg-2:#3A2A18; --ink:#F2E7D5; --ink-soft:#A8967D; --accent:#D8A84A;
  --glow-x:50%; --glow-y:88%;
  --particle-kind: gold; --particle-color: #D8A84A; --particle-density: .6; --particle-speed: .3; --particle-alpha: .6; --particle-blend: lighter;
}

/* ---------- 8a. Блок 1 «Крылья»: четыре подэкрана ----------
   Вход → история → композиция → отзыв, каждый ≈100svh. Отступы держат
   сами подэкраны: у секции их нет, иначе за четвёртым экраном остаётся
   пустой хвост перед ширмой #c12.
   Все новые классы — с префиксом .k-; общие (.plate, .eyebrow, .reveal,
   .sec__head, .sec__title) переиспользуются как есть. */
.sec--air{ padding: 0; }

/* --- фон блока: видео-макро sticky-кадром внутри мира секции ---
   .sec__world имеет z-index:0 и потому изолирует всё внутри: видео
   остаётся под атмосферой (z2), нитью (z3) и контентом (z4-5).
   .k-bg поднят на z1 внутри мира — чтобы «вторая краска» (.sec__world::after)
   не мылила кадр; за читаемость отвечает собственная виньетка. */
.k-bg{ position:absolute; inset:0; z-index:1; }
/* Ken Burns живёт на обёртке (scale), параллакс --par-y — на img:
   transform-анимация и JS-дрейф не спорят за одно свойство */
.k-bg__pic{
  position:sticky; top:0;
  display:block; height:100svh; overflow:hidden;
  background: var(--bg);
}
.k-bg__img{
  display:block; width:100%; height:100%;
  object-fit:cover;
}
@media (prefers-reduced-motion: no-preference){
  .k-bg__pic{ animation: kbDrift 46s ease-in-out infinite alternate; }
  @keyframes kbDrift{
    from{ transform: scale(1.06) translate3d(0,-0.6%,0); }
    to  { transform: scale(1.14) translate3d(0,0.9%,0); }
  }
}
/* живой слой среды: видео-петля тем же sticky-кадром поверх картинки,
   ПОД светом и вуалью; появляется мягко только когда реально играет
   (is-live ставит app.js по событию playing).
   Гибрид: кадр-обёртка клипует, видео выше кадра на 16svh — этот запас
   app.js растягивает в дрейф по скроллу (--kbv-y), фон едет за скроллом
   медленнее контента и продолжает жить сам */
.k-bg__live{
  position:sticky; top:0;
  display:block; height:100svh; margin-top:-100svh;
  overflow:clip;
}
.k-bg__vid{
  display:block; width:100%; height:116svh;
  object-fit:cover;
  transform: translate3d(0, var(--kbv-y, 0px), 0);
  /* без will-change: transform уже держит слой, лишний хинт при зуме
     только раздувает память слоёв (зум множит их на dpr²) */
  opacity:0; transition: opacity 1.2s ease;
}
.k-bg__vid.is-live{ opacity:1; }

/* --- падающие перья (Даниил 06.08): крупные, медленно падают сквозь
   сцену. Sticky-кадр = окно на весь блок; падение живёт на обёртке,
   маятниковое покачивание на img — трансформы не спорят. Дальние
   мельче/размытее, ближние крупнее с тенью — глубина падения --- */
.k-fall{
  position:sticky; top:0; height:100svh;
  overflow:clip; pointer-events:none;
  z-index:2;              /* над .k-bg (z1), иначе фон закрашивает перья */
}
.k-fall__f{ position:absolute; top:0; }
.k-fall__f img{ display:block; width:100%; height:auto; }
/* белое перо на белой фактуре тонет — тёплая тень отделяет от фона */
.k-fall__f--1{ left:6%;  width:min(360px,34vw); opacity:.92;
               filter: drop-shadow(-10px 22px 24px rgba(64,52,34,.34)); }
.k-fall__f--2{ left:36%; width:min(220px,20vw); opacity:.6;
               filter: blur(1.6px) drop-shadow(-6px 16px 18px rgba(64,52,34,.28)); }
.k-fall__f--3{ left:58%; width:min(420px,40vw); opacity:.95;
               filter: drop-shadow(-14px 30px 30px rgba(64,52,34,.38)); }
.k-fall__f--4{ left:84%; width:min(190px,17vw); opacity:.55;
               filter: blur(2px) drop-shadow(-5px 14px 16px rgba(64,52,34,.26)); }
.k-fall__f--5{ left:22%; width:min(260px,25vw); opacity:.8;
               filter: drop-shadow(-8px 20px 22px rgba(64,52,34,.3)); }
.k-fall__f--6{ left:72%; width:min(230px,22vw); opacity:.7;
               filter: blur(1px) drop-shadow(-7px 18px 20px rgba(64,52,34,.28)); }
@media (prefers-reduced-motion: no-preference){
  .k-fall__f{ animation: kFall linear infinite; }
  .k-fall__f img{ animation: kFallSway ease-in-out infinite alternate; }
  .k-fall__f--1{ animation-duration:19s; animation-delay:-4s; }
  .k-fall__f--1 img{ animation-duration:3.8s; }
  .k-fall__f--2{ animation-duration:27s; animation-delay:-15s; }
  .k-fall__f--2 img{ animation-duration:5.4s; animation-delay:-2s; }
  .k-fall__f--3{ animation-duration:16s; animation-delay:-9s; }
  .k-fall__f--3 img{ animation-duration:3.2s; animation-delay:-1s; }
  .k-fall__f--4{ animation-duration:24s; animation-delay:-20s; }
  .k-fall__f--4 img{ animation-duration:4.6s; animation-delay:-3s; }
  .k-fall__f--5{ animation-duration:21s; animation-delay:-13s; }
  .k-fall__f--5 img{ animation-duration:4.1s; animation-delay:-1.6s; }
  .k-fall__f--6{ animation-duration:18s; animation-delay:-6s; }
  .k-fall__f--6 img{ animation-duration:3.5s; animation-delay:-2.4s; }
  @keyframes kFall{
    from{ transform: translate3d(0,-42svh,0); }
    to  { transform: translate3d(-5vw,112svh,0); }
  }
  /* маятник настоящего пера: качается и слегка скользит в сторону крена */
  @keyframes kFallSway{
    from{ transform: rotate(-17deg) translateX(-5%); }
    to  { transform: rotate(13deg)  translateX(6%); }
  }
}
/* спокойный режим: перья стоят редкой декорацией на входе, не сыплются */
@media (prefers-reduced-motion: reduce){
  .k-fall__f--1{ top:12%; }
  .k-fall__f--2{ top:34%; }
  .k-fall__f--3, .k-fall__f--5, .k-fall__f--6{ display:none; }
  .k-fall__f--4{ top:58%; }
}
/* мобила: три пера вместо шести, поменьше */
@media (max-width: 767px){
  .k-fall__f--2, .k-fall__f--4, .k-fall__f--6{ display:none; }
  .k-fall__f--1{ width:34vw; }
  .k-fall__f--3{ width:38vw; }
  .k-fall__f--5{ width:28vw; }
}

/* --- зум-лайт (app.js initZoomGuard): при сильном зуме гасим слои,
   которые множат память GPU — видео, перья с blur/drop-shadow, blend-свет.
   Остаётся статичная картинка фона и контент: страница не падает --- */
html.zoom-lite .k-fall,
html.zoom-lite .k-bg__vid,
html.zoom-lite .k-bg__light{ display:none !important; }
html.zoom-lite .k-bg__pic{ animation:none; }

/* дыхание света: тёплое пятно медленно плывёт по фактуре */
.k-bg__light{
  position:sticky; top:0;
  display:block; height:100svh; margin-top:-100svh;
  pointer-events:none;
  background: radial-gradient(90% 64% at 26% 30%, rgba(255,242,214,.5), transparent 62%);
  mix-blend-mode: soft-light;
}
@media (prefers-reduced-motion: no-preference){
  .k-bg__light{ animation: lightBreath 17s ease-in-out infinite alternate; }
  @keyframes lightBreath{
    from{ transform: translate3d(-4%,-2%,0) scale(1); opacity:.75; }
    to  { transform: translate3d(5%,3.5%,0) scale(1.18); opacity:1; }
  }
}
/* виньетка идёт тем же sticky-кадром поверх видео: отрицательный отступ
   вместо абсолютного позиционирования — обе плашки живут в одном потоке
   и прилипают синхронно */
.k-bg__veil{
  position:sticky; top:0;
  display:block; height:100svh; margin-top:-100svh;
  background:
    linear-gradient(to bottom,
      color-mix(in srgb, var(--bg) 42%, transparent) 0%,
      color-mix(in srgb, var(--bg) 14%, transparent) 26%,
      color-mix(in srgb, var(--bg) 16%, transparent) 68%,
      color-mix(in srgb, var(--bg) 46%, transparent) 100%),
    radial-gradient(118% 76% at 50% 44%, transparent 40%, color-mix(in srgb, var(--bg) 30%, transparent) 100%);
}

/* --- подэкраны --- */
/* сетку .sec__inner (12 колонок на десктопе) блок 1 не использует:
   подэкраны идут простым потоком, раскладку держит каждый сам */
.sec--air .k-inner{ display:block; }
.k-screen{
  position:relative;                       /* без z-index: сэндвич слоёв внутри не схлопывается */
  display:flex; flex-direction:column; justify-content:flex-start;
  padding: clamp(24px, 4.5vh, 60px) 0 clamp(18px, 3.5vh, 44px);
}
/* плотность по скетчу: сцены авто-высоты, без пустых вертикальных дыр */
.k-comp{ justify-content:center; }
/* отзыв идёт сразу за сценой работы, без паузы-экрана */
.k-review{ justify-content:flex-start; padding-top: clamp(20px, 3.5vh, 44px); padding-bottom: clamp(24px, 4vh, 56px); }

/* 1/4 вход — типографика блока 1: фэшн-сериф Prata (выбор Даниила,
   Glamor без кириллицы) + PT Serif в истории; остальные блоки живут
   на Unbounded/Golos как раньше */
.k-hero{ padding-top: clamp(84px, 13vh, 150px); }
/* Рамка лид-строки (выбор Даниила 18.08, вариант «только рамка»).
   История вопроса: пятно под абзацем читалось как грязь, градиент от
   края - «всё равно плохо», плотная плашка перекрывает фактуру. Здесь
   заливки нет вообще: текст очерчен тонкой рамкой в тоне мира, фон под
   ним лишь слегка расфокусирован - фактура остаётся видимой.
   У hero подложки нет вовсе - его читаемость держит сам текст.
   Цвет рамки берём от --ink, поэтому она сама переворачивается на
   светлых мирах (1 и 3) и на тёмных (2, 4, 5, 6) без отдельных правил */
.k-lead::before{
  content:""; position:absolute; z-index:-1;
  top:-1.05em; bottom:-1.05em;
  left:-1.3em; right:-1.7em;
  background: transparent;
  /* блюр - страховка читаемости: видео под текстом иногда выносит
     светлый кадр, и одной рамки на нём не хватает */
  -webkit-backdrop-filter: blur(10px);
          backdrop-filter: blur(10px);
  border: 1px solid var(--lead-frame, color-mix(in srgb, var(--ink) 22%, transparent));
  border-radius: 14px;
  pointer-events:none;
}
/* на узком экране текст занимает 80% ширины - рамку прижимаем к тексту,
   иначе левый край уезжает за поле секции */
@media (max-width: 719px){
  .k-lead::before{
    top:-.85em; bottom:-.85em;
    left:-.85em; right:-.9em;
    border-radius: 12px;
  }
}


/* --- вход «театральная сцена» (выбор Даниила 06.08, variants/vhod В2):
   текст-группа = объект в 3D; reveal живёт на .sec__head, разворот на
   вложенной .k-hero3d — трансформы не спорят. Курсор-tilt пишет
   --k3-ry/--k3-rx (app.js), база -7°/2° как у холста карусели */
.k-hero .sec__head{ position:relative; max-width:46rem; }
.k-hero3d{
  position:relative;
  transform: perspective(1300px) rotateY(var(--k3-ry, -7deg)) rotateX(var(--k3-rx, 2deg));
  transform-style: preserve-3d;
}
/* Плашка-подиум под хедом СНЯТА (Даниил 18.08: «белая фигня, некрасивая»,
   три скрина - миры 3, 4, 5). Она держала читаемость заголовка на видео,
   но на живой фактуре читалась мутным пятном с видимым краем - тот же
   диагноз, что убил подложку под лид-строкой. Читаемость теперь целиком
   на самом тексте: экструзия и свечение заголовка по мирам ниже, у
   подстроки - мягкая тень там, где фон пёстрый (миры 2 и 4).
   Вместе с ней сняты пять переопределений по мирам (.d/.w/.n/.c/.g). */
/* заголовок стоит над плоскостью: тёплая экструзия + вынос по Z */
.k-hero3d .sec__title{
  text-shadow:
    1px 1px 0 rgba(180,134,47,.28),
    2px 2px 0 rgba(180,134,47,.2),
    3px 3px 0 rgba(180,134,47,.13),
    6px 10px 22px rgba(64,52,34,.28);
  transform: translateZ(40px);
}
.k-hero3d .stroke{ transform: translateZ(24px); }
/* статичных перьев у входа нет (Даниил 06.08: «все должны падать») —
   единственные перья блока живут в .k-fall */
.k-hero .opening{
  margin-bottom: clamp(28px, 5vh, 64px);
  font-family: 'Prata', serif; font-weight: 400;
  letter-spacing: .01em; line-height: 1.3;
}
.k-hero .sec__title{
  max-width: 12ch;
  font-family: 'Prata', serif; font-weight: 400;
  font-size: clamp(2.9rem, 14vw, 5.6rem);
  letter-spacing: .02em;
}

/* 2/4 история: четыре строки, каскад по --k-i */
.k-story__body{
  position:relative; z-index:5;
  max-width: 34ch;
  display:flex; flex-direction:column;
  gap: clamp(12px, 2.4vh, 28px);
}
.k-story__body > *:nth-child(1){ --k-i:0; }
.k-story__body > *:nth-child(2){ --k-i:1; }
.k-story__body > *:nth-child(3){ --k-i:2; }
.k-story__body > *:nth-child(4){ --k-i:3; }
.k-line{
  font-family: 'PT Serif', serif;
  font-size: 1.2rem; line-height:1.6; letter-spacing:0;
}
.k-line--quiet{ color: color-mix(in srgb, var(--ink) 72%, var(--bg)); }
.k-line--turn{
  font-family: 'Prata', serif; font-weight:400;
  font-size: clamp(1.25rem, 5.2vw, 1.7rem); line-height:1.42; letter-spacing:.01em;
  margin-top: .35em;
}
/* каскад: у scroll-driven ревилов сдвигаем окно диапазона, у JS-фолбека — задержку */
.k-story .reveal.is-in{ transition-delay: calc(var(--k-i, 0) * .22s); }
@supports (animation-timeline: view()){
  @media (prefers-reduced-motion: no-preference){
    .k-story .reveal{
      animation-range: entry calc(4% + var(--k-i, 0) * 9%) cover calc(26% + var(--k-i, 0) * 9%);
    }
  }
}

/* 3/4 композиция: 3D-карусель материалов «Крыльев» (решение 06.08,
   выбор Даниила из variants/karusel/): десктоп — «кольцо-сцена»
   (активная фронтом по центру, соседи по дуге кольца, дальние тают
   в вуали), мобила — «кольцо-мини» (соседи рёбрами у краёв, управление
   под сценой). Геометрия слотов задаётся здесь переменными, JS только
   читает их и двигает карточки */
.k-comp{ gap: 0; flex-direction:column; align-items:flex-start; }
/* одна строка истории живёт в сцене работы, над холстом */
.k-lead{
  position:relative; z-index:5;
  width:100%; max-width: 30ch;
  font-family:'PT Serif', serif;
  font-size: clamp(1.15rem, 4.6vw, 1.5rem); line-height:1.55;
  margin-bottom: clamp(30px, 5.5vh, 70px);
}
/* --- карусель: геометрия слотов ---
   слот 0 — активная фронтом по центру; ±1 и ±2 — соседи по дуге кольца.
   Переменные (мобила первой, десктоп в @media ниже):
   x1/x2 — вынос от центра, r1/r2 — поворот к центру (deg, число),
   s1/s2 — масштаб, o1/o2 — прозрачность. На мобиле слот ±2 погашен —
   это и есть «кольцо-мини» */
.kc{
  --kc-w: 74vw;  --kc-h: 62svh;
  --kc-x1: 52vw; --kc-x2: 74vw;
  --kc-r1: 38;   --kc-r2: 48;
  --kc-s1: .42;  --kc-s2: .4;
  --kc-o1: 1;    --kc-o2: 0;
  position:relative; z-index:4; width:100%;
  display:flex; flex-direction:column; align-items:center;
}
.kc__stage{
  position:relative; width:100%; height: var(--kc-h);
  perspective: 1100px; perspective-origin: 50% 42%;
  touch-action: pan-y;                      /* вертикальный скролл не перехватываем */
  outline:none;
}
.kc__stage:focus-visible{ outline: 2px solid color-mix(in srgb, var(--accent) 60%, transparent); outline-offset: 8px; }
/* тёплый ореол в центре сцены: активная карточка всегда стоит в нём */
.kc__stage::before{
  content:""; position:absolute; z-index:0;
  left:50%; top:50%; width:130%; height:120%;
  transform:translate(-50%,-50%);
  background: radial-gradient(38% 46% at 50% 48%,
    rgba(255,250,238,.85), rgba(255,246,226,.32) 56%, transparent 74%);
  pointer-events:none;
}
.kc__card{
  position:absolute; top:50%; left:50%; margin:0;
  /* карточка ОБНИМАЕТ свой кадр: высота от пропорции медиа, а не фиксированная.
     Так квадратная работа видна целиком и без пустого поля, а портретное
     видео занимает всю высоту сцены (Даниил 09.08: «надо чтобы поместилась») */
  width: var(--kc-w); height:auto; max-height:100%;
  border-radius: clamp(12px, 1.8vw, 20px); overflow:hidden;
  box-shadow: 0 12px 24px -14px rgba(64,52,34,.5), 0 46px 84px -38px rgba(64,52,34,.4);
  background: var(--bg-2);
  backface-visibility:hidden;
  cursor: grab;
}
.kc__stage.is-drag .kc__card{ cursor: grabbing; }
/* кадр вписывается ЦЕЛИКОМ, а не по заполнению (Даниил 09.08: «фотка не
   помещается полностью»): в кольце лежат и квадратные работы, и портретные
   видео, при cover квадрат резался сверху и снизу. Свободное поле работает
   как паспарту - оно тонировано под мир блока */
.kc__card img, .kc__card picture{ display:block; width:100%; height:auto; }
.kc__card img, .kc__vid{
  width:100%; height:auto; max-height:100%; display:block;
  object-fit: contain;
}
/* вуаль по краям СНЯТА 13.08 (десктоп-проход): плоский цвет мира поверх
   фото-фона рисовал молочную плиту с жёсткими краями бокса сцены, а
   дальние карточки всё равно живут ЗА боксом - растворение краёв делает
   спад прозрачности карточек (--kc-o1/o2). Вернуть - git до 1840a79 */
/* стрелки: якорятся к корню карусели — на мобиле садятся в строку
   с точками у нижнего края, на десктопе уезжают на бока сцены */
.kc__arr{
  position:absolute; z-index:30; bottom:0;
  width:46px; height:46px; border-radius:50%;
  border:1px solid color-mix(in srgb, var(--ink) 30%, transparent);
  background: color-mix(in srgb, var(--bg-2) 78%, transparent);
  color: var(--ink); cursor:pointer;
  display:flex; align-items:center; justify-content:center;
  transition: background-color .18s ease, transform .18s ease;
}
.kc__arr:hover{ background: var(--bg-2); }
.kc__arr:active{ transform: scale(.94); }
.kc__arr--l{ left: calc(50% - 118px); }
.kc__arr--r{ right: calc(50% - 118px); }
.kc__caption{
  position:relative; z-index:6; margin: 14px 0 0; text-align:center;
  font-family:'PT Serif', serif; font-style:italic;
  font-size:.95rem; color: var(--ink);
  transition: opacity .2s ease;
}
.kc__caption.is-swap{ opacity:0; }
.kc__dots{
  position:relative; z-index:6;
  display:flex; gap:0; margin-top:6px; flex-wrap:nowrap;
  /* на мобиле точки живут между стрелками — им нужна своя высота строки */
  min-height:46px; align-items:center;
}
/* А8 ревью 13.08: точки - кнопки с хитбоксом 24px (были <i> 9px в
   aria-hidden контейнере: мимо тач-нормы и невидимы для AT).
   18.08: 24px всё равно меньше пальца - хитбокс 44px, кружок прежний 7px */
.kc__dot{
  appearance:none; border:0; margin:0; padding:0;
  width:44px; height:44px; border-radius:50%;
  background:transparent; cursor:pointer;
  display:flex; align-items:center; justify-content:center;
}
.kc__dot::before{
  content:""; width:7px; height:7px; border-radius:50%;
  background: color-mix(in srgb, var(--ink) 34%, transparent);
  transition: background-color .2s ease, transform .2s ease;
}
.kc__dot:hover::before{ transform:scale(1.5); background: color-mix(in srgb, var(--ink) 62%, transparent); }
.kc__dot.on::before{ background: var(--accent); transform:scale(1.35); }
/* пробы длин: JS меряет offsetWidth — так vw/px из переменных
   приходят готовыми пикселями без парсинга юнитов */
.kc__probe{ position:absolute; visibility:hidden; height:0; pointer-events:none; }
.kc__probe--x1{ width: var(--kc-x1); }
.kc__probe--x2{ width: var(--kc-x2); }

/* параллакс фона (см. app.js 4b): карточки карусели в параллаксе
   не участвуют — глубину даёт само кольцо */
@media (prefers-reduced-motion: no-preference){
  .k-bg__img{ transform: translate3d(0, var(--par-y, 0px), 0) scale(1.12); will-change: transform; }
}

/* 4/4 отзыв: переписка + видео-кружок + тихий мостик к заявке */
.k-review{
  --k-round: clamp(148px, 40vw, 200px);
  --k-bubble-bg: color-mix(in srgb, var(--bg-2) 95%, transparent);
  gap: clamp(16px, 3vh, 36px);
}
.k-review__lead{
  position:relative; z-index:5;
  font-family: 'PT Serif', serif; font-style: italic;
  font-size: var(--t-small); letter-spacing:.03em;
  color: color-mix(in srgb, var(--ink) 68%, var(--bg));
}
/* продающие сцены на экранах 3/3 блоков 2-3 (v2 12.08: v1 забракована
   «мелко, плохо видно», тексты те же). Лид - крючок сцены, кеглем выше
   тела; CTA - кеглем тела и с воздухом под палец. Тихая подпись
   .k-review__lead блока 1 не трогается - модификатор только у сцен */
.k-review--sell .k-review__lead{
  font-size: clamp(1.35rem, 5.8vw, 1.9rem); line-height:1.3;
  letter-spacing:.01em; max-width: 24ch;
  color: color-mix(in srgb, var(--ink) 94%, var(--bg));
  /* Рамка лида (.k-lead::before) выступает на 1.05em выше своего текста,
     а зазор был 22-24px - рамка приходила прямо под заголовок и читалась
     как наложение (скрин Даниила 18.08, миры 2/3/5). Отступ считаем от
     кегля рамки, а не от кегля заголовка. */
  margin-bottom: clamp(34px, 4.4vh, 52px);
}
@media (max-width: 719px){
  /* на узком рамка ближе к тексту (-.85em), запас нужен меньше */
  .k-review--sell .k-review__lead{ margin-bottom: 30px; }

  /* 18.08: после увеличения хитбокса точек до 44px ряд из шести-восьми штук
     перестал помещаться между стрелками и полез под них (скрин Даниила).
     На телефоне стрелки уводим к краям сцены, точку сужаем до 32px: кружок
     прежний, а промахнуться мешает соседняя стрелка 46px и свайп. */
  .kc__arr--l{ left: 6px; }
  .kc__arr--r{ right: 6px; left: auto; }
  /* точек бывает от четырёх до восьми: даём им ужиматься, но не уже 24px,
     иначе кружки слипаются. Сам кружок (::before) всегда 7px */
  .kc__dot{ flex: 0 1 32px; width: auto; min-width: 24px; height: 32px; }
  .kc__dots{ padding: 0 62px; max-width: 100%; }
}
/* Кнопка принадлежит тексту (закон близости, нюанс Даниила 12.08), но
   мерить близость надо до РАМКИ лида, а не до его текста: рамка уходит на
   1.05em ниже последней строки, и отрицательный отступ сажал кнопку прямо
   на неё (скрин Даниила 18.08, мир «Кит»). */
.k-review--sell .k-bridge{ margin-top: clamp(0px, .6vh, 8px); }
@media (max-width: 719px){
  .k-review--sell .k-bridge{ margin-top: 0; }      /* на узком рамка ближе: -.85em */
}
/* кружок стоит СБОКУ от переписки (как на скетче): пузыри слева узкой
   колонкой мессенджера, кружок справа по центру, едва внахлёст.
   Посадка в среду (06.08): группа чата — объект сцены с лёгким 3D-
   разворотом (язык входа и карусели), под ней световой карман-подиум,
   тени тёплые (rgba(64,52,34)), не чёрный UI */
.k-chat{
  position:relative; z-index:5;
  transform: perspective(1100px) rotateY(-4deg) rotateX(1deg);
}
/* световой карман: переписка лежит в тёплом пятне света, он же scrim */
.k-chat::before{
  content:""; position:absolute; inset:-16% -12% -18% -14%; z-index:-1;
  background: radial-gradient(52% 58% at 40% 50%,
    color-mix(in srgb, var(--bg-2) 85%, transparent),
    color-mix(in srgb, var(--bg-2) 42%, transparent) 58%, transparent 80%);
  border-radius: 32px;
  pointer-events:none;
}
.k-chat__stream{
  display:flex; flex-direction:column; gap:.6em;
  max-width: calc(100% - var(--k-round) * 0.92);
}
.k-bubble{
  position:relative;
  padding: .78em 1.05em .82em;
  border-radius: 16px 16px 16px 5px;
  background: var(--k-bubble-bg);
  line-height:1.45;
  box-shadow:
    0 10px 22px -14px rgba(64,52,34,.42),
    0 30px 54px -36px rgba(64,52,34,.3);
}
/* рукописность: каждый пузырь лежит со своим едва заметным креном */
.k-chat__stream .k-bubble:nth-child(odd){ transform: rotate(-.7deg); }
.k-chat__stream .k-bubble:nth-child(even){ transform: rotate(.55deg); }
.k-bubble::after{                            /* хвостик пузыря */
  content:""; position:absolute; left:-6px; bottom:0;
  width:12px; height:14px;
  background: var(--k-bubble-bg);
  clip-path: polygon(100% 0, 100% 100%, 0 100%);
}
/* скрытый текст для скринридеров: роли реплик в чатах (ревью 12.08) */
.sr-only{
  position:absolute; width:1px; height:1px;
  margin:-1px; padding:0; border:0;
  clip-path: inset(50%); overflow:hidden; white-space:nowrap;
}

/* мысль-поталь: ключевая эмоциональная фраза блока набрана «золотом» -
   материя самой работы становится типографикой (v2 12.08; v1-коробка
   забракована «скудно»). Без плашки: крупный сериф, золото с переливом
   внутри букв, сияние вокруг, при скролле по строке проезжает блик */
.k-pull{
  position:relative; z-index:5;
  max-width: 17ch;
  margin: clamp(22px, 4vh, 40px) 0;
  font-family: 'Prata', serif; font-weight:400;
  font-size: clamp(1.7rem, 7.4vw, 2.7rem);
  line-height: 1.24;
}
/* золото живёт на СВОЁМ слое-спане: при background-clip:text буквы -
   это фон элемента, и псевдо-подложка с z:-1 рисовалась бы ПОВЕРХ них
   (слой негативных z выше слоя background) - грабля v3 */
.k-pull__t{
  display:block;
  background: linear-gradient(104deg,
    color-mix(in srgb, var(--ink) 88%, var(--accent)) 0%,
    var(--accent) 32%,
    color-mix(in srgb, var(--accent) 55%, #fff) 46%,
    var(--accent) 60%,
    color-mix(in srgb, var(--ink) 82%, var(--accent)) 100%);
  background-size: 220% 100%;
  background-position: 88% 0;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  /* одна тень, не две: отрыв от фона даёт карман-подложка, а каждая
     drop-shadow на clip:text-слое - лишний пейнт при блике */
  filter: drop-shadow(0 0 16px color-mix(in srgb, var(--accent) 38%, transparent));
}
/* подложка (v3 12.08, «сливается с фоном»): тёмный карман-подиум под
   фразой - тот же театральный приём, что у плашки входа; золото горит
   на глубокой тени, а не спорит с бликами рельефа */
.k-pull::before{
  content:""; position:absolute; inset:-20% -16%; z-index:-1;
  background: radial-gradient(60% 64% at 46% 50%,
    color-mix(in srgb, var(--bg) 88%, #000) 0%,
    color-mix(in srgb, var(--bg) 82%, transparent) 56%,
    transparent 84%);
  border-radius: 40px;
  pointer-events:none;
}
/* фолбек: без clip:text фраза просто акцентного цвета */
@supports not ((-webkit-background-clip: text) or (background-clip: text)) {
  .k-pull__t{ background: none; color: var(--accent); }
}
/* блик потали проезжает по строке ходом скролла (native scroll-driven,
   как у .reveal). ТОЛЬКО десктоп-указка: на таче анимация background
   на clip:text-слое = пере-пейнт над каруселью каждый кадр листания
   (подозреваемый морга 12.08); статичный перелив тоже живой */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) and (hover: hover) and (pointer: fine) {
    .k-pull__t{
      animation: pullGlint linear both;
      animation-timeline: view();
      animation-range: entry 20% cover 75%;
    }
    @keyframes pullGlint{
      from{ background-position: 88% 0; }
      to  { background-position: 8% 0; }
    }
  }
}

/* ответный пузырь художника: правая сторона, зеркальный хвост, тёплая
   нить акцента в теле - диалог живёт, монолог лежит (эмоции 12.08) */
.k-bubble--art{
  --k-bubble-bg: color-mix(in srgb, var(--accent) 18%, var(--bg-2));
  align-self:flex-end;
  border-radius: 16px 16px 5px 16px;
}
.k-bubble--art::after{
  left:auto; right:-6px;
  clip-path: polygon(0 0, 0 100%, 100% 100%);
}
.k-round{
  position:absolute; right:0; top:50%; z-index:5;
  width: var(--k-round);
  transform: translateY(-52%);
}
/* тёплый ореол за кружком: среда отвечает объекту светом,
   как за активной карточкой карусели */
.k-round::before{
  content:""; position:absolute; inset:-24%; z-index:-1;
  background: radial-gradient(50% 50% at 50% 50%,
    rgba(255,250,238,.8), rgba(255,246,226,.3) 58%, transparent 76%);
  pointer-events:none;
}
.k-round__vid{
  display:block; width:100%; height:auto;
  aspect-ratio:1; object-fit:cover;
  border-radius:50%;
  background: color-mix(in srgb, var(--ink) 14%, transparent);
  /* паспарту-кайма + тёплая тень вместо чёрной UI-тени */
  border: 4px solid color-mix(in srgb, var(--bg-2) 92%, transparent);
  box-shadow:
    0 16px 36px -18px rgba(64,52,34,.5),
    0 42px 74px -42px rgba(64,52,34,.36);
}
.k-bridge{
  position:relative; z-index:5;
  font-size: var(--t-small); color: var(--ink-soft);
  max-width: 30ch;             /* не дотягивается до лейбла миров справа */
}
/* оффер-строка в хиро блока 1 (12.08, формула Даниила «Картина, которую
   можно почувствовать»): серифом, цена читается с первого экрана.
   v2 12.08: кегль и контраст подняты - v1 на --t-small забракована
   («мелко, плохо видно»), тексты без изменений */
.k-offerline{
  position:relative; z-index:5;
  margin-top: 1em;
  font-family:'PT Serif', serif; font-style:italic;
  font-size: clamp(1.02rem, 4.1vw, 1.25rem); line-height:1.45;
  letter-spacing:.02em;
  color: color-mix(in srgb, var(--ink) 92%, var(--bg));
}
.k-bridge a{
  color: var(--accent);
  border-bottom:1px solid color-mix(in srgb, var(--accent) 50%, transparent);
  padding-bottom:1px;
}
.k-bridge a:hover{ border-bottom-color: currentColor; }

/* --- CTA-кнопка «золотая кромка» (12.08): все CTA сцен и заявки - кнопки.
   Референс: Magic UI Shimmer Button (21st.dev id 833, выбор из каталога) -
   искра бежит по кромке; порт в vanilla без React: под кнопкой вращается
   conic-блик (::before), тело (::after) закрывает центр, тихое кольцо в
   1.5px - фон самой кнопки из-под ::after. Цвета мира - токены --cta-* */
.cta-btn{
  --cta-bg: #2B2015;
  --cta-ink: #F7F0E3;
  --cta-spark: #E9C877;
  position:relative; display:inline-flex; align-items:center; gap:.55em;
  padding: 1.22em 1.5em; border-radius:999px;
  overflow:hidden; isolation:isolate;
  /* Prata - голос заголовков сайта; 600 у Golos не загружен, давал
     фальшивую жирность (нюанс Даниила 12.08 «шрифт не самый удачный») */
  font-family: 'Prata', 'PT Serif', serif; font-weight:400; line-height:1;
  font-size: clamp(.92rem, 3.7vw, 1rem); letter-spacing:.04em;
  color: var(--cta-ink); cursor:pointer; border:0;
  background: color-mix(in srgb, var(--cta-spark) 34%, var(--cta-bg));
  box-shadow: 0 12px 26px -16px rgba(31,24,14,.55);
  transition: transform .18s ease;
}
.cta-btn::before{
  content:""; position:absolute; z-index:-2; left:50%; top:50%;
  width:250%; aspect-ratio:1;
  transform: translate(-50%,-50%) rotate(0turn);
  background: conic-gradient(
    transparent 0turn, transparent .70turn,
    var(--cta-spark) .865turn, transparent .995turn);
  animation: ctaSpin 3.6s linear infinite;
}
.cta-btn::after{
  content:""; position:absolute; z-index:-1; inset:1.5px;
  border-radius:inherit; background: var(--cta-bg);
  transition: background-color .18s ease;
}
.cta-btn:hover{ transform: translateY(-1px); }
.cta-btn:hover::after{ background: color-mix(in srgb, var(--cta-bg) 88%, var(--cta-spark)); }
.cta-btn:active{ transform: translateY(1px); }
@keyframes ctaSpin{ to{ transform: translate(-50%,-50%) rotate(1turn); } }
@media (prefers-reduced-motion: reduce){
  .cta-btn::before{ animation:none; }
}
/* глушим линк-стили мостиков на кнопке */
.k-bridge a.cta-btn{ color: var(--cta-ink); border-bottom:0; padding-bottom:.78em; }
/* цвета кнопки по мирам: уголь с угольком в «Громко», холодный графит
   в «Фразах»; искра-золото - сквозная (поталь = материал Жени) */
.sec--drive .cta-btn{ --cta-bg:#200F0A; --cta-spark:#FFB169; }
.sec--words .cta-btn{ --cta-bg:#1D2126; }

/* блок 1: подводка + кнопка отделены от переписки - свой момент в воздухе
   перед прогаром (вердикт 12.08 «неудачное расположение, мелкий текст») */
.k-bridge--sell{
  margin-top: clamp(28px, 5vh, 64px);
  max-width: 20ch;
  font-family:'PT Serif', serif; font-style:italic;
  font-size: clamp(1.2rem, 5vw, 1.6rem); line-height:1.35;
  letter-spacing:.01em;
  color: color-mix(in srgb, var(--ink) 92%, var(--bg));
}
/* кнопка сразу под фразой - одна группа, не отдельный элемент */
.k-cta{ position:relative; z-index:5; margin-top: clamp(10px, 1.8vh, 16px); }

@media (min-width: 768px){
  .k-story__body{ max-width: 40ch; }
  /* десктоп «кольцо-сцена»: соседи ±1 и ±2 видны по дуге, вуаль по
     краям включается, стрелки уезжают на бока сцены */
  .kc{
    --kc-w: clamp(280px, 30vw, 430px); --kc-h: clamp(340px, 56vh, 540px);
    --kc-x1: clamp(240px, 24vw, 370px); --kc-x2: clamp(400px, 42vw, 640px);
    --kc-r1: 35;  --kc-r2: 52;
    --kc-s1: .72; --kc-s2: .55;
    --kc-o1: 1;   --kc-o2: .7;
  }
  .kc__stage{ perspective:1500px; }
  .kc__arr{ bottom:auto; top: calc(var(--kc-h) / 2); transform: translateY(-50%); }
  .kc__arr:active{ transform: translateY(-50%) scale(.94); }
  .kc__arr--l{ left: clamp(4px, 1.5vw, 22px); }
  .kc__arr--r{ right: clamp(4px, 1.5vw, 22px); left:auto; }
  .kc__dots{ min-height:0; }
  .k-review{ --k-round: clamp(200px, 26vw, 260px); }
}

@media (min-width: 980px){
  .k-hero .sec__head{ max-width: 44rem; }
  /* кружок встаёт в поток справа от переписки */
  .k-chat{ display:flex; align-items:center; }
  .k-chat__stream{ max-width: 36ch; }
  .k-round{
    position:static; flex:0 0 auto; transform:none;
    margin-left: clamp(-40px, -2.4vw, -16px);
  }
}

/* спокойный режим: каскада нет, строки просто на месте */
@media (prefers-reduced-motion: reduce){
  .k-story .reveal, .k-story .reveal.is-in{ transition-delay: 0s !important; }
}

/* ---------- 9. Сломы-открытия ---------- */
/* Механика одна на все сломы: в верхней полосе входящей секции лежит
   краска ПРЕДЫДУЩЕГО мира, поверх неё новый мир «наливается» вниз по
   позиции скролла (--p). Фронт несёт фигурный край — он и даёт характер.
   Страница при этом не двигается сама: --p считается из scrollY. */
.open{
  position:absolute; left:0; right:0; top:0;
  height: var(--open-h);
  overflow:hidden; z-index:1;
  pointer-events:none;
}
/* полоса слома всегда пустая: контент секции начинается ниже неё */
.sec--words, .sec--wild, .sec--deep, .sec--warm{
  padding-top: calc(var(--sec-pad-y) + var(--open-h));
}
.open.is-done{ display:none; }
.open__base{ position:absolute; inset:0; background: var(--prev-bg, var(--bg)); }
.open__fill{
  position:absolute; inset:0; background: var(--bg);
  transform: scaleY(var(--p, 1)); transform-origin: top center;
}
.open__edge{
  position:absolute; left:0; right:0; top:-1px;
  height: clamp(30px, 5.6vw, 64px);
  transform: translate(var(--jx, 0px), calc(var(--p, 1) * var(--open-h)));
}
.open__edge > svg{ display:block; width:100%; height:100%; }
.open__edge path{ fill: var(--bg); }

/* 1→2 Драйв: слом делает прогар burn2 (раздел 14), у секции ширмы-open нет */

/* 2→3 Фразы: лист бумаги разворачивается — светлый край и утечка света */
.sec--words{ --prev-bg:#0B0909; }
.open--paper .open__fill{
  /* лист ложится: край чуть скошен и выпрямляется к концу открытия */
  transform: scaleY(var(--p, 1)) skewY(calc((1 - var(--p, 1)) * -1.1deg));
}
.open--paper .open__edge{
  height: clamp(60px, 11vw, 130px);
  transform: translate(var(--jx, 0px), calc(var(--p, 1) * var(--open-h))) skewY(calc((1 - var(--p, 1)) * -1.1deg));
  background: linear-gradient(to bottom, rgba(255,247,232,.32), rgba(255,247,232,.06) 38%, rgba(255,247,232,0) 78%);
}
.open--paper .open__crease{
  position:absolute; left:-4%; right:-4%; top:0; height:2px;
  background: linear-gradient(to right, rgba(255,255,255,.15), rgba(255,255,255,.9) 22%, rgba(255,255,255,.6) 72%, rgba(255,255,255,.1));
  box-shadow: 0 0 18px 2px rgba(255,244,220,.35);
}

/* 3→4 Природа: занавес джунглей — край из листьев + створки по бокам */
.sec--wild{ --prev-bg:#EFF0EC; }
.open--leaf .open__edge{ height: clamp(54px, 10vw, 112px); }
.open__curtain{
  position:absolute; top:0; bottom:0; width:32%;
  opacity: calc(1 - var(--p, 1));
}
.open__curtain svg{ width:100%; height:100%; display:block; }
.open__curtain path, .open__curtain use{ fill: var(--bg); }
.open__curtain--l{ left:0;  transform: translateX(calc(var(--p, 1) * -104%)); }
.open__curtain--r{ right:0; transform: translateX(calc(var(--p, 1) *  104%)); }

/* 4→5 Космос: волна воды заливает экран, звёзды проступают
   (фолбек reduced-motion; в дефолте слом рисует voda.js).
   prev-bg = хвост мира 4 после пересборки 12.08 - глубокая зелень */
.sec--deep{ --prev-bg:#0E1A0C; }
.open--wave .open__edge{ height: clamp(38px, 6.6vw, 76px); overflow:hidden; }
.open--wave .open__edge > svg{ width:140%; animation: waveDrift 11s linear infinite; }
@keyframes waveDrift{ to{ transform: translateX(-12.5%); } }
.open__foam{ stroke: rgba(200,222,255,.5); stroke-width:2; }
.open__stars{
  position:absolute; inset:0; opacity: var(--p, 1);
  background-image:
    radial-gradient(1.4px 1.4px at 11% 24%, #EAE2FF 45%, transparent 46%),
    radial-gradient(1.2px 1.2px at 26% 62%, #D9CEF3 45%, transparent 46%),
    radial-gradient(1.6px 1.6px at 39% 15%, #FFF6E0 45%, transparent 46%),
    radial-gradient(1.1px 1.1px at 52% 48%, #CFC3EE 45%, transparent 46%),
    radial-gradient(1.5px 1.5px at 64% 78%, #EAE2FF 45%, transparent 46%),
    radial-gradient(1.2px 1.2px at 77% 33%, #D9CEF3 45%, transparent 46%),
    radial-gradient(1.7px 1.7px at 88% 66%, #FFF6E0 45%, transparent 46%),
    radial-gradient(1.1px 1.1px at 94% 12%, #CFC3EE 45%, transparent 46%),
    radial-gradient(1.3px 1.3px at 18% 88%, #EAE2FF 45%, transparent 46%),
    radial-gradient(1.2px 1.2px at 45% 92%, #D9CEF3 45%, transparent 46%);
}

/* 5→6 Тепло: рассвет — свет раскрывается снизу как диафрагма луча */
.sec--warm{ --prev-bg:#140F1D; }
.open--dawn .open__fill{ transform-origin: bottom center; }
.open--dawn .open__edge{
  top:auto; bottom:-1px; height: clamp(70px, 14vw, 150px);
  transform: translateY(calc(var(--p, 1) * var(--open-h) * -1));
  background: linear-gradient(to top, var(--bg), color-mix(in srgb, var(--bg) 40%, transparent) 52%, transparent);
}
.open--dawn .open__glow{
  position:absolute; left:50%; bottom:-8%; width:170%; height:130%;
  transform: translateX(-50%) scale(calc(.35 + var(--p, 1) * .85));
  opacity: var(--p, 1);
  background: radial-gradient(50% 50% at 50% 100%, rgba(255,213,140,.72), rgba(255,186,86,.20) 46%, transparent 72%);
}

/* 6→7 Заявка: без спецэффекта — только волосок и жест самой нити */
.sec--offer{ --prev-bg:#1A1108; }  /* хвост мира 6 - тёплая умбра (13.08) */
/* волосок золота по границе тепла и заявки — единственный «тихий» слом */
.sec--offer .sec__world::before{
  content:""; position:absolute; z-index:2;
  top:0; left: var(--pad-x); right: var(--pad-x);
  height:1px; background: var(--accent); opacity:.5;
  transform: scaleX(0); transform-origin: left center;
}
@supports (animation-timeline: view()){
  @media (prefers-reduced-motion: no-preference){
    .sec--offer .sec__world::before{
      animation: hair 1s linear both;
      animation-timeline: view();
      animation-range: cover 0% cover 18%;
    }
  }
}
@keyframes hair{ to{ transform: scaleX(1); } }

/* ---------- 9a. Прогар 1→2 (burn2) ----------
   Легаси-ширма (.c12/.c12__ember/.c12__scar/html.c12-css, ~120 строк)
   СНЕСЕНА ревью 13.08 - CSS-путь был недостижим с выката burn2 08.08.
   Вернуть - git до a8f60fb. Здесь остались только живые части. */

/* канвас прогара burn2-gl (класс переиспользован от старой ширмы): НАД
   контентом обоих миров (z5 + позиция после <main> в DOM), но ПОД каплей
   нити (.thread--head, z-index 6) */
.c12gl{
  position:fixed; inset:0; z-index:5;
  width:100%; height:100%;
  pointer-events:none;
}

/* секция драйва: --thread-solid держит геометрический сэндвич нити (см.
   build() в thread.js) */
.sec--drive{
  --thread-solid: 1;
}

/* ---------- 10. Заявка ---------- */
.sec--offer{ min-height: auto; }
.offer{ position:relative; z-index:5; max-width: 46ch; }
.offer__price{
  font-family: var(--f-display); font-weight:600;
  font-size: clamp(1.7rem, 7vw, 2.9rem); letter-spacing:-.03em;
  color: var(--accent);
  margin-bottom:.6em;
}
.offer__facts li{
  padding: .55em 0 .55em 1.1em; position:relative;
  border-bottom:1px solid color-mix(in srgb, var(--ink) 14%, transparent);
}
.offer__facts li::before{
  content:""; position:absolute; left:0; top:1.05em;
  width:6px; height:1px; background: var(--accent);
}
.btn{
  display:inline-flex; align-items:center; gap:.7em;
  margin-top: 1.8em;
  padding: .95em 1.5em;
  border-radius: 999px;
  background: var(--accent); color:#1A1206;
  font-weight:500; letter-spacing:.01em;
  transition: transform .18s ease, background-color .18s ease;
}
.btn:hover{ transform: translateY(-2px); }
/* главная CTA заявки переведена на .cta-btn (12.08) - отступ от .btn остаётся */
.offer .cta-btn{ margin-top: 1.8em; }
.btn--ghost{
  background: transparent; color: var(--ink);
  border:1px solid color-mix(in srgb, var(--ink) 32%, transparent);
  border-radius: 999px; margin-top:1.4em;
}
.offer__hint{ margin-top:1.1em; color: var(--ink-soft); font-size: var(--t-small); max-width:34ch; }

/* Б2 - факты процесса (срок/оплата/доставка). Мобильный складывает метку над
   значением: на 375px двухколоночная сетка рвала «после согласования эскиза» */
.offer__spec{ margin-top:1.6em; }
.offer__spec > div{
  padding:.6em 0;
  border-bottom:1px solid color-mix(in srgb, var(--ink) 14%, transparent);
}
.offer__spec dt{
  font-size:.74rem; letter-spacing:.18em; text-transform:uppercase;
  color: color-mix(in srgb, var(--ink) 72%, var(--bg));
  margin-bottom:.3em;
}
.offer__spec dd{ margin:0; }
@media (min-width: 768px){
  .offer__spec > div{ display:grid; grid-template-columns: 8em 1fr; gap:1em; align-items:baseline; }
  .offer__spec dt{ margin-bottom:0; }
}

.fform{ position:relative; z-index:5; max-width: 34ch; }
.fform__title{
  font-size:.74rem; letter-spacing:.18em; text-transform:uppercase; color: var(--ink-soft);
  margin-bottom:1.2em;
}
.fld{ display:block; margin-bottom:1.1em; }
.fld span{ display:block; font-size:.74rem; letter-spacing:.1em; text-transform:uppercase; color: var(--ink-soft); margin-bottom:.35em; }
.fld input{
  width:100%; background:transparent; border:0; border-bottom:1px solid color-mix(in srgb, var(--ink) 30%, transparent);
  border-radius:0; padding:.5em 0; outline:none;
}
.fld input:focus{ border-bottom-color: var(--accent); }
.fform__status{ margin-top:1em; font-size: var(--t-small); color: var(--accent); min-height:1.4em; }

@media (min-width: 980px){
  .sec__inner--offer{ align-items:start; }
  .sec__inner--offer .sec__head{ grid-column: 1 / 8; grid-row:1; }
  .offer{ grid-column: 1 / 7; grid-row: 2; }
  /* 8/-1: 12-я колонка пустовала всегда, форма выглядела недотянутой (MED #15) */
  .fform{ grid-column: 8 / -1; grid-row: 2; }
}
/* А6 ревью 13.08: блок заявки возвращён в типо-систему сайта. Заголовок
   и цена были Unbounded 600 (геометрический гротеск) против Prata шести
   миров - экран заявки выглядел другим сайтом. Гротеск остаётся только
   служебным лейблам (eyebrow, подписи полей) */
.sec--offer .sec__title{ font-family:'Prata','PT Serif',serif; font-weight:400; letter-spacing:.01em; line-height:1.04; }
.offer__price{ font-family:'Prata','PT Serif',serif; font-weight:400; letter-spacing:0; }
/* контрасты (ревью: заголовок формы 2.98:1, placeholder 1.91:1) */
.fform__title{ color: color-mix(in srgb, var(--ink) 72%, var(--bg)); }
.fld input::placeholder{ color: color-mix(in srgb, var(--ink) 52%, transparent); }
/* «Отправить» - высота в строй CTA миров */
.fform .btn{ font-size:1rem; padding:.82em 1.6em; }

/* ---------- 11. Подвал ---------- */
.foot{
  position:relative; z-index:5;
  background:#0F0B07; color:#8D7F6C;
  padding: clamp(40px, 8vh, 90px) var(--pad-x);
  font-size: var(--t-small);
  display:grid; gap: clamp(26px, 4vw, 48px);
  grid-template-columns: 1fr;
}
@media (min-width: 720px){ .foot{ grid-template-columns: repeat(4, auto); justify-content:space-between } }
.foot__col{ display:flex; flex-direction:column; gap:0 }
/* 18.08: у ссылок подвала было 23px высоты - зона нажатия вместо промежутка */
.foot__col a{ padding:.8em 0 }
.foot__col--law a{ padding:.8em 0 }
.foot__name{ color:#D9CDBA; font-family:'Prata',serif; font-size:1.05rem; margin:0 }
.foot__col p{ margin:0 }
.foot__ttl{ color:#8D7F6C; text-transform:uppercase; letter-spacing:.14em; font-size:.74rem;
            margin:0 0 .3em !important }
.foot a{ color:#B9AA95; text-decoration:none; width:fit-content;
         border-bottom:1px solid transparent; transition:color .18s ease, border-color .18s ease }
.foot a:hover{ color:#D9CDBA; border-bottom-color:currentColor }
.foot__col--law{ gap:.8em }
.foot__small{ color:#8D7F6C; font-size:.78rem }
.foot a sup{ font-size:.7em; line-height:0; vertical-align:super; margin-left:.1em }
/* сноска идёт отдельной строкой под всеми колонками */
.foot__disclaimer{ grid-column:1/-1; margin:0; color:#8A7C68; font-size:.74rem;
                   line-height:1.5; max-width:66ch;
                   border-top:1px solid #241C13; padding-top:1.4em }

/* ---------- 12. Ревилы ---------- */
/* простое — нативным CSS scroll-driven; JS-фолбек только там, где не поддержано */
.reveal{ opacity:0; transform: translateY(14px); }
.reveal.is-in{ opacity:1; transform:none; transition: opacity var(--dur) ease-out, transform var(--dur) ease-out; }
@supports (animation-timeline: view()){
  @media (prefers-reduced-motion: no-preference){
    .reveal{ animation: rise 1s linear both; animation-timeline: view(); animation-range: entry 6% cover 26%; }
  }
}
@keyframes rise{ to{ opacity:1; transform:none; } }

/* ---------- 13. Спокойный режим ---------- */
@media (prefers-reduced-motion: reduce){
  *,*::before,*::after{ animation-duration:.001ms !important; animation-iteration-count:1 !important; transition-duration:.001ms !important; }
  .reveal{ opacity:1 !important; transform:none !important; animation:none !important; }
  .sec--offer .sec__world::before{ transform: scaleX(1); animation:none !important; }
  .open{ display:none; }        /* сломы — статичные цветовые границы */
  .c12gl{ display:none; }       /* канвас прогара в спокойном режиме не создаётся */
  .sec--drive{ clip-path:none; }
  #thParts{ display:none; }     /* нить дорисована целиком, без частиц */
  .fx{ display:none; }
  /* H3 ревью 13.08: верхний запас фоновых сэндвичей (-26lvh, задуман под
     дышащий бар при ПИНЕ) без пина и z-лесенки наезжает на хвост
     предыдущего блока - в спокойном режиме запас не нужен */
  .d-bg{ inset:0; }
  /* стыки миров без пина - жёсткая граница: финальной сцене нужен воздух,
     иначе CTA-кнопка липнет к шву (десктоп-проход 13.08) */
  .k-review{ padding-bottom: clamp(72px, 12vh, 160px); }
}
/* режим «без анимаций» кнопкой (13.08): точный дубль reduce-блока выше -
   класс ставится инлайн-скриптом head ДО первой отрисовки и снимается
   только перезагрузкой (морга нет: анимации не пересоздаются на живой
   странице). JS-потребители reduced накрыты подменой matchMedia там же.
   Правишь reduce-блок - правь и этот */
html.anim-off *, html.anim-off *::before, html.anim-off *::after{ animation-duration:.001ms !important; animation-iteration-count:1 !important; transition-duration:.001ms !important; }
html.anim-off .reveal{ opacity:1 !important; transform:none !important; animation:none !important; }
html.anim-off .sec--offer .sec__world::before{ transform: scaleX(1); animation:none !important; }
html.anim-off .open{ display:none; }
html.anim-off .c12gl{ display:none; }
html.anim-off .sec--drive{ clip-path:none; }
html.anim-off #thParts{ display:none; }
html.anim-off .fx{ display:none; }
/* H3 ревью 13.08: дубли ОСТАЛЬНЫХ четырёх reduce-блоков (перья, осколки,
   кнопка, k-story) - без них перья блока 1 сбивались кучей top:0 */
html.anim-off .k-fall__f--1{ top:12%; }
html.anim-off .k-fall__f--2{ top:34%; }
html.anim-off .k-fall__f--3, html.anim-off .k-fall__f--5, html.anim-off .k-fall__f--6{ display:none; }
html.anim-off .k-fall__f--4{ top:58%; }
html.anim-off .d-fall__e--1{ top:18%; }
html.anim-off .d-fall__e--3{ top:52%; }
html.anim-off .d-fall__e--2, html.anim-off .d-fall__e--4, html.anim-off .d-fall__e--5, html.anim-off .d-fall__e--6{ display:none; }
html.anim-off .cta-btn::before{ animation:none; }
html.anim-off .k-story .reveal, html.anim-off .k-story .reveal.is-in{ transition-delay: 0s !important; }
html.anim-off .d-bg{ inset:0; }
html.anim-off .k-review{ padding-bottom: clamp(72px, 12vh, 160px); }

/* ---------- 14. ПРОБА ?burn2=1: «сгорает сама страница» (ширма 1→2 v2) ----------
   Флаг кладёт html.burn2 (burn2.js) до инициализации ScrollTrigger.
   Блок 2 подтянут под последний экран блока 1 — при двойном пине миры
   стоят друг за другом: воздух сверху (z5, лесенка air5>rz4>ln3>vd2>zl1) выгорает живым clip-path
   (SVG #burn2clip), сквозь дыры виден настоящий драйв (z1). Канвас
   огня .c12gl (z5) — общий с прежним прогаром. Без флага этих правил
   не существует, живой путь не тронут. */
html.burn2 .sec--air{ z-index:5; }  /* лесенка миров air5>rz4>ln3>vd2>zl1 (сдвиг 13.08 под слом 5→6) */
/* Перекрытие = 100 + BRAKE_VH·100 из burn2.js. Торможение выключено
   (приёмка 08.08), поэтому ровно экран: мир 2 встаёт фулскрином в кадр
   прибивания, выход из пина бесшовный — менять только вместе с BRAKE_VH.
   Маргин живёт на ОБЁРТКЕ .rz-hold (с 10.08), а не на секции: когда пин
   слома 2→3 уводит обёртку в fixed, схлоп маргина через неё рвался бы и
   всё после прыгало на 100svh; на самой обёртке ST переносит маргин в
   свой спейсер честно (тот же путь, что у drive в ширме 1→2) */
html.burn2 .rz-hold{ margin-top:-100vh; margin-top:-100svh; }
html.burn2 .sec--drive{ z-index:1; }
/* ЗАМЕР (?diag=1, diag.js): тумблер вязкого входа — перекрытие углубляется
   на зону торможения. Удаляется вместе с diag.js */
html.burn2.diag-brake .rz-hold{ margin-top:-135vh; margin-top:-135svh; }
html.burn2 .sec--air.burn2-full{ visibility:hidden; }

/* строка-мостик и кнопка не должны рождаться под самой кромкой прогара:
   дыхание под последним экраном — на пине строка стоит выше кромки и
   читается, пока низ уже тлеет (жалоба приёмки 07.08) */
/* + «воздух» после блока (приёмка 07.08: переход шёл впритык к контенту) —
   после строки-мостика выдох фактуры фона перед тем, как экран встанет */
html.burn2 .k-review{ padding-bottom: clamp(280px, 50svh, 620px); }

/* дожим скролл-ревилов у пина: и нативный view()-путь, и JS-фолбэк
   (иначе пузыри у кромки замирают полупрозрачными — «полоски» фактуры
   видео-фона сквозь недопроявленный пузырь, скрин Даниила 07.08).
   ⚠️ БЕЗ animation:none - его снятие пересоздаёт view()-анимацию, и на
   кадр привязки timeline весь контент стоит в базовом .reveal{opacity:0}
   (морг блока 5, видео Даниила 12.08); дожим держат сами important-
   объявления - в каскаде они сильнее keyframe-значений */
html.burn2 .sec--air.burn2-near .reveal{
  opacity: 1 !important;
  transform: none !important;
  transition: opacity .4s ease-out, transform .4s ease-out;
}

/* запас мира 1 ниже кромки секции: когда адресная строка мобилы прячется,
   вьюпорт вырастает, а пин держит страницу по старой высоте - без запаса
   в щели снизу светился мир 2 / подложка. Фон и фактура видео дотягиваются
   на BAND_PAD ниже; сгорают тем же фронтом (поле расширено в burn2.js) */
html.burn2 .sec--air .sec__world{ bottom:-160px; }
html.burn2 .sec--air .k-bg{ bottom:-160px; }

/* «белое» в воздухе на телефоне (Даниил 07.08): два вора фактуры разом.
   (1) слои фона были ростом 100svh - бар прячется, низ голый;
   (2) торможение подтягивает страницу вверх до BRAKE (35svh), и кадр
   фона уезжает вместе с ней - снизу открывалась полоса подложки.
   135lvh = экран со спрятанным баром + запас торможения: фактура
   покрывает воздух при любом состоянии бара и в любой фазе вязкости */
html.burn2 .k-bg__pic{ height:135lvh; }
html.burn2 .k-bg__live{ height:135lvh; margin-top:-135lvh; }
html.burn2 .k-bg__vid{ height:calc(135lvh + 16svh); }
/* вуаль обязана расти вместе со слоями: у неё плотные стопы на кромках,
   и её край в кадре читается «полоской» светлой пелены на фактуре */
html.burn2 .k-bg__veil{ height:135lvh; margin-top:-135lvh; }

/* ---------- 15. Блок 2 «Громко»: мир драйва ----------
   Собран 08.08 по анатомии блока 1 (приёмка Даниила: «блок 2 так же, как
   блок 1, и что-то огненное»). Тот же sticky-сэндвич фона, но мир тёмный:
   угольная фактура КГ·Звук живой петлёй, зарево снизу дышит как бас,
   искры летят вверх (частицы блока уже стояли в палитре: spark).
   Слои ростом РОВНО 100lvh: lvh уже считает экран со спрятанным баром, а
   любой запас сверх него отлипает от sticky ДО конца секции и рисует шов на
   хвосте блока (поймано на приёмке 08.08). Двигать высоты - только у всех
   слоёв разом: разнобой даёт видимую линию. ------------------------------ */
.sec--drive{ padding: 0; }
.sec--drive .k-inner{ display:block; }

/* БЕЗ overflow на контейнере: Safari трактует clip как hidden, контейнер
   становится скролл-контейнером, и sticky-слои перестают липнуть к экрану -
   сверху блока открывалась чёрная полоса (скрин Даниила 09.08, айфон).
   Задачу «кадр не вылезает за секцию» решаем иначе: масштаб живёт на
   ВЛОЖЕННОЙ картинке, а обёртка ростом ровно 100lvh её обрезает */
.d-bg{ position:absolute; inset:-26lvh 0 0 0; z-index:1; }
/* ЗАПАС СВЕРХУ 26lvh - не декоративный. Перекрытие блока 2 задано в svh
   (margin-top:-100svh, блок 14), а это высота экрана с ВИДИМОЙ адресной
   строкой. Стоит строке спрятаться - экран вырастает до lvh, а блок
   подтянут по-прежнему на svh, и сверху открывается полоса без мира:
   ровно в высоту спрятанной строки. Скрин Даниила 09.08, айфон.
   Лечим запасом геометрии, а НЕ переводом перекрытия в lvh: перекрытие
   связано с математикой пина (правило 100 + BRAKE·100, см. burn2.js),
   трогать его - значит пересобирать выверенный переход */
.d-bg__pic{
  position:sticky; top:0;
  display:block; height:100lvh; overflow:hidden;
  background: var(--bg);
}
.d-bg__img{ display:block; width:100%; height:100%; object-fit:cover; opacity:.85; }
@media (prefers-reduced-motion: no-preference){
  .d-bg__img{ animation: dbDrift 38s ease-in-out infinite alternate; }
  @keyframes dbDrift{
    from{ transform: scale(1.08) translate3d(0,0.7%,0); }
    to  { transform: scale(1.16) translate3d(0,-0.8%,0); }
  }
}
/* живая петля: та же механика, что у блока 1 (is-live ставит app.js по
   событию playing, --kbv-y - дрейф по скроллу из app.js) */
.d-bg__live{
  position:sticky; top:0;
  display:block; height:100lvh; margin-top:-100lvh;
  overflow:hidden;
}
/* дрейф петли: у блока 1 его тянет скролл-параллакс (--kbv-y, app.js прибит
   к #s-air), здесь фон живёт сам - запас 16lvh разъезжается собственным
   медленным ходом. Так проще и дешевле: одна анимация вместо второго
   scroll-linked слоя, а на кромке пина ничего не дёргается */
.d-bg__vid{
  display:block; width:100%; height:116lvh;
  object-fit:cover;
  filter: brightness(.82) saturate(.92);   /* тише по яркости, а не по альфе */
  opacity:0; transition: opacity 1.4s ease;
}
.d-bg__vid.is-live{ opacity:1; }   /* НЕ приглушать непрозрачностью: под видео
   лежит постер, и на разнице просвечивала прежняя картинка двойным кадром
   (поймано Даниилом 09.08). Приглушение - только вуалью и фильтром ниже */
@media (prefers-reduced-motion: no-preference){
  .d-bg__vid{ animation: dbVidDrift 44s ease-in-out infinite alternate; }
  @keyframes dbVidDrift{
    from{ transform: translate3d(0,0,0); }
    to  { transform: translate3d(0,-14lvh,0); }
  }
}

/* ЗАРЕВО: два очага жара снизу кадра - как от невидимой сцены за краем.
   Дышит медленно (бас), не мигает: мигание на тёмном читается как баг */
.d-bg__heat{
  position:sticky; top:0;
  display:block; height:100lvh; margin-top:-100lvh;
  pointer-events:none;
  background:
    radial-gradient(72% 42% at 26% 104%, rgba(226,59,46,.62), transparent 66%),
    radial-gradient(58% 34% at 78% 108%, rgba(255,120,42,.42), transparent 68%),
    radial-gradient(90% 60% at 50% 128%, rgba(255,74,26,.34), transparent 70%);
  mix-blend-mode: screen;
}
@media (prefers-reduced-motion: no-preference){
  /* дыхание баса: гоняем сам градиент и прозрачность, БЕЗ transform -
     масштабированный слой вылезал за секцию (см. комментарий у .d-bg) */
  .d-bg__heat{
    background-size: 100% 104%, 100% 104%, 100% 104%;
    animation: heatBreath 4.6s ease-in-out infinite alternate;
  }
  @keyframes heatBreath{
    from{ background-position: 50% 102%, 50% 104%, 50% 106%; opacity:.72; }
    to  { background-position: 50% 98%,  50% 99%,  50% 100%; opacity:1; }
  }
}
/* виньетка: держит читаемость светлого текста на горячем фоне */
.d-bg__veil{
  position:sticky; top:0;
  display:block; height:100lvh; margin-top:-100lvh;
  background:
    linear-gradient(to bottom,
      color-mix(in srgb, var(--bg) 72%, transparent) 0%,
      color-mix(in srgb, var(--bg) 34%, transparent) 24%,
      color-mix(in srgb, var(--bg) 30%, transparent) 62%,
      color-mix(in srgb, var(--bg) 78%, transparent) 100%),
    radial-gradient(120% 78% at 50% 40%, transparent 34%, color-mix(in srgb, var(--bg) 62%, transparent) 100%);
}
/* зум-лайт: гасим то же, что и в блоке 1 - видео и blend-слои */
html.zoom-lite .d-bg__vid,
html.zoom-lite .d-bg__heat{ display:none !important; }
html.zoom-lite .d-bg__pic{ animation:none; }


.d-hero3d .sec__title{
  color: var(--ink);
  text-shadow:
    0 1px 0 rgba(255,150,90,.5),
    0 0 26px rgba(226,59,46,.42),
    0 14px 40px rgba(0,0,0,.75);
}
/* на угольной фактуре приглушённый тон блока 1 тонет - держим контраст
   светлым тоном и мягкой тенью, а не увеличением кегля */
.d-hero3d .opening{
  color: color-mix(in srgb, var(--ink) 82%, transparent);
  text-shadow: 0 2px 14px rgba(0,0,0,.85);
}
.sec--drive .k-lead{ text-shadow: 0 2px 12px rgba(0,0,0,.7); }
/* продающая сцена 3/3 стоит на том же живом видео - лиду ту же тень
   (CTA теперь кнопка со своим телом, тень ей не нужна) */
.sec--drive .k-review--sell .k-review__lead{ text-shadow: 0 2px 12px rgba(0,0,0,.7); }
.d-hero3d .stroke{ color: var(--accent); }

/* рамка мира 2: чистый тон света, без примеси акцента - красная рамка
   на угле читается как предупреждение, а не как окантовка */
.sec--drive{ --lead-frame: color-mix(in srgb, var(--ink) 24%, transparent); }

/* заглушки блока (данных от Жени пока нет): не притворяются контентом -
   пунктирная кромка и приглушённый тон честно говорят «здесь будет» */
.k-bubble--stub{
  border: 1px dashed color-mix(in srgb, var(--ink) 26%, transparent);
  background: color-mix(in srgb, var(--bg-2) 46%, transparent);
  color: var(--ink-soft);
}
/* кружок-заглушка держит форму сам: настоящий кружок получает высоту от
   видео внутри (aspect-ratio), у пустого её брать неоткуда */
.k-round--stub{
  display:grid; place-items:center;
  aspect-ratio:1; border-radius:50%;
  border: 1px dashed color-mix(in srgb, var(--ink) 30%, transparent);
  background: color-mix(in srgb, var(--bg-2) 40%, transparent);
}
/* ореол за кружком в тёмном мире - тёплый уголь, а не белый свет:
   белый нимб на угольной фактуре читается как дыра */
.sec--drive .k-round::before{
  background: radial-gradient(50% 50% at 50% 50%,
    rgba(226,59,46,.34), rgba(120,30,20,.16) 58%, transparent 76%);
}
.k-round__hint{
  font-size: clamp(11px, 1.4vw, 13px);
  letter-spacing:.08em; text-transform:uppercase;
  color: var(--ink-soft); text-align:center; line-height:1.5;
}
/* --- СЛОЙ АРТЕФАКТА мира драйва: СЕЙЧАС ПУСТ (09.08, «свинец не в тему»).
   Разметка снята из index.html, механика оставлена рабочей - вернуть объект
   значит положить шесть span'ов с картинками, ход и кувырок уже настроены.
   История попыток и почему они не подошли:
   Урок замены: артефакт должен быть ДРУГОЙ природы, чем среда. Головешки
   повторяли новый фон-корку и переставали читаться как объекты; свинец даёт
   двойной контрапункт - холодный металл против жара и падение вниз против
   текущего вверх огня. Материал взят из самой работы: «красное полотно и
   свинцовый рельеф». Картинки - Higgsfield nano_banana_2 на чёрном фоне,
   вырезаны заливкой от углов. Как у перьев: ход на обёртке, кувырок на
   вложенном - трансформы не спорят; дальние мельче и размытее --- */
.d-fall{
  position:sticky; top:0; height:100lvh;
  overflow:clip; pointer-events:none;
  z-index:2;              /* над .d-bg (z1), под контентом мира */
}
.d-fall__e{ position:absolute; top:0; }
.d-fall__e img{
  display:block; width:100%; height:auto;
  /* металл не светится сам: даём ему вес тенью и лёгкий тёплый отсвет от
     жара снизу - как будто среда отражается в кромке */
  filter: drop-shadow(0 0 10px rgba(226,59,46,.22))
          drop-shadow(0 14px 30px rgba(0,0,0,.68));
}

.d-fall__e--1{ left:8%;  width:min(148px,13vw); opacity:.94; }
.d-fall__e--2{ left:31%; width:min(86px,7.5vw); opacity:.6;  filter:blur(1.2px); }
.d-fall__e--3{ left:57%; width:min(178px,15vw); opacity:.96; }
.d-fall__e--4{ left:82%; width:min(74px,6.5vw); opacity:.52; filter:blur(1.8px); }
.d-fall__e--5{ left:20%; width:min(116px,10vw); opacity:.82; }
.d-fall__e--6{ left:70%; width:min(98px,8.5vw); opacity:.68; filter:blur(1px); }

@media (prefers-reduced-motion: no-preference){
  .d-fall__e{ animation: dRise linear infinite; }
  .d-fall__e img{ animation: dTumble ease-in-out infinite alternate; }
  .d-fall__e--1{ animation-duration:21s; animation-delay:-5s; }
  .d-fall__e--1 img{ animation-duration:4.2s; }
  .d-fall__e--2{ animation-duration:29s; animation-delay:-17s; }
  .d-fall__e--2 img{ animation-duration:6.1s; animation-delay:-2s; }
  .d-fall__e--3{ animation-duration:18s; animation-delay:-10s; }
  .d-fall__e--3 img{ animation-duration:3.6s; animation-delay:-1s; }
  .d-fall__e--4{ animation-duration:26s; animation-delay:-22s; }
  .d-fall__e--4 img{ animation-duration:5.2s; animation-delay:-3s; }
  .d-fall__e--5{ animation-duration:23s; animation-delay:-14s; }
  .d-fall__e--5 img{ animation-duration:4.6s; animation-delay:-1.8s; }
  .d-fall__e--6{ animation-duration:20s; animation-delay:-7s; }
  .d-fall__e--6 img{ animation-duration:3.9s; animation-delay:-2.6s; }
  /* свинец падает: тяжело, почти отвесно, сносит чуть в сторону.
     Контрапункт к фону - жар в трещинах течёт вверх */
  @keyframes dRise{
    from{ transform: translate3d(0,-46lvh,0); }
    to  { transform: translate3d(-4vw,118lvh,0); }
  }
  /* кувырок литого куска: медленный и короткий, металл не порхает */
  @keyframes dTumble{
    from{ transform: rotate(-13deg) translateX(-3%); }
    to  { transform: rotate(9deg)   translateX(4%); }
  }
}
/* спокойный режим: пара головешек стоит тлеющей декорацией, ничего не летит */
@media (prefers-reduced-motion: reduce){
  .d-fall__e--1{ top:18%; }
  .d-fall__e--3{ top:52%; }
  .d-fall__e--2, .d-fall__e--4, .d-fall__e--5, .d-fall__e--6{ display:none; }
}
/* мобила: три куска вместо шести, крупнее по доле экрана */
@media (max-width: 767px){
  .d-fall__e--2, .d-fall__e--4, .d-fall__e--6{ display:none; }
  .d-fall__e--1{ width:21vw; }
  .d-fall__e--3{ width:26vw; }
  .d-fall__e--5{ width:17vw; }
}
/* зум-лайт: тяжёлые слои с blur и drop-shadow гасим, как перья в блоке 1 */
html.zoom-lite .d-fall{ display:none !important; }

/* ---------- 16. ПРОБА ?razbor=1: слом 2→3 «сдув» ----------
   Флаг кладёт html.razbor (razbor.js) до инициализации ScrollTrigger.
   Блок 3 подтянут под последний экран блока 2 — при двойном пине миры
   стоят друг за другом: драйв сверху (z1, правило блока 14) разбирает
   и сдувает razbor.js, позади проступает светлый мир фраз (z0).
   Без флага этих правил не существует, живой путь не тронут. */
/* перекрытие -100svh живёт на ОБЁРТКЕ .ln-hold, не на секции (12.08, слом
   3→4): у статичной обёртки маргин ребёнка схлопывается наружу и раскладка
   та же, но пин слома 3→4 делает обёртку fixed = BFC - схлоп исчезал и
   words уезжал вверх ВНУТРИ обёртки (мир 3 пропадал из просвета ширмы).
   Тот же приём, что у burn2 с .rz-hold */
html.razbor .sec--words{ z-index:0; }
html.razbor .ln-hold{ margin-top:-100vh; margin-top:-100svh; }
/* обёртка держит драйв НАД миром 3 и в пине: fixed от ST может создать
   свой stacking-context, и без явного z-index words всплывал бы по
   DOM-порядку. relative не рвёт схлоп маргина -100svh.
   transform:none НАВСЕГДА: после отпуска пина ST оставляет на обёртке
   инертный translate(0,0), а любой transform делает её containing block
   для fixed — и пин ширмы 1→2 (drive внутри) ехал с потоком (прогон
   10.08). Пин окна ST позиционирует fixed'ом, transform ему не нужен */
html.razbor .rz-hold{ position:relative; z-index:4; transform:none !important; }
/* старый «лист бумаги» этого стыка не рисуем: слом целиком делает razbor.js */
html.razbor .sec--words .open--paper{ display:none; }

/* подложка мира драйва прозрачная ТОЛЬКО когда лист слома реально тронут
   (класс rz-open ставит applyWorld в razbor.js при wt>0). Было rz-live -
   и в live-зоне ДО пина сквозь прозрачный мир светился беж под блоком 2:
   «полоска» с видео Даниила 11.08, диагноз по бейджу ?polosa=1 (ui тёмный,
   rz LIVE, до пина). До заворота подложка тёмная и прикрывает любые щели;
   при завороте за листом и так легитимно виден мир 3. Вторая краска
   (::after) и так лежит ПОД .d-bg (z1) и не видна — гасим, чтобы не
   проступила в опустевшем контейнере */
html.razbor .sec--drive.rz-open .sec__world{ background: transparent; }
html.razbor .sec--drive .sec__world::after{ display:none; }
/* запас мира ниже кромки секции — зеркало правила burn2 (блок 14): в пине
   низ блока 2 прибит по высоте экрана НА МОМЕНТ ЗАМЕРА, а бар мобилы её
   меняет — без запаса при спрятанном баре снизу открывалась щель, в ней
   светился мир 3 (на глаз неотличим от мира 1 — жалоба Даниила 10.08).
   Продлённый контейнер даёт sticky-слоям 160px люфта доехать — кадр липнет
   к реальному экрану весь пин. ⚠️ В headless не воспроизводится (svh=lvh),
   проверка только на устройстве */
html.razbor .sec--drive .sec__world{ bottom:-160px; }

/* дожим ревилов у кромки пина (контракт burn2-near): CSS-анимации
   выключаются, транспортом объектов управляет инлайн-трансформ razbor.js —
   поэтому transform здесь НЕ трогаем (!important убил бы полёт) */
html.razbor .sec--drive.rz-near .reveal{
  /* без animation:none - см. комментарий у burn2-near (морг 12.08) */
  opacity: 1 !important;
  transition: none !important;
}
/* первый экран блока 3 за ширмой виден сразу: его ревил не должен ждать
   скролла (буквы заголовка играют собственный выход).
   L1 ревью 13.08: animation:none убран - последняя мина морга (снятие
   класса пересоздаёт view()-анимацию кадром opacity:0); дожим держат
   сами important-объявления, как во всех остальных near-дожимах */
html.razbor .sec--words.rz-near .sec__head{
  opacity: 1 !important;
  transform: none !important;
}

/* буквы и строки: инлайн-блоки, чтобы работал transform; композитный слой
   буквам даём только у кромки пина, не постоянно */
.rz-l, .rz-line{ display: inline-block; }
html.razbor .sec--words.rz-near .rz-l{ will-change: transform; }

/* перелистывание листа (3D-вариант слома, 10.08; «в бок» - вердикт Даниила):
   слои полотнища получают общий rotateY вокруг ПРАВОЙ кромки - корешок
   справа, левый край уходит в глубину, по ветру разлёта строк; origin и
   backface - здесь, угол и перспектива - razbor.js. Изнанку листа не
   показываем: после 90° проекция уже почти нулевая */
html.razbor .sec--drive .d-bg > *{
  transform-origin: 100% 50%;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}
/* тень сгиба: последний слой полотнища (создаёт razbor.js), летит тем же
   трансформом; цилиндр у корешка (тёмная полоса → блик) + затемнение
   к дальнему (левому) краю. Яркость ведёт JS по прогрессу отгиба */
html.razbor .rz-fold{
  position: sticky; top: 0;
  display: block; height: 100lvh; margin-top: -100lvh;
  pointer-events: none; opacity: 0;
  background:
    linear-gradient(to left,
      rgba(0,0,0,.52) 0%, rgba(0,0,0,.20) 6%,
      rgba(255,255,255,.10) 11%, transparent 19%,
      transparent 52%, rgba(0,0,0,.42) 100%);
}

/* ---------- 17. Блок 3 «Слова, которые держат»: мир фраз ----------
   Собран 10.08 по KAK-SOBRAT-BLOK.md, анатомия блока 1: вход-театр →
   кольцо материалов → человек. Мир светлый и ХОЛОДНЫЙ - это осознанно:
   тёплый белый уже занят блоком 1, а на айфоне светлый мир 3 в щели от
   адресной строки Даниил принял за блок 1 (жалоба 10.08). Фактура своя:
   белая паста и пастельные буквы, дневной свет скользит по рельефу.
   Правила мира соблюдены: слои сэндвича ровно 100lvh и двигаются все
   вместе; overflow на контейнере НЕТ (Safari трактует clip как hidden и
   убивает sticky - урок 09.08), масштаб живёт на вложенной картинке;
   теней у плашки входа нет. Артефакта мира нет: без запроса Даниила не
   делаем (договорённость 09.08). ------------------------------------ */
.sec--words{ padding: 0; }
.sec--words .k-inner{ display:block; }

/* полоса слома «лист бумаги» лежит НАД сэндвичем: на живом пути (без
   ?razbor=1) в ней ещё краска блока 2, и фон не должен её закрашивать.
   Под флагом слома .open--paper скрыт целиком (раздел 16) */
.sec--words .open{ z-index:2; }

/* --- фон блока: тот же sticky-сэндвич, что у блоков 1-2 --- */
.w-bg{ position:absolute; inset:0; z-index:1; }
/* ЗАПАС СВЕРХУ - только под флагом слома. Там блок 3 подтянут на -100svh,
   и при спрятанном баре Safari экран вырастает до lvh: сверху открылась бы
   полоса без мира (дефект блока 2, лечили 09.08). На живом пути запаса
   быть НЕ должно - секция блок 2 не перекрывает, и слой, вылезший вверх,
   закрасил бы его хвост */
html.razbor .sec--words .w-bg{ inset:-26lvh 0 0 0; }
.w-bg__pic{
  position:sticky; top:0;
  display:block; height:100lvh; overflow:hidden;
  background: var(--bg);
}
.w-bg__img{ display:block; width:100%; height:100%; object-fit:cover; }
@media (prefers-reduced-motion: no-preference){
  .w-bg__img{ animation: wbDrift 42s ease-in-out infinite alternate; }
  @keyframes wbDrift{
    from{ transform: scale(1.06) translate3d(0,-0.5%,0); }
    to  { transform: scale(1.14) translate3d(0,0.8%,0); }
  }
}
/* живая петля: как у блока 2, дрейф собственный (--kbv-y из app.js прибит
   к блоку 1). Запас 16lvh разъезжается медленным ходом - одна анимация
   вместо второго scroll-linked слоя, на кромке пина ничего не дёргается */
.w-bg__live{
  position:sticky; top:0;
  display:block; height:100lvh; margin-top:-100lvh;
  overflow:hidden;
}
.w-bg__vid{
  display:block; width:100%; height:116lvh;
  object-fit:cover;
  filter: brightness(1.02) saturate(.94);   /* тише фильтром, не альфой */
  opacity:0; transition: opacity 1.4s ease;
}
.w-bg__vid.is-live{ opacity:1; }   /* НЕ приглушать непрозрачностью: под
   видео лежит постер, и на разнице альфы проступает двойной кадр
   (поймано Даниилом 09.08) */
@media (prefers-reduced-motion: no-preference){
  .w-bg__vid{ animation: wbVidDrift 46s ease-in-out infinite alternate; }
  @keyframes wbVidDrift{
    from{ transform: translate3d(0,0,0); }
    to  { transform: translate3d(0,-14lvh,0); }
  }
}
/* ДЕНЬ ИЗ ОКНА: холодное световое поле сверху-слева медленно ходит по
   рельефу - в светлом мире роль зарева блока 2 играет мягкий свет, а не
   жар. Тёплая нота только внутри пятна, чтобы белое не стало синим */
.w-bg__light{
  position:sticky; top:0;
  display:block; height:100lvh; margin-top:-100lvh;
  pointer-events:none;
  background:
    radial-gradient(86% 58% at 22% 16%, rgba(255,255,255,.72), transparent 64%),
    radial-gradient(52% 40% at 78% 82%, rgba(226,70,95,.10), transparent 70%);
  mix-blend-mode: soft-light;
}
@media (prefers-reduced-motion: no-preference){
  .w-bg__light{ animation: wLightBreath 19s ease-in-out infinite alternate; }
  @keyframes wLightBreath{
    from{ transform: translate3d(-3%,-2%,0) scale(1);    opacity:.8; }
    to  { transform: translate3d(4%,3%,0)   scale(1.16); opacity:1; }
  }
}
/* вуаль читаемости: в светлом мире она светлая (в тёмном была угольной) */
.w-bg__veil{
  position:sticky; top:0;
  display:block; height:100lvh; margin-top:-100lvh;
  background:
    linear-gradient(to bottom,
      color-mix(in srgb, var(--bg) 52%, transparent) 0%,
      color-mix(in srgb, var(--bg) 20%, transparent) 26%,
      color-mix(in srgb, var(--bg) 22%, transparent) 66%,
      color-mix(in srgb, var(--bg) 56%, transparent) 100%),
    radial-gradient(116% 76% at 50% 44%, transparent 38%, color-mix(in srgb, var(--bg) 34%, transparent) 100%);
}
/* зум-лайт: гасим то же, что в блоках 1-2 - видео и blend-слой */
html.zoom-lite .w-bg__vid,
html.zoom-lite .w-bg__light{ display:none !important; }
html.zoom-lite .w-bg__img{ animation:none; }

/* --- вход-театр --- */
/* первый экран начинается под полосой слома: на живом пути в ней ещё
   лежит тёмная краска блока 2, текст в неё заезжать не должен */
.w-hero{ padding-top: calc(var(--open-h) + clamp(10px, 2.5vh, 32px)); }
/* заголовок в две строки, как задумано разметкой: ширина блока 1 (12ch)
   роняет «которые держат» на третью строку. Кегль подогнан ЗАМЕРОМ
   (жалоба Даниила 10.08 «перенесена фраза»): «которые держат» в Prata =
   8.4em ширины, контейнер = W − 2·pad (оба во vw) → максимум ~10.6vw
   на любой ширине, 10.2 с запасом на рендер; min 2.1rem держит две
   строки вплоть до 320px */
.w-hero .sec__title{ max-width:none; font-size: clamp(2rem, 10.2vw, 5rem); }

/* заголовок стоит над плоскостью холодной тенью с розовой кромкой -
   экструзия блока 1 золотая, здесь золоту взяться неоткуда */
.w-hero3d .sec__title{
  text-shadow:
    1px 1px 0 rgba(226,70,95,.20),
    2px 2px 0 rgba(226,70,95,.13),
    0 12px 30px rgba(40,38,46,.20);
}
.w-hero3d .opening{ color: color-mix(in srgb, var(--ink) 86%, transparent); }

/* --- человек --- */
/* ореол за кружком: в тёплом мире блока 1 он кремовый, здесь холодный
   дневной - иначе жёлтое пятно на белой пасте читается как загрязнение */
.sec--words .k-round::before{
  background: radial-gradient(50% 50% at 50% 50%,
    rgba(255,255,255,.9), rgba(238,240,244,.42) 58%, transparent 76%);
}
/* пузыри отзыва: у блока 1 подложка задана своим токеном, в светлом мире
   фраз держим её чуть плотнее - под ней живая фактура */
.sec--words .k-chat{ --k-bubble-bg: color-mix(in srgb, var(--bg-2) 92%, transparent); }

/* WebGL-заворот листа (razbor-gl.js): канвас - пятый слой сэндвича, живёт
   тем же sticky-кадром, что остальные. Вне фазы невидим (лейаут стабилен,
   компиляция и alloc успевают на подходе); на фазе rz-curl DOM-слои листа
   прячутся visibility (rect'ы и CSS-анимации продолжают жить - из них
   шейдер берёт дрейфы), рисует канвас. Тень плоского флипа не нужна -
   тень заворота считает шейдер */
.rz-gl{
  position: sticky; top: 0;
  display: block; width: 100%; height: 100lvh; margin-top: -100lvh;
  visibility: hidden; pointer-events: none;
}
html.razbor .sec--drive.rz-curl .rz-gl{ visibility: visible; }
html.razbor .sec--drive.rz-curl .d-bg > *:not(.rz-gl){ visibility: hidden; }

/* ---------- 17. Слом 3→4 «ширма листвы» - БОЕВОЙ (дефолт с 12.08, ?liany=0 аварийный) ----------
   Флаг кладёт html.liany (liany.js) до инициализации ScrollTrigger.
   Два акта от прогресса пина: стебли-разведчики ползут с краёв и листва
   смыкается стеной (захват страницы 3), затем стена расходится створками
   (живая ширма) и открывает мир 4. Без флага правил не существует. */
/* перекрытие мира 4 - на ОБЁРТКЕ .vd-hold (та же грабля, что у ln-hold:
   обёртку пина 4→5 ST делает fixed = BFC, схлоп маргина исчезает);
   z-index остаётся на секции */
html.liany .vd-hold{ margin-top:-100vh; margin-top:-100svh; }
/* обёртка по правилам rz-hold: relative не рвёт схлоп маргина, лесенка холдов
   (air5>rz4>ln3>vd2>zl1) держит миры по порядку; transform:none НАВСЕГДА - остаточный translate
   ST делал бы её containing block для fixed (.ln-stage и пин ширмы 2→3) */
html.liany .ln-hold{ position:relative; z-index:3; transform:none !important; }
/* старый листовой занавес мира 4 не рисуем - слом целиком делает liany.js */
html.liany .sec--wild .open--leaf{ display:none; }
/* запас мира ниже кромки секции - зеркало правил burn2/razbor (бар мобилы
   меняет высоту экрана; в headless не воспроизводится, svh=lvh) */
html.liany .sec--wild .sec__world{ bottom:-160px; }
/* дожим ревилов у кромки пина (контракт near burn2/razbor);
   без animation:none - см. комментарий у burn2-near (морг 12.08) */
html.liany .sec--words.ln-near .reveal,
html.liany .sec--wild.ln-near .reveal{
  opacity:1 !important; transform:none !important; transition:none !important;
}
/* страница 3 под сомкнутой стеной погашена: мир 4 за ширмой уже живёт,
   к раскрытию створок шва нет. Класс ставит/снимает liany.js */
html.liany .sec--words.ln-covered{ visibility:hidden; }

/* сцена ширмы: fixed поверх страницы (внутри .ln-hold с transform:none),
   под хедером (z20); включается только в live-зоне слома */
.ln-stage{
  position:fixed; inset:0; z-index:6;
  pointer-events:none; visibility:hidden;
  overflow:hidden;
}
.ln-live .ln-stage{ visibility:visible; }
/* стебли-разведчики: полноэкранный слой ПОД кулисами - растут от кромок
   экрана сразу (пре-фаза до стопа), стены накрывают их и под сомкнутой
   стеной liany.js их гасит (невидимый момент) */
.ln-vines{ position:absolute; inset:0; width:100%; height:100%; }
/* кулиса: 62vw - при смыкании перекрытие в центре ~24vw, шва нет */
.ln-leaf{ position:absolute; top:0; bottom:0; width:62vw; }
.ln-leaf--l{ left:0;  transform:translate3d(-102%,0,0); }
.ln-leaf--r{ right:0; transform:translate3d(102%,0,0); }
/* overflow видимый: листья кромки честно торчат из стены в просвет,
   иначе граница svg режет их полулуниями */
.ln-leaf svg{ width:100%; height:100%; display:block; overflow:visible; }
/* палитра стены: глубокая зелень двумя тонами + листья кромки светлее -
   тёмный занавес читается и на белом мире 3, и на светлой зелени мира 4 */
.ln-wall__back{ fill:#1E3115; }
.ln-wall__front{ fill:#2A4520; }
.ln-wall use{ fill:#35571F; }
.ln-stem{
  fill:none; stroke:#2F4C1E; stroke-width:4px; stroke-linecap:round;
  stroke-dasharray:1 1; stroke-dashoffset:1;
}
.ln-sprout{ opacity:0; transform-box:fill-box; transform-origin:center; }
.ln-sprout use{ fill:#3D6326; }
.ln-sprout use + use{ fill:#4A7A2E; }
.ln-live .ln-leaf{ will-change:transform; }

/* WebGL-стена листвы (liany v2): канвас поверх SVG-кулис; CSS-размер
   прибивает alloc() в px. В GL-режиме SVG-слои спят - они фолбек */
.ln-gl{ position:absolute; left:0; top:0; }
.ln-stage.ln-glmode .ln-leaf,
.ln-stage.ln-glmode .ln-vines{ display:none; }

/* ---------- 17b. МИР 4 «Место силы»: свет после дождя ----------
   Сэндвич фона переиспользует .d-bg целиком (запас 26lvh, sticky-слои,
   петля) - здесь только перекраска света: не зарево снизу, а мягкое
   влажное свечение сверху, как солнце сквозь мокрую листву */
.sec--wild .k-inner{ display:block; }
.sec--wild .d-bg__heat{
  background:
    radial-gradient(78% 40% at 50% -6%, rgba(214,236,178,.34), transparent 68%),
    radial-gradient(46% 30% at 24% -4%, rgba(255,252,222,.20), transparent 70%),
    radial-gradient(60% 44% at 82% 2%, rgba(168,206,132,.16), transparent 72%);
  mix-blend-mode: screen;
}
@media (prefers-reduced-motion: no-preference){
  .sec--wild .d-bg__heat{
    animation-duration: 7.5s;              /* дыхание света медленнее баса */
  }
}
/* рамка мира 4: тон света с каплей свежей кромки */
.sec--wild{ --lead-frame: color-mix(in srgb, var(--accent) 16%, color-mix(in srgb, var(--ink) 20%, transparent)); }
.sec--wild .k-lead{ text-shadow: 0 2px 12px rgba(4,10,3,.7); }
.sec--wild .k-review--sell .k-review__lead{ text-shadow: 0 2px 12px rgba(4,10,3,.7); }


.n-hero3d .sec__title{
  color: var(--ink);
  text-shadow:
    0 1px 0 rgba(200,226,150,.42),
    0 0 26px rgba(120,168,74,.36),
    0 14px 40px rgba(2,8,2,.75);
}
.n-hero3d .opening{
  color: color-mix(in srgb, var(--ink) 84%, transparent);
  /* плашка снята 18.08, и на светлых стеблях подстрока садилась -
     тень уплотнена в два слоя (замер на кадре видео 75%) */
  text-shadow: 0 2px 14px rgba(2,8,2,.88), 0 0 30px rgba(2,8,2,.6);
}
.n-hero3d .stroke{ color: var(--accent); }
/* кнопка мира 4: тело - глубокая зелень, искра-золото сквозная */
.sec--wild .cta-btn{ --cta-bg:#152410; }


/* ---------- 17c. МИР 5 «Кит»: два светила ----------
   Сэндвич фона переиспользует .d-bg целиком (запас 26lvh, sticky-слои,
   петля) - здесь только перекраска света: не зарево снизу, а светила
   самой работы - тёплое золото потали сверху-слева (солнце) и холодное
   серебро снизу-справа (луна), между ними фиолетовое поле космоса */
.sec--deep .k-inner{ display:block; }
.sec--deep .d-bg__heat{
  background:
    radial-gradient(64% 38% at 16% -8%, rgba(216,168,74,.32), transparent 66%),
    radial-gradient(42% 28% at 90% 106%, rgba(196,206,238,.24), transparent 70%),
    radial-gradient(84% 54% at 55% 34%, rgba(108,74,168,.16), transparent 74%);
  mix-blend-mode: screen;
}
@media (prefers-reduced-motion: no-preference){
  .sec--deep .d-bg__heat{
    animation-duration: 9s;                /* космос дышит медленнее всех */
  }
}
/* рамка мира 5: тон света с нитью звёздного золота */
.sec--deep{ --lead-frame: color-mix(in srgb, var(--accent) 16%, color-mix(in srgb, var(--ink) 20%, transparent)); }
.sec--deep .k-lead{ text-shadow: 0 2px 12px rgba(6,3,14,.75); }
.sec--deep .k-review--sell .k-review__lead{ text-shadow: 0 2px 12px rgba(6,3,14,.75); }


.c-hero3d .sec__title{
  color: var(--ink);
  text-shadow:
    0 1px 0 rgba(216,190,120,.38),
    0 0 26px rgba(140,110,220,.4),
    0 14px 40px rgba(3,2,10,.8);
}
.c-hero3d .opening{
  color: color-mix(in srgb, var(--ink) 84%, transparent);
  text-shadow: 0 2px 14px rgba(3,2,10,.75);
}
.c-hero3d .stroke{ color: var(--accent); }
/* свет рампы кольца: кремовый (мир 1) здесь выглядывает из-за
   ГОРИЗОНТАЛЬНОЙ главной карточки грязным пятном - у миров 2/4 его
   прятала вертикальная главная. Мир 5 подсвечивает сцену звёздным
   фиолетом, тише и шире */
.kc--deep .kc__stage::before{
  background: radial-gradient(42% 50% at 50% 48%,
    rgba(154,124,224,.34), rgba(118,90,188,.14) 56%, transparent 76%);
}
/* кнопка мира 5: тело - глубокий фиолет, искра-золото сквозная */
.sec--deep .cta-btn{ --cta-bg:#1B1230; }
/* комета: собрана и СНЯТА вердиктом Даниила 12.08 («без неё всё хорошо»)
   - сниппет целиком в RESHENIYA.md, запись 12.08 «эмоции» */


/* ---------- 17d. МИР 6 «Золотое древо»: закатное золото ----------
   Сэндвич фона переиспользует .d-bg целиком - здесь только перекраска:
   свет - тёплое закатное зарево сверху (солнце потали) + тихий янтарный
   отсвет снизу, между ними глубокая умбра работы */
.sec--warm .k-inner{ display:block; }
.sec--warm .d-bg__heat{
  background:
    radial-gradient(66% 40% at 50% -10%, rgba(233,178,74,.34), transparent 66%),
    radial-gradient(46% 30% at 12% 108%, rgba(196,132,48,.18), transparent 72%),
    radial-gradient(84% 56% at 55% 40%, rgba(122,84,32,.14), transparent 76%);
  mix-blend-mode: screen;
}
@media (prefers-reduced-motion: no-preference){
  .sec--warm .d-bg__heat{
    animation-duration: 8s;                /* золото дышит медленно, тягуче */
  }
}
/* рамка мира 6: тон света с поталью - здесь золото уместно прямо */
.sec--warm{ --lead-frame: color-mix(in srgb, var(--accent) 22%, color-mix(in srgb, var(--ink) 18%, transparent)); }
.sec--warm .k-lead{ text-shadow: 0 2px 12px rgba(10,6,2,.75); }
.sec--warm .k-review--sell .k-review__lead{ text-shadow: 0 2px 12px rgba(10,6,2,.75); }

.g-hero3d .sec__title{
  color: var(--ink);
  text-shadow:
    0 1px 0 rgba(240,200,120,.42),
    0 0 26px rgba(217,164,65,.38),
    0 14px 40px rgba(8,5,2,.8);
}
.g-hero3d .opening{
  color: color-mix(in srgb, var(--ink) 84%, transparent);
  text-shadow: 0 2px 14px rgba(8,5,2,.75);
}
.g-hero3d .stroke{ color: var(--accent); }
/* рампа кольца: тёплое золото, тихое и широкое - кремовый свет мира 1
   на тёмной умбре выглядел бы грязным пятном (грабля кита, 12.08) */
.kc--warm .kc__stage::before{
  background: radial-gradient(42% 50% at 50% 48%,
    rgba(233,178,74,.30), rgba(178,126,44,.12) 56%, transparent 76%);
}
/* кнопка мира 6: тело - глубокая умбра, искра-золото сквозная */
.sec--warm .cta-btn{ --cta-bg:#2A1B0C; }


/* ---------- 19. Слом 4→5 «затопление» - БОЕВОЙ (дефолт с 12.08) ----------
   html.voda кладёт voda.js по умолчанию (ON = !reduced), ?voda=0 -
   аварийный выключатель. Вода поднимается снизу и съедает страницу 4,
   толща под поверхностью темнеет в космос мира 5 */
/* перекрытие мира 5 живёт на ОБЁРТКЕ .zl-hold (13.08, слом 5→6 обернул
   deep): маргин на секции внутри пина = fixed = BFC, схлоп исчезает -
   грабля 12.08. Обёртка в DOM всегда, правило работает и при ?zoloto=0 */
html.voda .zl-hold{ margin-top:-100vh; margin-top:-100svh; }
/* обёртка: transform:none НАВСЕГДА - остаточный translate ST делал бы её
   containing block для fixed (.vd-stage и пины внутри) */
html.voda .vd-hold{ position:relative; z-index:2; transform:none !important; }
/* старая волна-ширма этого стыка не рисуется: слом целиком делает voda.js */
html.voda .sec--deep .open--wave{ display:none; }
/* запас мира ниже кромки - зеркало правил burn2/razbor/liany (бар мобилы) */
html.voda .sec--deep .sec__world{ bottom:-160px; }
/* дожим ревилов у кромки пина (контракт near);
   без animation:none - см. комментарий у burn2-near (морг 12.08:
   граница near-зоны воды проходит по кольцу кита, каждый свайп
   пересоздавал view()-анимации всех .reveal - кадр opacity:0) */
html.voda .sec--wild.vd-near .reveal,
html.voda .sec--deep.vd-near .reveal{
  opacity:1 !important; transform:none !important; transition:none !important;
}
/* страница 4 под водой: на нижней стороне зоны держится погашенной
   (хвост перекрывал бы первый экран мира 5 - урок «полоски») */
html.voda .sec--wild.vd-covered{ visibility:hidden; }

/* сцена воды: fixed поверх страницы (внутри .vd-hold с transform:none),
   под хедером; включается только в live-зоне слома */
.vd-stage{
  position:fixed; inset:0; z-index:6;
  pointer-events:none; visibility:hidden;
  overflow:hidden;
}
.vd-live .vd-stage{ visibility:visible; }
.vd-gl{ position:absolute; left:0; top:0; }
/* фолбек без WebGL: градиентная толща, верх режется клипом-волной из
   тех же сэмплов (voda.js), кромка - светлая пена бордером */
.vd-deep{
  position:absolute; inset:0; display:none;
  background: linear-gradient(to bottom,
    #4A7A6E 0%, #2E5E52 12%, #17394A 38%, #10203A 62%, #140F1D 100%);
  border-top: 3px solid rgba(226,240,228,.85);
}
.vd-stage.vd-fallback .vd-deep{ display:block; }


/* ---------- 21. Слом 5→6 «жидкое золото» - БОЕВОЙ (дефолт с 13.08) ----------
   html.zoloto кладёт zoloto.js по умолчанию (ON = !reduced), ?zoloto=0 -
   аварийный выключатель. Расплавленная поталь поднимается снизу - тягучая,
   гуще воды; звёзды тонут, в толще проступают тёмные прожилки-ветви,
   наверху золото остывает в закат и растворяется в мир 6 к отпуску пина */
html.zoloto .sec--warm{ margin-top:-100vh; margin-top:-100svh; }
/* обёртка вокруг кита: deep уже пинится пином B воды - два ST-пина на
   одном элементе делят pin-spacer (урок rz-hold). z1 - низ лесенки миров
   (air5>rz4>ln3>vd2>zl1), warm остаётся ниже на auto */
html.zoloto .zl-hold{ position:relative; z-index:1; transform:none !important; }
/* фолбек-ширма стыка не рисуется: слом целиком делает zoloto.js */
html.zoloto .sec--warm .open--dawn{ display:none; }
/* запас мира ниже кромки - зеркало правил burn2/razbor/liany/voda */
html.zoloto .sec--warm .sec__world{ bottom:-160px; }
/* дожим ревилов у кромки пина (контракт near); без animation:none (морг
   12.08) и дожим только opacity/transition - transform:none в дожиме
   перебил бы inline-полёты (урок сдува 12.08, здесь их нет - на вырост) */
html.zoloto .sec--deep.zl-near .reveal,
html.zoloto .sec--warm.zl-near .reveal{
  opacity:1 !important; transition:none !important;
}
/* страница 5 под золотом: на нижней стороне зоны держится погашенной
   (хвост перекрывал бы первый экран мира 6 - урок «полоски») */
html.zoloto .sec--deep.zl-covered{ visibility:hidden; }

/* сцена золота: fixed поверх страницы (внутри .zl-hold с transform:none),
   под хедером; включается только в live-зоне слома */
.zl-stage{
  position:fixed; inset:0; z-index:6;
  pointer-events:none; visibility:hidden;
  overflow:hidden;
}
/* M2 ревью 13.08: на время зоны золота канвас частиц уходит ПОД толщу
   (.fx z2 против .zl-hold z1 - звёзды мира 5 светили поверх расплава) */
html.zl-live .fx{ z-index:0; }
.zl-live .zl-stage{ visibility:visible; }
.zl-gl{ position:absolute; left:0; top:0; }
/* фолбек без WebGL: градиентная толща расплавленного золота, ход тем же
   riseT (zoloto.js), кромка - светлая нить потали бордером */
.zl-deep{
  position:absolute; inset:0; display:none;
  background: linear-gradient(to bottom,
    #F0C468 0%, #D9A441 10%, #9A6E24 34%, #4E3413 64%, #1A1108 100%);
  border-top: 3px solid rgba(248,228,170,.9);
}
.zl-stage.zl-fallback .zl-deep{ display:block; }

/* ---------- 19. ХЕД САЙТА (13.08, порт Editorial Collage Hero 21st.dev) ----------
   Один НЕполный экран (~88svh): из-под хеда выглядывает вход мира 1 -
   приглашение скроллить. Палитра = мир 1 (шапка выше s-air живёт в мире 0,
   стык бесшовный). Слева h1+подстрока+CTA+строка доверия, справа коллаж
   двух работ (большая вертикальная + квадратная внахлёст, паспарту цвета
   --bg-2 как у карточек). Хед НЕ .sec - вне rail/fx/геометрии миров. */
.hed{
  --bg:#EDE8DF; --bg-2:#F7F3EA; --ink:#23201C; --ink-soft:#6B6055; --accent:#B4862F;
  /* z6: фон мира 1 продолжен под хед (.sec--air .k-bg top:-120svh), а
     сам мир в живом режиме стоит в лесенке z5 (burn2) - контент хеда
     обязан быть выше расширенного фона. Своего фона у хеда НЕТ - стыка
     с миром не существует (вердикт 14.08) */
  position:relative; z-index:6;
  min-height: 88svh;
  display:flex; align-items:center;
  background: transparent;
  padding: calc(64px + 4vh) 0 6vh;           /* верх - зазор под fixed-шапку */
}
.hed__inner{
  width:100%; max-width:1480px; margin:0 auto;
  padding: 0 clamp(24px, 6.5vw, 126px);
  display:grid; grid-template-columns: 1.08fr .92fr;
  gap: clamp(40px, 5vw, 88px); align-items:center;
}
.hed__title{
  margin:0;
  font-family:'Prata', 'PT Serif', serif; font-weight:400;
  font-size: clamp(2.15rem, 3vw, 3.55rem); line-height:1.16;
  letter-spacing:-.01em; color:var(--ink); text-wrap:balance;
}
.hed__sub{
  margin: clamp(16px, 2.2vh, 26px) 0 0;
  font-family:'PT Serif', serif;
  font-size: clamp(1.02rem, 1.35vw, 1.32rem); line-height:1.55;
  color: var(--ink-soft); max-width: 46ch;
}
.hed__cta{
  margin-top: clamp(22px, 3.2vh, 36px);
  display:flex; flex-wrap:wrap; align-items:center; gap: 12px 26px;
}
.hed__more{
  position:relative;
  font-family:'PT Serif', serif; font-style:italic;
  font-size: clamp(1rem, 1.15vw, 1.12rem); color: var(--ink);
  text-decoration: underline; text-underline-offset: .28em;
  text-decoration-color: color-mix(in srgb, var(--accent) 55%, transparent);
  transition: color .18s ease, text-decoration-color .18s ease;
}
.hed__more::after{ content:""; position:absolute; inset:-10px -8px; }
.hed__more:hover{ color: var(--accent); text-decoration-color: var(--accent); }
/* --- коллаж: большая вертикальная + квадратная внахлёст снизу-справа --- */
.hed__art{ position:relative; justify-self:end; width:min(100%, 470px); }
.hed__art figure{ margin:0; }
.hed__art img{ display:block; width:100%; height:auto; }
.hed__art-main{
  width:78%;
  border-radius: clamp(14px, 1.6vw, 22px); overflow:hidden;
  box-shadow: 0 18px 34px -20px rgba(64,52,34,.5), 0 60px 110px -48px rgba(64,52,34,.42);
}
.hed__art-over{
  position:absolute; right:0; bottom:-9%; width:52%;
  border-radius: clamp(12px, 1.3vw, 18px); overflow:hidden;
  border: 6px solid var(--bg-2);            /* паспарту, как зазор в референсе */
  box-shadow: 0 14px 28px -16px rgba(64,52,34,.55), 0 42px 80px -40px rgba(64,52,34,.4);
}
/* мобильная колонка: копия сверху, коллаж ниже; хед короче экрана,
   вход мира 1 виден тем более */
@media (max-width: 767px){
  .hed{ min-height:0; padding: calc(64px + 3vh) 0 12vh; }
  .hed__inner{ grid-template-columns: 1fr; gap: 40px; }
  .hed__art{ justify-self:center; width:min(86%, 400px); padding-bottom:9vw; }
}

/* ---------- 20. А3 ревью 13.08: десктопная ступень - элементные правила ----------
   Стоит В КОНЦЕ файла сознательно: правила той же специфичности ниже по
   файлу забирают каскад (первая попытка ступени у :root проиграла базовым
   .k-lead и хиро-клампам). Токены ступени - в @media у :root (раздел 1).
   Заголовки миров сидят на СВОИХ клампах (.k-hero), токен --t-title их
   не касается - поднимаем адресно. Мир 3 исключён: .w-hero - предел
   переноса «которые держат», собирается по буквам (razbor). */
@media (min-width: 1440px){
  .k-hero:not(.w-hero) .sec__title{ font-size: clamp(6rem, 5.5vw, 6.6rem); }
  /* лид блока: мера 30ch давала 28-33 знака в строке (HIGH ревью) */
  .k-lead{ font-size: 1.7rem; max-width: 44ch; }
  /* продающие фразы: миры 2-6 подрастают; мир 1 (.k-bridge--sell) был
     тише остальных (25.6px/20ch против 30.4/24ch, MED #16) - уравнен */
  .k-review--sell .k-review__lead{ font-size: 2.05rem; max-width: 26ch; }
  .k-bridge--sell{ font-size: 2.05rem; max-width: 26ch; }
}

/* --- А4 ревью 13.08: продающие экраны на десктопе - двухколонник.
   Было: колонка 384px слева + ~540px пустого хвоста во всех 6 мирах
   (занято ~15% кадра 1920). Стало: переписка справа, крючок+строка+CTA
   слева, вертикальное центрирование экрана. Миры 2-3 переписки не имеют
   (отзывов нет - факт контента) - их группа центрируется как цельный
   блок, отсутствие чата читается замыслом, не дырой. Мобила не тронута */
@media (min-width: 1440px){
  .k-review:has(.k-chat){
    display:grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, .9fr);
    column-gap: clamp(64px, 7vw, 140px);
    align-content:center; align-items:center;
  }
  .k-review:has(.k-chat) .k-chat{
    grid-column:2; grid-row:1 / span 4;
    justify-self:start; align-self:center;
  }
  .k-review:has(.k-chat) .k-review__lead,
  .k-review:has(.k-chat) .k-bridge--sell{ grid-column:1; align-self:end; }
  .k-review:has(.k-chat) > .k-lead{ grid-column:1; margin-bottom: clamp(14px, 2.4vh, 28px); }
  .k-review:has(.k-chat) .k-cta,
  .k-review:has(.k-chat) .k-bridge:not(.k-bridge--sell){ grid-column:1; align-self:start; }
  /* Миры без переписки (2-3). Было: цельный блок по центру кадра - на
     широком экране висел посреди пустоты (вердикт Даниила 18.08: «не
     красиво расположен, должен быть левее и крупнее»). Стало: прижат к
     левому краю колонки и укрупнён - экран читается как разворот, а не
     как одинокий абзац. */
  .k-review--sell:not(:has(.k-chat)){
    justify-content:center;
    max-width: 30ch; margin-inline:0;
  }
  .k-review--sell:not(:has(.k-chat)) .k-review__lead{
    font-size: 2.7rem; max-width: 15ch; line-height: 1.16;
  }
  .k-review--sell:not(:has(.k-chat)) .k-lead{
    font-size: 1.45rem; max-width: 30ch;
  }
}

/* --- А7 ревью 13.08: рельса-навигация возвращается ТОЛЬКО на десктопе.
   Снята Даниилом 06.08 («фигня справа») - на мобиле остаётся снятой.
   Оба ревью: 27000px скролла без навигации и ощущения длины. Тихий вид:
   чёрточки без подписей, подпись - по hover/фокусу; активный мир -
   акцент + длинная черта (механика is-active в app.js живая) */
@media (min-width: 1440px){
  .rail{ display:block; }
  .rail__item span{ display:none; }
  .rail__item.is-active span{ display:none; }
  .rail__item:hover span,
  .rail__item:focus-visible span,
  .rail__item.is-active:hover span{ display:block; }
}

/* --- А8 ревью 13.08: единый видимый фокус с клавиатуры.
   Свой :focus-visible был ровно у одного элемента (.kc__stage) - у всех
   остальных дефолтное кольцо браузера, у инпутов outline:none.
   :where держит специфичность нулевой - адресные стили не перебивается */
:where(a, button, [tabindex]):focus-visible{
  outline: 2px solid var(--ui-accent, var(--accent, #B4862F));
  outline-offset: 3px;
  border-radius: 4px;
}
.fld input:focus-visible{
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-bottom-color: var(--accent);
}

/* --- А8: стрелки кольца на десктопе - к краям вьюпорта (стояли поверх
   карточек: кольцо шире сцены) + честный hover (рост и акцентная кромка;
   было 78%→100% подложки - на фото не читалось) */
@media (min-width: 1440px){
  .kc__arr--l{ left: max(calc(-1 * ((100vw - 100%) / 2) + clamp(14px, 1.8vw, 40px)), 14px); }
  .kc__arr--r{ right: max(calc(-1 * ((100vw - 100%) / 2) + clamp(14px, 1.8vw, 40px)), 14px); left:auto; }
  .kc__arr:hover{
    transform: translateY(-50%) scale(1.1);
    background: var(--bg-2);
    border-color: var(--accent);
  }
  .kc__arr:active{ transform: translateY(-50%) scale(.96); }
  /* боковые карточки: лёгкий отклик на курсор (transform занят JS-кольцом -
     подсветка фильтром, не движением) */
  .kc__card{ transition: filter .2s ease; }
  .kc__card:hover{ filter: brightness(1.07) saturate(1.04); }
}

/* --- стык хед→мир 1 v2 (14.08, вердикт Даниила «полоску видно, сделать
   мягко»): стыка больше НЕ СУЩЕСТВУЕТ - у хеда нет своего фона, фон
   мира 1 продолжается под него до верха страницы. Верх кадра bg-air -
   светлое «окно» - становится задником хеда (эту роль он играл, когда
   мир 1 был первым экраном). Кадр-липучка прибит к вьюпорту с загрузки:
   расширенный вверх containing block переводит sticky в «уже прилип» */
.sec--air .k-bg{ top:-120svh; }

/* На телефоне текстовые группы стоят РОВНО (Даниил 18.08: «наклон типа 3d
   читается как фигня»). Разворот сцены задумывался под курсор-tilt, а он
   и так живёт только с 768px - на узком экране оставался мёртвый перекос,
   который лишь ломал строку. Наклон карусели работ не трогаем: там объём
   несёт смысл кольца */
@media (max-width: 719px){
  .k-hero3d{ transform:none; transform-style:flat; }
  .k-hero3d .sec__title,
  .k-hero3d .stroke{ transform:none; }
  .k-chat{ transform:none; }
}
