/* =====================================================================
   PLEXI FORM — «Тёмный полированный титан» (с 2.4). Токены и правила: docs/research-titanium.md;
   движение: docs/research-ux-motion.md
   ===================================================================== */
/* ---------- шрифты (2.12, docs/research-typography.md): свои копии в vendor/fonts (OFL), без Google Fonts ----------
   Cormorant Garamond — антиква заголовков, цен и характеристик (вариативная 300–400 + курсив 400);
   Ysabeau Office — гротеск того же автора (К. Тальманн) для текста, подписей прописными и цифр (вариативный 400–600).
   Три файла «ru1»: каждый — свой набор глифов (ASCII, Latin-1, вся основная кириллица, ₽ № — « » − × и пр., список в
   docs), поэтому кириллица, пунктуация и ₽ приходят одним файлом. Версия шрифта и набора — в имени: vendor/ кэшируется
   на год. Все — swap (текст виден сразу; основные файлы предзагружаются в index.html). Запасные шрифты подогнаны по
   ширине и высоте строки (size-adjust) — при подмене вёрстка не прыгает */
@font-face { font-family: 'Cormorant Garamond'; font-style: normal; font-weight: 300 400; font-display: swap;
  src: url("../vendor/fonts/cormorant-garamond-v21-ru1.woff2") format('woff2'); }
@font-face { font-family: 'Cormorant Garamond'; font-style: italic; font-weight: 400; font-display: swap;
  src: url("../vendor/fonts/cormorant-garamond-italic-v21-ru1.woff2") format('woff2'); }
@font-face { font-family: 'Ysabeau Office'; font-style: normal; font-weight: 400 600; font-display: swap;
  src: url("../vendor/fonts/ysabeau-office-v4-ru1.woff2") format('woff2'); }
@font-face { font-family: 'Cormorant Fallback'; src: local('Times New Roman'), local('Times'), local('Liberation Serif');
  size-adjust: 94%; ascent-override: 98%; descent-override: 31%; line-gap-override: 0%; }
@font-face { font-family: 'Ysabeau Fallback'; src: local('Arial'), local('Helvetica'), local('Liberation Sans'), local('Roboto');
  size-adjust: 92%; ascent-override: 114%; descent-override: 32%; line-gap-override: 0%; }
/* заголовок первого экрана (2.16b, docs/research-typography.md §5д): тонкий геометрический гротеск Jost 300 — свободный
   аналог Futura (Messika, Jacquemus, Louis Vuitton). Каждое начертание — статичный файл с набором «ru1».
   Два запасных варианта лежат рядом и не грузятся, пока не выбраны: Sofia Sans Semi Condensed 300 (спокойный
   неогротеск) и Tenor Sans 400 (гуманист в духе Optima). Как переключить — у правила .hero-title */
@font-face { font-family: 'Jost'; font-style: normal; font-weight: 300; font-display: swap;
  src: url("../vendor/fonts/jost-v20-w300-ru1.woff2") format('woff2'); }
@font-face { font-family: 'Jost Fallback'; src: local('Arial'), local('Helvetica'), local('Liberation Sans'), local('Roboto');
  size-adjust: 94%; ascent-override: 113%; descent-override: 40%; line-gap-override: 0%; }
@font-face { font-family: 'Sofia Sans Semi Condensed'; font-style: normal; font-weight: 300; font-display: swap;
  src: url("../vendor/fonts/sofia-sans-semi-condensed-v8-w300-ru1.woff2") format('woff2'); }
@font-face { font-family: 'Sofia Fallback'; src: local('Arial'), local('Helvetica'), local('Liberation Sans'), local('Roboto');
  size-adjust: 89%; ascent-override: 101%; descent-override: 34%; line-gap-override: 0%; }
@font-face { font-family: 'Tenor Sans'; font-style: normal; font-weight: 400; font-display: swap;
  src: url("../vendor/fonts/tenor-sans-v21-w400-ru1.woff2") format('woff2'); }
@font-face { font-family: 'Tenor Fallback'; src: local('Arial'), local('Helvetica'), local('Liberation Sans'), local('Roboto');
  size-adjust: 110%; ascent-override: 83%; descent-override: 23%; line-gap-override: 0%; }

:root {
  --bg: #0b0c0e;
  --bg-2: #111215;
  --surface: #16181b;
  --surface-2: #1d1f23;
  --glass: rgba(232, 228, 220, .035);
  --glass-line: rgba(232, 228, 220, .1);
  --text: #e8e5df;
  --text-2: #a3a19c;
  --muted: #8b8c90;  /* мелкие подписи 11–13 px: 5,4 : 1 на #121519, ≥ 4,8 : 1 на панели (до 2.12 — #6e6f73, 3,6 : 1) */
  --line: rgba(232, 228, 220, .08);
  --line-2: rgba(232, 228, 220, .16);
  --ti-hi: #c9c5bd;
  --ti-mid: #6f6e6b;
  --ti-lo: #2b2c2f;
  --cobalt: #4f6fe8;
  --bronze: #b98a55;
  --plum: #8b70d6;
  --anodized: linear-gradient(90deg, var(--bronze), var(--plum), var(--cobalt));
  --ice: #9fb4f5;  /* фокус и выделение — приглушённый кобальт */
  --danger: #e07a6e;

  --serif: 'Cormorant Garamond', 'Cormorant Fallback', 'Times New Roman', serif;
  --sans: 'Ysabeau Office', 'Ysabeau Fallback', system-ui, -apple-system, 'Segoe UI', sans-serif;
  /* «цифры и характеристики»: прежний моноширинный шрифт заменён табличными цифрами текстового (.mono) */
  --mono: var(--sans);
  /* подписи прописными (eyebrow, меню, кнопки, пункты панели): вес 500 и разрядка .1em — тихо, «без усилия», как у
     модных изданий и домов (The Cut, SSENSE, Cartier: капс 400–500, разрядка .05–.12em); кегли ≤ 10 px — 600 (оптическая
     компенсация). До 2.12 было 500 / .22em — разрядку можно вернуть здесь одной строкой */
  --caps-weight: 500;
  --caps-track: .1em;

  --ease-expo: cubic-bezier(.16, 1, .3, 1);
  --ease-quart: cubic-bezier(.25, 1, .5, 1);
  --ease-io: cubic-bezier(.65, 0, .35, 1);
  --d-hover: 200ms;
  --d-ui: 320ms;
  --d-reveal: 900ms;

  --pad: clamp(20px, 5vw, 88px);
  --section: clamp(96px, 14vw, 220px);
  --nav-h: 76px;
}

* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
/* 2.22.1 (QA): горизонтальный жест по строке цвета, заголовку раздела или подписи не уходит в «назад» браузера
   (Chrome/Edge: жест истории по касанию и трекпаду уводил со страницы) */
html, body { overscroll-behavior-x: none; }
html.lenis, html.lenis body { height: auto; }
.lenis.lenis-smooth { scroll-behavior: auto !important; }
.lenis.lenis-stopped { overflow: hidden; }
body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: 400 16px/1.6 var(--sans);
  font-kerning: normal; font-variant-numeric: lining-nums proportional-nums; font-synthesis: none; /* без поддельных жирного и курсива */
  -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}
body.is-loading { overflow: hidden; }
img { display: block; max-width: 100%; }
button, input, textarea { font: inherit; color: inherit; }
a { color: inherit; }
::selection { background: var(--ice); color: #000; }
:focus-visible { outline: 1px solid var(--ice); outline-offset: 3px; }

/* заголовки — антиква обычного веса 400 (волосные 300 на 80+ px «тают» и выглядят шаблоном), курсив — настоящий 400
   и только на одном слове; интерлиньяж 1 — кириллическим «й», «ё» и выносным «д», «у», «щ» не тесно */
.display { font-family: var(--serif); font-weight: 400; letter-spacing: -.02em; line-height: 1; font-variant-numeric: lining-nums; text-wrap: balance; }
.display em, .h2 em { font-style: italic; font-weight: 400; }
/* цифры и характеристики: табличные цифры высоты прописных — значения не «прыгают» при движении ползунка */
.mono { font-family: var(--mono); font-weight: 500; letter-spacing: .02em; font-variant-numeric: lining-nums tabular-nums; }
/* подпись прописными (владельцу нравится «ВАШЕ КОЛЬЦО» → «Персональное кольцо» в панели тем же стилем): гротеск 600
   (прописные Ysabeau ниже, чем у прежнего Manrope, поэтому 11,5 px вместо 11), разрядка --caps-track */
.eyebrow {
  margin: 0; font: var(--caps-weight) 11.5px/1.4 var(--sans); letter-spacing: var(--caps-track); text-transform: uppercase; color: var(--text-2);
}
/* шкала заголовков: H1 hero ≤ 96 px → H2 разделов 30–64 px → H3 шагов 24–38 px; соседние уровни различаются ≥ 1,25×
   на всех ширинах от 320 px (390: 48 / 30 / 24; 1440: 86 / 57 / 38; 1920: 96 / 64 / 38) */
.h2 { font-size: clamp(30px, 20px + 2.6vw, 64px); margin: 0; }

/* ---------- зерно ---------- */
.grain {
  position: fixed; inset: -50%; z-index: 90; pointer-events: none; opacity: .045;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  animation: grain 1.2s steps(6) infinite;
}
@keyframes grain {
  0% { transform: translate(0, 0); } 20% { transform: translate(-3%, 2%); } 40% { transform: translate(2%, -3%); }
  60% { transform: translate(-2%, -1%); } 80% { transform: translate(3%, 3%); } 100% { transform: translate(0, 0); }
}

/* ---------- экран загрузки ---------- */
.loader {
  position: fixed; inset: 0; z-index: 100; background: var(--bg);
  display: grid; place-items: center; align-content: center; gap: 28px;
  transition: opacity 900ms var(--ease-io), visibility 0s 900ms;
}
.loader.done { opacity: 0; visibility: hidden; pointer-events: none; }   /* пока гаснет — клики уже проходят к странице */
.loader-mark { font: 400 clamp(28px, 4vw, 44px)/1 var(--serif); letter-spacing: .42em; padding-left: .42em; }
.loader-mark span {
  display: inline-block; opacity: 0; transform: translateY(40%); filter: blur(6px);
  animation: letter 1.1s var(--ease-expo) forwards;
}
@keyframes letter { to { opacity: 1; transform: none; filter: none; } }
.loader-line { width: min(240px, 50vw); height: 1px; background: var(--line); overflow: hidden; }
.loader-line span { display: block; height: 100%; width: 100%; background: var(--text); transform-origin: left; transform: scaleX(0); transition: transform 400ms var(--ease-quart); }
.loader-count { position: absolute; right: var(--pad); bottom: 32px; font-size: 12px; letter-spacing: .14em; color: var(--muted); }

/* ---------- навигация ---------- */
.nav {
  position: fixed; inset: 0 0 auto; z-index: 50; height: var(--nav-h);
  display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; padding: 0 var(--pad);
  border-bottom: 1px solid transparent;
  transition: background var(--d-ui) var(--ease-quart), border-color var(--d-ui), transform 600ms var(--ease-expo);
}
.nav.is-scrolled {
  background: rgba(2, 2, 2, .55); border-color: var(--line);
  backdrop-filter: blur(18px) saturate(140%); -webkit-backdrop-filter: blur(18px) saturate(140%);
}
.nav.is-hidden { transform: translateY(-100%); }
.nav.is-hidden:focus-within { transform: none; }   /* фокус с клавиатуры в спрятанной шапке — шапка выезжает */
.nav-side { display: flex; gap: 36px; }
.nav-right { justify-content: flex-end; }
.nav a { text-decoration: none; }
.nav-side a {
  font: var(--caps-weight) 11.5px/1 var(--sans); letter-spacing: var(--caps-track); text-transform: uppercase; color: var(--text-2);
  position: relative; padding: 8px 0; transition: color var(--d-hover);
}
.nav-side a::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: 2px; height: 1px; background: currentColor;
  transform: scaleX(0); transform-origin: right; transition: transform 500ms var(--ease-expo);
}
.nav-side a:hover { color: var(--text); }
.nav-side a:hover::after { transform: scaleX(1); transform-origin: left; }
.nav-logo { font: 400 21px/1 var(--serif); letter-spacing: .38em; padding-left: .38em; white-space: nowrap; }

/* ---------- кнопки ---------- */
.btn {
  position: relative; overflow: hidden; isolation: isolate;
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 52px; padding: 0 32px; border-radius: 999px; border: 1px solid var(--text);
  font: var(--caps-weight) 12px/1 var(--sans); letter-spacing: var(--caps-track); text-transform: uppercase; text-decoration: none;
  cursor: pointer; background: transparent; color: var(--text);
  transition: color var(--d-ui) var(--ease-quart), border-color var(--d-ui), opacity var(--d-ui);
}
.btn::before {
  content: ''; position: absolute; inset: -1px; z-index: -1; border-radius: inherit;
  transform: translateY(101%); transition: transform 500ms var(--ease-expo);
}
.btn span { position: relative; }
.btn-light { background: var(--text); color: #050505; }
.btn-light::before { background: #fff; }
.btn-ghost { border-color: var(--line); }
.btn-ghost::before { background: rgba(255, 255, 255, .08); }
.btn:not(:disabled):hover::before { transform: translateY(0); }
.btn:disabled { opacity: .35; cursor: wait; }
.btn-block { width: 100%; }
.btn-text {
  background: none; border: 0; padding: 6px 0; cursor: pointer; color: var(--text-2);
  font: var(--caps-weight) 12px/1 var(--sans); letter-spacing: var(--caps-track); text-transform: uppercase; text-decoration: none;
  background-image: linear-gradient(currentColor, currentColor); background-size: 100% 1px; background-repeat: no-repeat; background-position: 0 100%;
  transition: color var(--d-hover), background-size 500ms var(--ease-expo);
}
.btn-text:hover { color: var(--text); }
.btn-text:disabled { opacity: .4; cursor: wait; }
.magnetic { will-change: transform; }

/* ---------- hero «Светлое поле» (docs/research-hero.md) ----------
   Студийный световой стол: кольцо стоит на полу, свет слева сверху, текст — в самой светлой зоне.
   При скролле пол уходит в тень и без шва становится титаном сайта #121519.
   «Сцена» (.hero-stage) имеет пропорции плиты и покрывает экран как object-fit: cover; кольцо стоит
   в % сцены — при любом окне оно приклеено к своему месту на полу. Раскладка выбирается по соотношению
   сторон окна: W (≥ 7/5) — плита 16×9, S (≥ 1) — 4×3, P (≥ 0.65) — 3×4, T — 9×16. */
.hero { --ink: #16171a; --ink-2: #3e4147; --ink-3: #5c5f66; --p: 0; --fl: max(24svh, 160px);
  --ar: 16 / 9; --ax: 58%; --ay: 62%; --rl: 44.45%; --rt: 27.15%; --rw: 42.96%; /* кольцо — вырез x 226…946, y 186…786 исходника */
  position: relative; min-height: max(100svh, 600px); display: grid; align-items: center; overflow: hidden; background: #121519; color: var(--ink); }
.hero-media { position: absolute; inset: 0; margin: 0; overflow: hidden; container-type: size; will-change: transform; transform: translate3d(0, calc(var(--p) * 30svh), 0); }
.hero-stage { position: absolute; left: var(--ax); top: var(--ay); aspect-ratio: var(--ar); transform-origin: 62% 72%;
  width: max(100vw, calc(100svh * var(--ar))); width: max(100cqw, calc(100cqh * var(--ar))); translate: calc(var(--ax) * -1) calc(var(--ay) * -1); }
/* точка контакта кольца с полом в вырезе — (40 %, 74 %): масштаб идёт вокруг неё, кольцо не «отрывается» от пола */
.hero-plate, .hero-plate img, .hero-ring img { display: block; width: 100%; height: 100%; max-width: none; max-height: none; object-fit: cover; transform-origin: 40% 74%; }
.hero-ring { position: absolute; left: var(--rl); top: var(--rt); width: var(--rw); aspect-ratio: 6 / 5; transform-origin: 40% 74%; scale: calc(1 - var(--p) * .04); will-change: transform; }
.hero-glint { position: absolute; inset: 0; overflow: hidden; pointer-events: none; mix-blend-mode: screen; opacity: .5;
  -webkit-mask: url("../assets/hero/hero-ring-mask.webp") 0 0 / 100% 100% no-repeat; mask: url("../assets/hero/hero-ring-mask.webp") 0 0 / 100% 100% no-repeat; }
.hero-glint i { position: absolute; top: -10%; bottom: -10%; left: 0; width: 45%; translate: -120% 0; background: linear-gradient(100deg, transparent 20%, rgba(255, 255, 255, .8) 50%, transparent 80%); }
.hero-fade { position: absolute; left: 0; right: 0; top: calc(100% - var(--fl)); bottom: -2px; z-index: 1; pointer-events: none;
  background: linear-gradient(180deg, rgba(18,21,25,0), rgba(18,21,25,.05) 14%, rgba(18,21,25,.17) 27%, rgba(18,21,25,.35) 39%, rgba(18,21,25,.55) 50%,
    rgba(18,21,25,.74) 61%, rgba(18,21,25,.9) 73%, rgba(18,21,25,.98) 85%, #121519 94%) 0 0 / 100% var(--fl) no-repeat, linear-gradient(#121519, #121519) 0 var(--fl) / 100% 100% no-repeat; }
.hero-tone { position: absolute; left: 0; right: 0; top: 0; height: 70%; pointer-events: none; }
.hero + .collection { margin-top: -2px; } /* композитный слой плиты при дробном масштабе просвечивает 1px-линией на стыке */
.hero-copy { position: relative; z-index: 2; width: min(46vw, 780px); padding: calc(var(--nav-h) + 3svh) 0 16svh var(--pad); translate: 0 calc(var(--p) * -9svh); opacity: calc(1 - var(--p) * 2.2); }
.hero .eyebrow { color: var(--ink-3); display: flex; align-items: center; gap: 14px; }
.hero .eyebrow::before { content: ''; width: 28px; height: 1px; background: currentColor; opacity: .5; }
/* заголовок — прямой тонкий гротеск без курсива (2.16b) и спокойный блок из двух строк одной ширины (2.16c,
   docs/research-typography.md §5е): «Свет, который / можно носить» — строки раскладывает js/app.js, каждая выключена
   по ширине блока (text-align-last: justify), блок шириной в самую длинную строку, «С» чуть висит за край колонки.
   ПЕРЕКЛЮЧЕНИЕ шрифта — переменные ниже (и строка preload в index.html):
     Jost (сейчас):                --hero-face: 'Jost', 'Jost Fallback'; --hero-weight: 300; --hero-track: -.01em; --hero-scale: 1.12
     Sofia Sans Semi Condensed:    --hero-face: 'Sofia Sans Semi Condensed', 'Sofia Fallback'; 300; 0; 1.12
     Tenor Sans:                   --hero-face: 'Tenor Sans', 'Tenor Fallback'; 400; -.01em; .94
   --hero-scale подгоняет кегль под ширину шрифта; --rod-y — середина очка от верха строки (по ней идёт стеклянный стержень;
   для Jost при line-height 1: база .845em, очко .46em), у другого шрифта уточнить */
.hero-title { --hero-face: 'Jost', 'Jost Fallback'; --hero-weight: 300; --hero-track: -.01em; --hero-scale: 1.12;
  --rod-y: .615em; --rod-h: .12em;
  position: relative; left: -.035em; width: fit-content; max-width: 100%;
  color: var(--ink); font-family: var(--hero-face), 'Helvetica Neue', Arial, sans-serif; font-weight: var(--hero-weight);
  font-size: calc(clamp(38px, min(5.2vw, 10svh), 84px) * var(--hero-scale)); line-height: 1; letter-spacing: var(--hero-track); margin: 22px 0 28px; }
.hero-title em { font-style: normal; } /* курсива в заголовке нет, даже если в config.js останется *слово* */
.hero-title .line { position: relative; isolation: isolate; display: block; overflow: hidden; padding: 0 .08em .06em; margin: 0 -.08em -.06em; } /* выносные элементы не режутся */
.hero-title .line > span { display: block; text-align: justify; text-align-last: justify; }

/* «Стеклянные стержни» (2.16c): по середине очка каждой строки лежит тонкий стержень прозрачного стекла, подсвеченного
   с торца (как светится торец Люцита). Под стержнем буквы преломлены как в линзе цилиндра — копия строки (::after из
   data-text, в тексте h1 её нет) в полосе стержня увеличена по вертикали на 12 % и чуть высветлена светом стержня,
   сама строка в этой полосе прозрачна (маска). У стержня — тонкие светлые грани, светящаяся середина и мягкое холодноватое
   свечение; после интро по стержням один раз проходит свет. Всё — CSS: в покое ничего не анимируется и не
   перерисовывается. Стекло проявляется (--gl 0 → 1), когда строки встали; без «движения» — сразу.
   Контраст букв в полосе ≈ 4,5 : 1 и выше (#707173 на #f5f5f5), вне полосы — прежний */
@property --gl { syntax: '<number>'; inherits: true; initial-value: 0; }
.hero-title { --gl: 0; transition: --gl 1100ms var(--ease-quart) 1500ms; }
.hero-title.in, html:not(.js-motion) .hero-title { --gl: 1; }
/* строка: в полосе стержня гаснет (padding снизу — чтобы маска не срезала выносные «р», «у») */
.hero-title .line > span { padding-bottom: .3em; margin-bottom: -.3em;
  -webkit-mask: linear-gradient(#000 calc(var(--rod-y) - var(--rod-h) / 2), rgb(0 0 0 / calc(1 - var(--gl))) 0 calc(var(--rod-y) + var(--rod-h) / 2), #000 0);
  mask: linear-gradient(#000 calc(var(--rod-y) - var(--rod-h) / 2), rgb(0 0 0 / calc(1 - var(--gl))) 0 calc(var(--rod-y) + var(--rod-h) / 2), #000 0); }
/* преломлённая копия строки — только в полосе стержня (края полосы растушёваны на 1 px) */
.hero-title .line::after { content: attr(data-text); content: attr(data-text) / ''; position: absolute; z-index: 1; left: .08em; right: .08em; top: 0;
  padding-bottom: .3em; text-align: justify; text-align-last: justify; pointer-events: none; user-select: none;
  color: color-mix(in srgb, var(--ink) 85%, #fff); scale: 1 1.12; transform-origin: 50% var(--rod-y); opacity: var(--gl);
  -webkit-mask: linear-gradient(transparent calc(var(--rod-y) - var(--rod-h) / 2), #000 calc(var(--rod-y) - var(--rod-h) / 2 + 1px) calc(var(--rod-y) + var(--rod-h) / 2 - 1px), transparent calc(var(--rod-y) + var(--rod-h) / 2));
  mask: linear-gradient(transparent calc(var(--rod-y) - var(--rod-h) / 2), #000 calc(var(--rod-y) - var(--rod-h) / 2 + 1px) calc(var(--rod-y) + var(--rod-h) / 2 - 1px), transparent calc(var(--rod-y) + var(--rod-h) / 2)); }
/* сам стержень: проход света (за краем, пока не запущен) · светлые грани и светящаяся середина · свечение */
.hero-title .line::before { content: ''; position: absolute; z-index: 2; left: 0; right: 0; pointer-events: none;
  top: calc(var(--rod-y) - var(--rod-h) / 2); height: var(--rod-h); border-radius: calc(var(--rod-h) / 2); opacity: var(--gl);
  background:
    linear-gradient(90deg, transparent, rgba(255, 255, 255, .95) 50%, transparent) -100% 0 / 40% 100% no-repeat,
    linear-gradient(180deg, rgba(255, 255, 255, .8) 0 1px, rgba(255, 255, 255, .22) 2px, rgba(238, 244, 255, .28) 50%, rgba(255, 255, 255, .2) calc(100% - 2px), rgba(255, 255, 255, .65) calc(100% - 1px));
  box-shadow: 0 0 .18em rgba(255, 255, 255, .8), 0 0 .6em rgba(226, 234, 255, .45); }
.js-motion .hero-title.in .line::before { animation: rod-sweep 1900ms var(--ease-io) calc(2500ms + var(--i, 0) * 180ms) both; }
@keyframes rod-sweep { from { background-position: -100% 0, 0 0; } to { background-position: 200% 0, 0 0; } }
.hero-text { max-width: 24em; color: var(--ink-2); font-size: 17px; font-weight: 400; line-height: 1.6; margin: 0 0 36px; text-wrap: pretty; }
.hero-actions { display: flex; align-items: center; gap: 14px 28px; flex-wrap: wrap; }
.hero-foot { position: absolute; left: var(--pad); right: var(--pad); bottom: 28px; z-index: 3; display: flex; align-items: center; gap: 18px; font-size: 10.5px; color: #8e8d89; text-transform: uppercase; }
.hero-foot .mono { font-weight: var(--caps-weight); letter-spacing: var(--caps-track); }
.hero :focus-visible { outline-color: #3550c8; }
.scroll-line { flex: 0 0 72px; height: 1px; background: var(--line); overflow: hidden; }
.scroll-line i { display: block; height: 100%; width: 40%; background: var(--text-2); animation: scrollhint 2.4s var(--ease-io) infinite; }
@keyframes scrollhint { from { transform: translateX(-100%); } to { transform: translateX(260%); } }

/* ---------- секции ---------- */
.section { padding: var(--section) var(--pad); position: relative; }
.section-head { display: grid; grid-template-columns: 120px 1fr minmax(0, 420px); gap: 24px 40px; align-items: end; margin-bottom: clamp(56px, 8vw, 120px); }
.section-num { font-size: 12px; color: var(--muted); align-self: start; padding-top: 14px; }
.section-num::after { content: ''; display: inline-block; width: 40px; height: 1px; background: var(--line); vertical-align: middle; margin-left: 14px; }
.section-lead { color: var(--text-2); max-width: 27em; margin: 0; font-size: 17px; }

/* ---------- коллекция ---------- */
.collection-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: clamp(20px, 3vw, 48px); align-items: start; }
.collection-grid .card:nth-child(3n+2) { margin-top: clamp(40px, 9vw, 160px); }
.collection-grid .card:nth-child(3n+3) { margin-top: clamp(20px, 4vw, 64px); }
.card { display: block; text-decoration: none; cursor: pointer; background: none; border: 0; padding: 0; text-align: left; width: 100%; }
/* «витрина»: тёмная ниша с прожектором сверху и световым пятном под изделием */
.card-media {
  position: relative; aspect-ratio: 4 / 5; overflow: hidden;
  background:
    radial-gradient(70% 30% at 50% 84%, rgba(236, 240, 246, .12), transparent 70%),
    radial-gradient(80% 70% at 50% 38%, #17191d 0%, #0b0c0e 55%, #050506 100%);
}
.card-media img {
  position: absolute; inset: 9% 9% 13%; width: 82%; height: 78%; object-fit: contain;
  transform: translateY(6px) scale(.97);
  transition: transform 1600ms var(--ease-expo);
}
.card-media::after { /* блик-развёртка */
  content: ''; position: absolute; inset: -20% -60%;
  background: linear-gradient(105deg, transparent 40%, rgba(255, 255, 255, .22) 50%, transparent 60%);
  transform: translateX(-70%); pointer-events: none;
}
.card:hover .card-media img, .card:focus-visible .card-media img { transform: translateY(-4px) scale(1.02); }
.card:hover .card-media::after { transform: translateX(70%); transition: transform 1300ms var(--ease-io); }
.card-cta {
  position: absolute; left: 20px; bottom: 20px; z-index: 2;
  font: var(--caps-weight) 11px/1 var(--sans); letter-spacing: var(--caps-track); text-transform: uppercase;
  padding: 12px 18px; border-radius: 999px; color: #050505; background: rgba(236, 237, 239, .92);
  opacity: 0; transform: translateY(10px); transition: opacity 400ms var(--ease-quart), transform 600ms var(--ease-expo);
}
.card:hover .card-cta, .card:focus-visible .card-cta { opacity: 1; transform: none; }
.card-meta { display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px 14px; padding: 16px 0 0; border-top: 1px solid var(--line); margin-top: 18px; }
/* подпись работы — как в каталоге ювелирного дома: имя изделия антиквой строчными, рядом мелкая подпись прописными */
.card-name { font: 400 clamp(22px, 16px + .9vw, 28px)/1 var(--serif); letter-spacing: -.01em; text-wrap: balance; } /* < H2 ≥ 1,25× */
.card-meta .mono { font: var(--caps-weight) 10.5px/1.2 var(--sans); letter-spacing: var(--caps-track); text-transform: uppercase; color: var(--muted); text-align: right; }
.card-price { margin-left: auto; font-size: 12px; color: var(--text-2); }

/* ---------- конструктор ---------- */
.configurator {
  position: relative; height: 100svh; min-height: 640px; display: grid; grid-template-columns: minmax(0, 1fr) 420px;
  background: var(--bg); border-top: 1px solid var(--line);
}
.stage { position: relative; overflow: hidden; }
#viewer, #viewer-snapshot { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
#viewer { touch-action: none; cursor: grab; }
#viewer:active { cursor: grabbing; }
#viewer-snapshot { pointer-events: none; opacity: 0; }
#viewer-snapshot.fading { transition: opacity 420ms var(--ease-quart); }
.stage-top {
  position: absolute; top: calc(var(--nav-h) + 16px); left: var(--pad); right: 32px; z-index: 2;
  display: flex; justify-content: space-between; gap: 16px; pointer-events: none;
}
.stage-state { font-size: 12px; color: var(--muted); transition: opacity 400ms; }
.stage-progress { position: absolute; left: 0; right: 0; bottom: 0; height: 1px; overflow: hidden; z-index: 2; opacity: 0; transition: opacity 400ms; }
.stage-progress.on { opacity: 1; }
.stage-progress i { display: block; height: 100%; width: 30%; background: linear-gradient(90deg, transparent, var(--ice), transparent); animation: indeterminate 1.4s var(--ease-io) infinite; }
@keyframes indeterminate { from { transform: translateX(-100%); } to { transform: translateX(340%); } }
.stage-bottom {
  position: absolute; left: var(--pad); right: 24px; bottom: 24px; z-index: 2;
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
}
.stage-dims { font-size: 12px; color: var(--muted); }
.stage-tools { display: flex; gap: 8px; }
.tool {
  width: 42px; height: 42px; display: grid; place-items: center; border-radius: 50%; cursor: pointer;
  background: var(--glass); border: 1px solid var(--glass-line); color: var(--text-2);
  backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px);
  transition: color var(--d-hover), border-color var(--d-hover), background var(--d-hover);
}
.tool svg { width: 18px; height: 18px; }
.tool:hover { color: var(--text); border-color: rgba(255, 255, 255, .25); }
.tool[aria-pressed="true"] { color: var(--ice); border-color: rgba(207, 230, 255, .4); }
.stage-cursor {
  position: absolute; left: 0; top: 0; z-index: 3; width: 64px; height: 64px; margin: -32px 0 0 -32px;
  border-radius: 50%; border: 1px solid rgba(236, 237, 239, .35); display: grid; place-items: center;
  font: 600 9.5px/1 var(--sans); letter-spacing: var(--caps-track); text-transform: uppercase; color: var(--text-2);
  pointer-events: none; opacity: 0; transition: opacity 300ms, scale 400ms var(--ease-expo);
}
.stage-cursor.on { opacity: 1; }
.stage-cursor.down { scale: .8; }

/* панель */
.panel {
  position: relative; display: flex; flex-direction: column; min-height: 0;
  background: linear-gradient(180deg, rgba(255, 255, 255, .045), rgba(255, 255, 255, .02));
  border-left: 1px solid var(--line);
}
.panel-scroll { flex: 1; overflow-y: auto; padding: calc(var(--nav-h) + 20px) 32px 24px; scrollbar-width: thin; scrollbar-color: var(--line) transparent; }
.panel-head { margin-bottom: 22px; }
.model-name { font-size: 56px; margin: 10px 0 0; }
/* аккордеон */
.acc { border-top: 1px solid var(--line); }
.acc:last-child { border-bottom: 1px solid var(--line); }
.acc-head {
  width: 100%; display: flex; align-items: center; gap: 12px; padding: 18px 0; cursor: pointer;
  background: none; border: 0; text-align: left; color: var(--text);
}
.acc-num { font-size: 10px; color: var(--muted); width: 22px; }
.acc-title { font: var(--caps-weight) 11.5px/1 var(--sans); letter-spacing: var(--caps-track); text-transform: uppercase; }
.acc-sum { margin-left: auto; font-size: 12.5px; font-weight: 400; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 48%; }
.acc-icon { width: 11px; height: 11px; position: relative; flex: none; }
.acc-icon::before, .acc-icon::after { content: ''; position: absolute; left: 0; right: 0; top: 50%; height: 1px; background: var(--text-2); transition: transform 500ms var(--ease-expo); }
.acc-icon::after { transform: rotate(90deg); }
.acc.open .acc-icon::after { transform: rotate(0deg); }
/* 2.20 (аудит конструктора на телефоне, п. 3): высота секции — без анимации (анимация grid-template-rows — раскладка и
   перерисовка всей панели в каждом кадре, ≈ 0,5 с отрисовки на два раскрытия при ×4); плавность даёт содержимое —
   opacity / transform (композитор) */
.acc-body { display: grid; grid-template-rows: 0fr; }
.acc.open .acc-body { grid-template-rows: 1fr; }
.acc-inner { overflow: hidden; }
.acc-content { padding: 4px 0 22px; opacity: 0; transform: translateY(-6px); transition: opacity 400ms var(--ease-quart), transform 600ms var(--ease-expo); }
.acc.open .acc-content { opacity: 1; transform: none; transition-delay: 80ms; }

/* ползунки */
.slider { margin-bottom: 16px; }
.slider:last-child { margin-bottom: 0; }
.slider[hidden] { display: none; }
.slider-head { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; }
.slider-head label { font-size: 14.5px; color: var(--text-2); }
.slider-head output { font-family: var(--mono); font-size: 14px; font-weight: 500; letter-spacing: .02em; color: var(--text); font-variant-numeric: lining-nums tabular-nums; }
.slider-hint { font-size: 12.5px; line-height: 1.5; color: var(--muted); margin: 0; text-wrap: pretty; }
.slider.disabled { opacity: .35; }
input[type="range"] {
  -webkit-appearance: none; appearance: none; width: 100%; height: 26px; margin: 0; background: transparent; cursor: pointer;
}
input[type="range"]::-webkit-slider-runnable-track {
  height: 1px; background: linear-gradient(90deg, var(--text) var(--fill, 50%), var(--line) var(--fill, 50%));
}
input[type="range"]::-moz-range-track { height: 1px; background: var(--line); }
input[type="range"]::-moz-range-progress { height: 1px; background: var(--text); }
input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none; width: 13px; height: 13px; margin-top: -6px; border-radius: 50%;
  background: var(--text); border: 0; box-shadow: 0 0 0 0 rgba(207, 230, 255, .0);
  transition: box-shadow 300ms var(--ease-quart), transform 300ms var(--ease-expo);
}
input[type="range"]::-moz-range-thumb { width: 13px; height: 13px; border-radius: 50%; background: var(--text); border: 0; }
input[type="range"]:hover::-webkit-slider-thumb { box-shadow: 0 0 0 6px rgba(207, 230, 255, .1); }
input[type="range"]:active::-webkit-slider-thumb { transform: scale(1.25); box-shadow: 0 0 0 8px rgba(207, 230, 255, .14), 0 0 18px rgba(207, 230, 255, .5); }
input[type="range"]:focus-visible { outline: none; }
input[type="range"]:focus-visible::-webkit-slider-thumb { box-shadow: 0 0 0 4px rgba(207, 230, 255, .35); }
input[type="range"]:disabled { cursor: not-allowed; }

/* выбор формы верха */
.tops { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; margin-bottom: 18px; }
.top-choice {
  display: grid; justify-items: center; gap: 8px; padding: 14px 4px 10px; cursor: pointer;
  background: transparent; border: 1px solid var(--line); border-radius: 2px; color: var(--muted);
  font: 600 9.5px/1 var(--sans); letter-spacing: var(--caps-track); text-transform: uppercase;
  transition: color var(--d-hover), border-color var(--d-hover), background var(--d-hover);
}
.top-choice svg { width: 34px; height: 34px; }
.top-choice:hover { color: var(--text-2); border-color: rgba(255, 255, 255, .22); }
.top-choice[aria-checked="true"] { color: var(--text); border-color: var(--ice); background: rgba(207, 230, 255, .05); }

/* цвета и отделка */
.swatches { display: flex; flex-wrap: wrap; gap: 12px; margin-bottom: 8px; }
.swatch {
  width: 30px; height: 30px; border-radius: 50%; padding: 0; cursor: pointer; position: relative;
  border: 1px solid rgba(255, 255, 255, .18);
  background: radial-gradient(circle at 32% 28%, rgba(255, 255, 255, .9), var(--c) 46%, color-mix(in srgb, var(--c) 55%, #000) 100%);
}
.swatch::after { content: ''; position: absolute; inset: -6px; border-radius: 50%; border: 1px solid transparent; transition: border-color 300ms, inset 400ms var(--ease-expo); }
.swatch:hover::after { border-color: rgba(255, 255, 255, .2); }
.swatch[aria-checked="true"]::after { border-color: var(--ice); inset: -5px; }
.swatch-label { font-size: 13.5px; color: var(--text-2); margin: 10px 0 18px; }
.pills { display: flex; flex-wrap: wrap; gap: 8px; }
.pill {
  padding: 10px 14px; border-radius: 999px; cursor: pointer; background: transparent; color: var(--text-2);
  border: 1px solid var(--line); font-size: 13.5px; transition: all var(--d-hover);
}
.pill:hover { border-color: rgba(255, 255, 255, .25); color: var(--text); }
.pill[aria-checked="true"] { border-color: var(--ice); color: var(--text); background: rgba(207, 230, 255, .06); }
.note { font-size: 12.5px; line-height: 1.5; color: var(--muted); margin: 12px 0 0; text-wrap: pretty; }

/* низ панели */
.panel-foot { padding: 18px 32px 24px; border-top: 1px solid var(--line); background: rgba(2, 2, 2, .35); }
.price-row { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
/* цена — антиква с табличными цифрами высоты прописных: при движении ползунка сумма не «дрожит» по ширине */
.price { font-size: 40px; font-weight: 400; letter-spacing: -.01em; font-variant-numeric: lining-nums tabular-nums; }
.spec { font-size: 12px; color: var(--muted); margin: 6px 0 16px; min-height: 1em; }

/* ---------- материал (светлая секция) ---------- */
.theme-light {
  --text: #0e0f11; --text-2: #4a4e55; --muted: #62666d; --line: rgba(14, 15, 17, .12); /* muted ≥ 4,5 : 1 на #e8e9eb */
  background: radial-gradient(120% 90% at 30% 40%, #f3f3f4, #e8e9eb 55%, #d9dadd);
  color: var(--text);
}
.material { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(40px, 7vw, 120px); align-items: center; }
.material-media {
  margin: 0; aspect-ratio: 4 / 5; overflow: hidden; display: grid; place-items: center;
  background: radial-gradient(70% 60% at 50% 42%, #fbfbfc, #e3e4e7 60%, #d2d4d8);
}
.material-media img { width: 78%; height: 78%; max-width: 640px; object-fit: contain; filter: drop-shadow(0 18px 30px rgba(0, 0, 0, .35)); }
.material-copy .h2 { margin: 28px 0 32px; }
.specs { margin: 48px 0 0; }
.specs div { display: flex; justify-content: space-between; gap: 24px; padding: 14px 0; border-top: 1px solid var(--line); }
.specs div:last-child { border-bottom: 1px solid var(--line); }
.specs dt { font: var(--caps-weight) 11px/1.4 var(--sans); letter-spacing: var(--caps-track); text-transform: uppercase; color: var(--text-2); }
/* значения — антиква 400 (волосные линии 300 на тёмном в 19–21 px тают) с цифрами высоты прописных: «1,19 г/см³», «92%» */
.specs dd { margin: 0; font-family: var(--serif); font-weight: 400; font-size: 21px; line-height: 1.1; text-align: right; font-variant-numeric: lining-nums; }

/* ---------- процесс ---------- */
.process .section-head { grid-template-columns: 120px 1fr; }
.steps { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(4, 1fr); border-top: 1px solid var(--line); }
.steps li { padding: 32px 32px 0 0; border-right: 1px solid var(--line); margin-right: 32px; }
.steps li:last-child { border-right: 0; margin-right: 0; }
.steps .mono { font-size: 11px; color: var(--muted); }
.steps h3 { font: 400 clamp(24px, 14px + 2vw, 38px)/1 var(--serif); letter-spacing: -.01em; margin: 48px 0 16px; } /* H3 < H2 на всех ширинах */
.steps p { color: var(--text-2); margin: 0 0 32px; max-width: 17.5em; text-wrap: pretty; }
.process-cta { margin-top: clamp(56px, 8vw, 120px); display: flex; justify-content: center; }

/* ---------- подвал ---------- */
.footer { padding: 72px var(--pad) 48px; border-top: 1px solid var(--line); display: grid; gap: 18px; justify-items: center; text-align: center; color: var(--muted); font-size: 14px; }
.footer-logo { font-size: clamp(34px, 10vw, 160px); color: var(--text); /* «PLEXIFORM» одним словом: на 320 px не шире экрана */ letter-spacing: .2em; padding-left: .2em; line-height: 1; }
.footer p { margin: 0; }
.footer-links { display: flex; flex-wrap: wrap; justify-content: center; gap: 14px 28px; } /* на 320 px ссылки — двумя строками, телефон не рвётся */
.footer-links a { font: var(--caps-weight) 11.5px/1 var(--sans); letter-spacing: var(--caps-track); text-transform: uppercase; text-decoration: none; color: var(--text-2); white-space: nowrap; }

/* ---------- диалог заказа ---------- */
dialog {
  width: min(520px, calc(100vw - 24px)); max-height: calc(100svh - 24px); padding: 0; color: var(--text);
  overscroll-behavior: contain;   /* 2.22.1: прокрутка окна заказа не уходит в страницу под ним */
  background: rgba(14, 15, 18, .86); border: 1px solid var(--glass-line); border-radius: 2px;
  backdrop-filter: blur(30px) saturate(140%); -webkit-backdrop-filter: blur(30px) saturate(140%);
}
dialog[open] { animation: dlg-in 700ms var(--ease-expo); }
dialog::backdrop { background: rgba(0, 0, 0, .6); backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px); animation: fade-in 500ms var(--ease-quart); }
@keyframes dlg-in { from { opacity: 0; transform: translateY(24px) scale(.98); } to { opacity: 1; transform: none; } }
@keyframes fade-in { from { opacity: 0; } }
.order-form { position: relative; padding: 40px 36px 36px; }
.order-step { display: grid; gap: 18px; }
.order-step[hidden] { display: none; }
.order-form h2 { font-size: 52px; margin: 0 0 4px; }
.dialog-close { position: absolute; top: 18px; right: 18px; width: 40px; height: 40px; display: grid; place-items: center; background: none; border: 0; color: var(--text-2); cursor: pointer; transition: transform 500ms var(--ease-expo), color 200ms; }
.dialog-close:hover { color: var(--text); transform: rotate(90deg); }
.order-recap { font-size: 13.5px; color: var(--text-2); padding: 14px 0; border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); line-height: 1.7; }
.field { display: grid; gap: 6px; }
.field > span { font: var(--caps-weight) 11px/1 var(--sans); letter-spacing: var(--caps-track); text-transform: uppercase; color: var(--text-2); }
.field em { font-style: normal; color: var(--muted); letter-spacing: .02em; text-transform: none; }
.field input, .field textarea {
  width: 100%; padding: 10px 0; background: transparent; border: 0; border-bottom: 1px solid var(--line); border-radius: 0;
  font-size: 16px; transition: border-color 300ms; /* 16 px — iPhone не увеличивает страницу при вводе */
}
.field textarea { resize: vertical; }
.field input::placeholder, .field textarea::placeholder { color: var(--muted); }
.field input:focus, .field textarea:focus { outline: none; border-color: var(--ice); }
.field input[aria-invalid="true"] { border-color: var(--danger); }
.field-small input { max-width: 120px; }
.check { display: flex; gap: 12px; align-items: flex-start; font-size: 13.5px; line-height: 1.5; color: var(--text-2); }
.check input { margin-top: 2px; accent-color: var(--ice); }
.form-error { color: var(--danger); font-size: 13.5px; margin: 0; }
.form-error:empty { display: none; }
.order-done-text { color: var(--text-2); margin: 0 0 8px; text-wrap: pretty; }

/* ---------- toast ---------- */
.toast {
  position: fixed; left: 50%; bottom: 28px; z-index: 95; transform: translate(-50%, 16px);
  padding: 12px 22px; border-radius: 999px; background: var(--text); color: #050505;
  font: var(--caps-weight) 11.5px/1 var(--sans); letter-spacing: var(--caps-track); text-transform: uppercase;
  opacity: 0; pointer-events: none; transition: opacity 400ms var(--ease-quart), transform 600ms var(--ease-expo);
}
.toast.show { opacity: 1; transform: translate(-50%, 0); }

/* ---------- появление при скролле (включается только при работающем JS) ---------- */
.js-motion .reveal-up { opacity: 0; transform: translateY(28px); transition: opacity var(--d-reveal) var(--ease-expo), transform 1100ms var(--ease-expo); transition-delay: var(--delay, 0ms); }
.js-motion .reveal-up.in { opacity: 1; transform: none; }
/* строки заголовка — блоки всегда (и при «Уменьшении движения», когда .js-motion нет): иначе строки склеиваются в одно
   длинное «слово» без пробелов, распирают колонку шире экрана, и на iPhone страницу можно отдалить за её край */
.reveal-lines .line { display: block; }
.reveal-lines .line > span { display: block; }
.js-motion .reveal-lines .line { display: block; overflow: hidden; padding-bottom: .06em; margin-bottom: -.06em; }
.js-motion .reveal-lines .line > span { display: block; transform: translateY(110%); transition: transform 1200ms var(--ease-expo); transition-delay: var(--delay, 0ms); }
.js-motion .reveal-lines.in .line > span { transform: none; }
.js-motion .hero-title .line > span { transform: translateY(110%); transition: transform 1300ms var(--ease-expo); transition-delay: var(--delay, 0ms); }
.js-motion .hero-title.in .line > span { transform: none; }
.js-motion .reveal-clip { clip-path: inset(100% 0 0 0); transition: clip-path 1400ms var(--ease-expo); }
.js-motion .reveal-clip.in { clip-path: inset(0 0 0 0); }
.js-motion .reveal-clip img { transform: scale(1.15); transition: transform 2000ms var(--ease-expo); }
.js-motion .reveal-clip.in img { transform: none; }
.js-motion .card { opacity: 0; transform: translateY(48px); transition: opacity 1000ms var(--ease-expo), transform 1300ms var(--ease-expo); transition-delay: var(--delay, 0ms); }
.js-motion .card.in { opacity: 1; transform: none; }

/* =====================================================================
   ТИТАН (2.4): тёплый графитовый полированный титан, цвет — только как свет.
   Самое яркое на экране — кольцо; интерфейс не ярче половины его яркости.
   ===================================================================== */
body {
  background:
    radial-gradient(55vw 45vh at 0% 8%, rgba(43, 92, 255, .07), transparent 70%),
    radial-gradient(55vw 45vh at 100% 96%, rgba(201, 128, 58, .06), transparent 70%),
    radial-gradient(35vw 35vh at 88% 12%, rgba(123, 75, 214, .045), transparent 70%),
    linear-gradient(180deg, #121316, var(--bg) 35%, var(--bg));
  background-attachment: fixed;
}
/* фактура тонкой горизонтальной шлифовки вместо зерна */
.grain {
  inset: 0; opacity: .05; mix-blend-mode: overlay; animation: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='600' height='600'%3E%3Cfilter id='b'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.002 0.8' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23b)'/%3E%3C/svg%3E");
}
.nav.is-scrolled { background: rgba(14, 15, 17, .62); border-color: var(--line); }

/* кнопки (2.13, docs/review-212 panel-01/02): без «хрома» и бликов — сплошной тихий тон палитры: на тёмном — светлая
   (тёплый белый #e6e3dd, текст 14 : 1), при наведении чуть светлее, при нажатии — чуть темнее; фокус — кольцо 2 px */
.btn-light {
  color: #141518; border-color: transparent; background: #e6e3dd;
  transition: background-color var(--d-ui) var(--ease-quart), color var(--d-ui), opacity var(--d-ui);
}
.btn-light::before { display: none; }
.btn-light:not(:disabled):hover { background-color: #f3f1ec; }
.btn-light:not(:disabled):active { background-color: #d8d5ce; }
.btn:focus-visible { outline: 2px solid var(--ice); outline-offset: 3px; }
.btn-ghost { border-color: var(--line-2); }
.btn-text { color: var(--text-2); }

/* панель конструктора: шлифованная рамка и мягкий внутренний блик */
.panel {
  background: linear-gradient(180deg, #1b1d21, #141518);
  border-left: 1px solid rgba(232, 228, 220, .1);
  box-shadow: inset 1px 0 0 rgba(255, 255, 255, .04), -24px 0 60px -30px #000;
}
.panel-foot { background: linear-gradient(180deg, rgba(20, 21, 24, .4), rgba(14, 15, 17, .9)); border-top-color: var(--line); }
.model-name em { font-style: italic; }
.tool {
  background: radial-gradient(circle at 35% 30%, rgba(232, 228, 220, .14), rgba(232, 228, 220, .03) 60%);
  border-color: var(--line-2);
}
.tool[aria-pressed="true"] { color: var(--text); border-color: transparent; box-shadow: 0 0 0 1px rgba(159, 180, 245, .5), 0 0 18px rgba(79, 111, 232, .25); }

/* ползунки: дорожка — светлый титан, бегунок — точёный металл */
input[type="range"]::-webkit-slider-runnable-track { background: linear-gradient(90deg, var(--ti-hi) var(--fill, 50%), var(--line-2) var(--fill, 50%)); }
input[type="range"]::-moz-range-progress { background: var(--ti-hi); }
input[type="range"]::-webkit-slider-thumb {
  background: conic-gradient(from 200deg, #8e8a84, #d8d4cc 15%, #9c9891 35%, #c9c5bd 55%, #8f8b85 75%, #b5b1aa 90%, #8e8a84);
  box-shadow: 0 0 0 1px rgba(0, 0, 0, .45), inset 0 1px 0 rgba(255, 255, 255, .4);
}
input[type="range"]::-moz-range-thumb { background: #c9c5bd; }
input[type="range"]:hover::-webkit-slider-thumb { box-shadow: 0 0 0 1px rgba(0, 0, 0, .45), 0 0 0 6px rgba(79, 111, 232, .12); }
input[type="range"]:active::-webkit-slider-thumb { box-shadow: 0 0 0 1px rgba(0, 0, 0, .45), 0 0 0 8px rgba(79, 111, 232, .16), 0 0 16px rgba(79, 111, 232, .35); }

/* выбранное состояние (2.13; до того — линия побежалости «бронза → слива → кобальт», в ревью — «RGB-кант»): спокойная
   линия 1 px цвета текста (≈ 13 : 1 к панели, невыбранная — волосяная .08), у плиток и отделки — едва заметная подложка */
.top-choice[aria-checked="true"], .pill[aria-checked="true"] { color: var(--text); border-color: currentColor; background: rgba(232, 228, 220, .045); }
/* образцы цвета — плоские диски настоящего цвета акрила (цвета не приглушаем; прежде — глянцевые «леденцы»), по краю —
   волосяная светлая линия: тёмный «Обсидиан» не тонет в панели. Выбранный — кольцо 1 px цвета текста */
.swatch { border: 0; background: var(--c); box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .14); }
.swatch[aria-checked="true"]::after { border-color: var(--text); inset: -5px; }

/* расшифровка цены и подсказки */
/* переключатель параметра («Соединить грани»): дорожка — светлый титан, во включённом — линия побежалости */
.toggle { padding: 6px 0 4px; }
.toggle-btn {
  display: flex; align-items: center; justify-content: space-between; gap: 16px; width: 100%;
  background: none; border: 0; padding: 6px 0; color: var(--text); font: inherit; font-size: 14.5px; cursor: pointer; text-align: left;
}
.toggle-track {
  position: relative; flex: 0 0 38px; height: 22px; border-radius: 11px;
  background: rgba(232, 228, 220, .08); box-shadow: inset 0 0 0 1px var(--line-2); transition: background 300ms var(--ease-quart), box-shadow 300ms;
}
.toggle-track i {
  position: absolute; top: 3px; left: 3px; width: 16px; height: 16px; border-radius: 50%;
  background: conic-gradient(from 200deg, #8e8a84, #d8d4cc 15%, #9c9891 35%, #c9c5bd 55%, #8f8b85 75%, #b5b1aa 90%, #8e8a84);
  box-shadow: 0 1px 3px rgba(0, 0, 0, .5); transition: transform 400ms var(--ease-expo);
}
.toggle-btn[aria-checked="true"] .toggle-track { background: rgba(79, 111, 232, .18); box-shadow: inset 0 0 0 1px rgba(159, 180, 245, .55); }
.toggle-btn[aria-checked="true"] .toggle-track i { transform: translateX(16px); }
.toggle-btn:focus-visible { outline: 1px solid var(--ice); outline-offset: 4px; }
.toggle.disabled { opacity: .45; }
.toggle.disabled .toggle-btn { cursor: default; }

/* телефон для связи под кнопкой заказа и в окне заказа */
.foot-contact, .order-phone { font-size: 13.5px; line-height: 1.5; color: var(--text-2); margin: 12px 0 0; text-align: center; }
.foot-contact a, .order-phone a { color: var(--text); text-decoration: none; border-bottom: 1px solid var(--line-2); white-space: nowrap; }
.foot-contact a:hover, .order-phone a:hover { border-bottom-color: currentColor; }
.stage-hint {
  position: absolute; left: 50%; bottom: 30px; transform: translateX(-50%); z-index: 2; margin: 0;
  font-size: 12px; font-weight: 400; letter-spacing: .04em; color: var(--muted); pointer-events: none; white-space: nowrap;
}
/* узкая сцена (окно до 1280 px): подсказка не помещается между размерами и кнопками — поднимаем её над ними */
@media (min-width: 861px) and (max-width: 1280px) {
  .stage-hint { bottom: 80px; width: min(80%, 420px); white-space: normal; text-align: center; line-height: 1.6; }
}
/* переход к ползунку по двойному щелчку — короткая вспышка */
.slider { border-radius: 6px; }
.slider.flash { animation: slider-flash 1.6s var(--ease-quart); }
@keyframes slider-flash {
  0%, 35% { background: rgba(79, 111, 232, .14); box-shadow: 0 0 0 10px rgba(79, 111, 232, .14); }
  100% { background: transparent; box-shadow: 0 0 0 10px transparent; }
}

/* всплывающий ползунок грани (удержание на телефоне) */
.quick {
  position: absolute; left: 16px; right: 16px; bottom: 74px; z-index: 4;
  padding: 14px 48px 8px 16px; border-radius: 12px;
  background: rgba(22, 24, 27, .9); border: 1px solid var(--line-2);
  backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
  opacity: 0; transform: translateY(12px); transition: opacity 300ms var(--ease-quart), transform 450ms var(--ease-expo);
}
.quick.on { opacity: 1; transform: none; }
.stage-hint { transition: opacity 300ms var(--ease-quart); }
.stage.quick-open .stage-hint { opacity: 0; }
.quick label { font-size: 14.5px; color: var(--text); }
.quick-close {
  position: absolute; top: 8px; right: 8px; width: 36px; height: 36px; display: grid; place-items: center;
  background: none; border: 0; color: var(--text-2); cursor: pointer;
}

/* каталог: 4 готовые работы в один ряд; стилизованные фото — на всю карточку.
   Края всех стилизованных кадров уходят ровно в #121519 — такого же цвета фон секции и карточек */
.collection, .material { background: #121519; }
.collection-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.collection-grid .card:nth-child(n) { margin-top: 0; }
.collection-grid .card:nth-child(2n) { margin-top: clamp(28px, 5vw, 88px); }
.card-media {
  border-radius: 2px;
  background:
    radial-gradient(70% 38% at 50% 84%, rgba(232, 228, 220, .07), transparent 70%),
    radial-gradient(90% 70% at 25% 18%, rgba(43, 92, 255, .08), transparent 60%),
    linear-gradient(160deg, #23252a, #16171a 55%, #0b0c0e);
  box-shadow: inset 0 0 0 1px rgba(232, 228, 220, .06);
}
.card-media img { inset: 0; width: 100%; height: 100%; object-fit: cover; transform: scale(1.02); }
.card:hover .card-media img, .card:focus-visible .card-media img { transform: scale(1.06); }
.card-fallback .card-media img { inset: 9% 9% 13%; width: 82%; height: 78%; object-fit: contain; }
.card-cta { color: #141518; background: linear-gradient(100deg, #b5b1aa, #d8d4cc 50%, #a9a59e); }

/* hero «Светлое поле»: режимы по соотношению сторон окна, интро, шапка и лоадер (docs/research-hero.md) */
@media (min-aspect-ratio: 1/1) { /* W/S: кнопка на светлом — сплошной графит (2.13; до того — тёмный полированный титан) */
  .hero .btn-light { color: #eeece7; background-color: #1b1c20; }
  .hero .btn-light:not(:disabled):hover { background-color: #2c2d32; }
  .hero .btn-light:not(:disabled):active { background-color: #111214; }
  .hero .btn-text { color: var(--ink); }
}
@media (max-height: 760px) and (min-aspect-ratio: 1/1) { .hero-title { margin: 16px 0 20px; } .hero-text { margin-bottom: 26px; font-size: 16px; } .hero-copy { padding-bottom: 12svh; } }
@media (max-height: 520px) and (min-aspect-ratio: 1/1) { .hero-text { display: none; } } /* телефон в ландшафте */
@media not all and (min-aspect-ratio: 7/5) { /* S: 4:3, 5:4, планшет в ландшафте */
  .hero { --ar: 4 / 3; --ax: 62%; --ay: 60%; --rl: 42.66%; --rt: 35.39%; --rw: 52.06%; align-items: start; }
  .hero-copy { width: min(54vw, 620px); padding-top: calc(var(--nav-h) + 7svh); }
  .hero-title { font-size: calc(clamp(38px, min(5.7vw, 7.8svh), 84px) * var(--hero-scale)); }
}
@media not all and (min-aspect-ratio: 1/1) { /* P и T: заголовок на стене, кольцо в середине, кнопки на полу */
  .hero { --ar: 3 / 4; --ax: 50%; --ay: 60%; --rl: 20.36%; --rt: 43.43%; --rw: 67.86%; --fl: 20svh; display: block; padding-bottom: clamp(140px, 24svh, 220px); }
  .hero-media { bottom: auto; height: 100svh; transform: translate3d(0, calc(var(--p) * 18svh), 0); }
  .hero-fade { top: calc(100svh - var(--fl)); }
  .hero-tone { height: 64svh; }
  .hero-foot { display: none; }
  .hero-copy { width: auto; min-height: 100svh; margin: 0; display: grid; grid-template-rows: auto auto 1fr auto; padding: calc(var(--nav-h) + 3svh) var(--pad) 8svh; translate: none; opacity: 1; }
  .hero .eyebrow { grid-row: 1; }
  .hero-title { grid-row: 2; font-size: calc(clamp(38px, min(7.8vw, 6.3svh), 76px) * var(--hero-scale)); margin: 18px 0 0; }
  .hero-actions { grid-row: 4; }
  .hero-text { position: absolute; left: var(--pad); right: var(--pad); top: calc(100% + 4px); max-width: 26em; margin: 0; color: var(--text-2); font-weight: 400; font-size: 16px; }
  .hero .btn-text { color: var(--text); }
}
@media not all and (min-aspect-ratio: 13/20) { /* T: телефоны */
  .hero { --ar: 9 / 16; --ax: 50%; --ay: 40%; --rl: 8.12%; --rt: 41.68%; --rw: 83.53%; }
  .hero-title { font-size: calc(clamp(36px, min(10.8vw, 6.3svh), 56px) * var(--hero-scale) * 1.12); } /* две строки — блок ≈ 85 % ширины телефона */
}
/* 2.12f: телефон (≤ 480 px, портрет) — абзац hero стоял под сгибом и уходил под стекло непрочитанным: вместо него
   одна строка над кнопками, на тёмном полу (.hero-lede, в разметке). На компьютере и планшете — прежний абзац */
.hero-lede { display: none; }
@media (max-width: 480px) and (orientation: portrait) {
  .hero-copy { grid-template-rows: auto auto 1fr auto auto; }
  .hero-text { display: none; }
  .hero-lede { display: block; grid-row: 4; margin: 0 0 20px; color: var(--text); font-size: 15px; line-height: 1.4; text-wrap: balance; }
  .hero-actions { grid-row: 5; }
}
/* интро — только при .js-motion */
.js-motion .hero-stage { scale: 1.05; transition: scale 2600ms var(--ease-expo); }
.js-motion .hero-ring img { opacity: 0; scale: .97; transition: opacity 1400ms var(--ease-quart) 200ms, scale 2200ms var(--ease-expo) 200ms; }
.js-motion .hero-foot { opacity: 0; transition: opacity 900ms var(--ease-quart) 1200ms; }
.js-motion .hero.in .hero-stage, .js-motion .hero.in .hero-ring img, .js-motion .hero.in .hero-foot { scale: 1; opacity: 1; }
.js-motion .hero.in .hero-glint i { animation: hero-glint 1800ms var(--ease-io) 1500ms both; }
@keyframes hero-glint { to { translate: 330% 0; } }
@media (prefers-reduced-motion: reduce) { .hero-glint { display: none; } }
/* шапка: над светлым hero — тёмные чернила */
.nav { color: var(--text); transition: color 400ms var(--ease-quart), background-color 400ms var(--ease-quart), border-color 400ms, transform 600ms var(--ease-expo), opacity 900ms var(--ease-quart) 500ms; }
body.is-loading .nav { opacity: 0; }
.nav.on-light { --text: #16171a; --text-2: #3e4147; --line: rgba(22, 23, 26, .1); }
.nav.on-light.is-scrolled { background: rgba(246, 246, 245, .66); border-color: rgba(22, 23, 26, .08); }
.nav.on-light :focus-visible { outline-color: #3550c8; }
/* лоадер: светлый — передаёт кадр светлому hero без вспышки */
.loader { background: #f2f2f1; color: #16171a; transition: opacity 1000ms var(--ease-io) 120ms, visibility 0s 1120ms; }
.loader-line { background: rgba(22, 23, 26, .12); }
.loader-line span { background: #16171a; }
.loader-count { color: #686a6f; } /* 4,8 : 1 на светлом экране загрузки */
.loader > * { transition: opacity 450ms cubic-bezier(.5, 0, .75, 0), transform 450ms cubic-bezier(.5, 0, .75, 0); }
.loader.done > * { opacity: 0; transform: translateY(-10px); }

/* материал: светлее основного фона, тот же титан */
.material { border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); }
.material-media {
  background: radial-gradient(70% 60% at 50% 45%, #2a2c31, #17181b 65%, #0f1012);
  box-shadow: inset 0 0 0 1px rgba(232, 228, 220, .06);
}
.material-media.has-photo { background: #121519; box-shadow: none; }
.material-media.has-photo img { width: 100%; height: 100%; max-width: none; object-fit: cover; filter: none; }
.card:not(.card-fallback) .card-media { background: #121519; box-shadow: none; }

/* ---------- адаптив ---------- */
@media (max-width: 1100px) {
  .collection-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 1100px) {
  .configurator { grid-template-columns: minmax(0, 1fr) 360px; }
  .model-name { font-size: 46px; }
  .steps { grid-template-columns: repeat(2, 1fr); }
  .steps li:nth-child(2) { border-right: 0; margin-right: 0; }
}
@media (max-width: 860px) {
  :root { --nav-h: 64px; }
  .nav { grid-template-columns: 1fr auto; }
  .nav-side:first-child { display: none; }
  .nav-right a:not(:last-child) { display: none; } /* на телефоне справа — только «Заказ» */
  .nav-logo { font-size: 17px; letter-spacing: .3em; justify-self: start; padding-left: 0; }
  .section-head { grid-template-columns: minmax(0, 1fr); gap: 16px; }
  .process .section-head { grid-template-columns: minmax(0, 1fr); }
  .collection-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .collection-grid .card:nth-child(n) { margin-top: 0; }
  .collection-grid .card:nth-child(2n) { margin-top: 56px; }
  .configurator { height: auto; min-height: 0; grid-template-columns: minmax(0, 1fr); }
  .stage { position: sticky; top: 0; height: 58svh; z-index: 1; }
  .stage-top { top: calc(var(--nav-h) + 8px); }
  .panel { z-index: 2; border-left: 0; border-top: 1px solid var(--line); background: rgba(10, 11, 13, .92); }
  .panel-scroll { overflow: visible; padding: 28px var(--pad) 12px; }
  .panel-foot { position: sticky; bottom: 0; z-index: 3; background: rgba(2, 2, 2, .88); padding: 14px var(--pad) calc(14px + env(safe-area-inset-bottom)); } /* 2.20: без backdrop-filter */
  .price { font-size: 32px; }
  .spec { margin-bottom: 10px; }
  .material { grid-template-columns: minmax(0, 1fr); }
  .stage-cursor { display: none; }
  input[type="range"] { height: 40px; }
  .stage-hint { bottom: auto; top: calc(var(--nav-h) + 30px); }
  .quick { bottom: 70px; }
}
@media (max-width: 560px) {
  .collection-grid { grid-template-columns: minmax(0, 1fr); }
  .collection-grid .card:nth-child(2n) { margin-top: 0; }
  .steps { grid-template-columns: minmax(0, 1fr); }
  .steps li { border-right: 0; margin-right: 0; padding-right: 0; }
  .steps h3 { margin-top: 24px; }
  .order-form { padding: 32px 22px 24px; }
  .order-form h2 { font-size: 42px; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 1ms !important; animation-iteration-count: 1 !important; transition-duration: 200ms !important; transition-delay: 0ms !important; }
  .grain { animation: none; }
}

/* =====================================================================
   ЖИДКИЙ ТИТАН (2.6) — docs/research-liquid-glass.md
   Один сквозной фон под всей тёмной частью страницы: WebGL-холст #ambient (js/ambient.js) — смазанный
   полированный титан с цветным светом и лёгким «жидким стеклом». Разделы прозрачны и без рамок —
   границ фона между ними нет. Hero не меняется: его пол уходит в #121519, из этого же цвета
   поле проявляется сверху коллекции.
   ===================================================================== */
body { background: #121519; } /* без background-attachment: fixed; цвет совпадает с низом .hero-fade */
.ambient { position: fixed; left: 0; top: 0; z-index: -1; display: block; width: 100%; height: 100vh; height: 100lvh; pointer-events: none; }
html.no-ambient body { /* нет WebGL: статичный свет того же характера */
  background:
    radial-gradient(70vw 60vh at 0% 24%, rgba(43, 92, 255, .07), transparent 70%),
    radial-gradient(70vw 60vh at 100% 46%, rgba(201, 128, 58, .06), transparent 70%),
    radial-gradient(60vw 50vh at 64% 78%, rgba(123, 75, 214, .05), transparent 70%),
    #121519;
}
.collection, .material, .process, .configurator, .footer { background: transparent; border: 0; }
.grain { opacity: .045; }

/* hero → коллекция: поле проявляется из того же #121519, в который уходит пол hero */
.collection { isolation: isolate; }
.collection::before {
  content: ''; position: absolute; left: 0; right: 0; top: 0; z-index: -1; height: min(72vh, 680px); pointer-events: none;
  background: linear-gradient(180deg, #121519, rgba(18, 21, 25, .95) 16%, rgba(18, 21, 25, .82) 32%, rgba(18, 21, 25, .58) 50%,
    rgba(18, 21, 25, .32) 68%, rgba(18, 21, 25, .12) 84%, rgba(18, 21, 25, 0));
}

/* ---------- коллекция: изделия без подложек, единый мотив под всеми ---------- */
.collection-grid .card .card-media { aspect-ratio: 1 / 1; overflow: visible; border-radius: 0; background: none; box-shadow: none; }
.collection-grid .card .card-media::after { display: none; }
/* кольцо стоит на «полированном полу»: отражение снизу; масса изделий выровнена (--w из app.js) */
.card-obj {
  position: absolute; left: 50%; bottom: 27%; width: var(--w, 72%); translate: -50% 0;
  transform: translateY(6px) scale(.97); transition: transform 1600ms var(--ease-expo);
  -webkit-box-reflect: below 0 linear-gradient(transparent 64%, rgba(0, 0, 0, .3));
}
.collection-grid .card .card-media img { position: static; inset: auto; display: block; width: 100%; height: auto; max-width: none; object-fit: fill; transform: none; transition: none; }
.card:hover .card-obj, .card:focus-visible .card-obj { transform: translateY(-6px) scale(1.03); }
/* каустика: свет, прошедший сквозь акрил, ложится на титан кобальтом и бронзой; под кольцом — мягкая тень */
.card-halo {
  position: absolute; left: 50%; bottom: 14%; width: 92%; height: 24%; translate: -50% 0; pointer-events: none;
  background:
    radial-gradient(40% 24% at 50% 44%, rgba(4, 5, 7, .5), transparent 72%),
    radial-gradient(30% 30% at 37% 60%, rgba(79, 111, 232, .12), transparent 70%),
    radial-gradient(26% 28% at 65% 56%, rgba(185, 138, 85, .1), transparent 70%),
    radial-gradient(60% 50% at 50% 50%, rgba(232, 228, 220, .04), transparent 72%);
  opacity: .85; transform: scaleX(.94); transition: opacity 1200ms var(--ease-quart), transform 1600ms var(--ease-expo);
}
.card:hover .card-halo, .card:focus-visible .card-halo { opacity: 1; transform: scaleX(1.06); }
/* блик-развёртка по акрилу: маскирована силуэтом кольца, без прямоугольника */
.card-glint {
  position: absolute; inset: 0; pointer-events: none; opacity: 0;
  -webkit-mask-size: 100% 100%; mask-size: 100% 100%; -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  background: linear-gradient(105deg, transparent 40%, rgba(214, 226, 255, .22) 46%, rgba(255, 255, 255, .5) 50%, rgba(255, 236, 214, .22) 54%, transparent 60%) 100% 0 / 300% 100% no-repeat;
  transition: background-position 0s 1.4s, opacity 400ms var(--ease-quart);
}
.card:hover .card-glint, .card:focus-visible .card-glint { opacity: 1; background-position: 0 0; transition: background-position 1400ms var(--ease-io), opacity 200ms; }
/* «Создать своё» — капля жидкого стекла */
.collection-grid .card-cta {
  left: 50%; bottom: 4%; translate: -50% 0; white-space: nowrap; color: #ece9e3;
  background: linear-gradient(180deg, rgba(255, 255, 255, .16), rgba(255, 255, 255, .045) 55%, rgba(255, 255, 255, .09));
  border: 1px solid rgba(255, 255, 255, .14);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .28), inset 0 -1px 0 rgba(0, 0, 0, .25), 0 12px 30px -14px rgba(0, 0, 0, .7);
}
.card-meta { border-top: 1px solid transparent; border-image: linear-gradient(90deg, rgba(232, 228, 220, .18), rgba(232, 228, 220, .04) 80%, transparent) 1; }
/* если вырезки нет — стилизованное фото с растворёнными краями */
.collection-grid .card-photo .card-obj { width: 100%; bottom: 0; -webkit-box-reflect: none; }
.collection-grid .card-photo .card-media img {
  -webkit-mask-image: radial-gradient(closest-side, #000 55%, transparent); mask-image: radial-gradient(closest-side, #000 55%, transparent);
}
.card-photo .card-glint, .card-photo .card-halo { display: none; }

/* ---------- конструктор: сцена и панель растворяются в общем поле, снизу титан «стекает» ---------- */
#viewer, #viewer-snapshot {
  -webkit-mask-image: linear-gradient(180deg, transparent, rgba(0, 0, 0, .45) 4%, #000 11%, #000 80%, rgba(0, 0, 0, .78) 87%, rgba(0, 0, 0, .38) 94%, transparent);
  mask-image: linear-gradient(180deg, transparent, rgba(0, 0, 0, .45) 4%, #000 11%, #000 80%, rgba(0, 0, 0, .78) 87%, rgba(0, 0, 0, .38) 94%, transparent);
}
.configurator .panel { isolation: isolate; background: none; border: 0; box-shadow: none; }
/* подложка панели — тёмное стекло: растворяется вверху и стекает ниже раздела */
.configurator .panel::before {
  content: ''; position: absolute; left: 0; right: 0; top: 0; bottom: -22vh; z-index: -1; pointer-events: none;
  background: linear-gradient(180deg, rgba(31, 33, 38, .8), rgba(22, 24, 28, .74) 55%, rgba(18, 21, 25, .66));
  box-shadow: inset 1px 0 0 rgba(232, 228, 220, .1), inset 2px 0 0 rgba(255, 255, 255, .025);
  -webkit-mask-image: linear-gradient(180deg, transparent, rgba(0, 0, 0, .25) 4%, rgba(0, 0, 0, .62) 9%, rgba(0, 0, 0, .9) 14%, #000 19%, #000 64%, rgba(0, 0, 0, .6) 76%, rgba(0, 0, 0, .22) 88%, transparent);
  mask-image: linear-gradient(180deg, transparent, rgba(0, 0, 0, .25) 4%, rgba(0, 0, 0, .62) 9%, rgba(0, 0, 0, .9) 14%, #000 19%, #000 64%, rgba(0, 0, 0, .6) 76%, rgba(0, 0, 0, .22) 88%, transparent);
}
.configurator .panel-foot { background: none; border-top: 1px solid transparent; border-image: linear-gradient(90deg, transparent, rgba(232, 228, 220, .12) 20%, rgba(232, 228, 220, .12) 80%, transparent) 1; }

/* ---------- без нумерации разделов (2.8.2): шапка раздела — заголовок и лид, без колонки номера; раздела «Материал»
   больше нет — коротко о материале в «Приручении прозрачности»: лид в шапке и строка характеристик под шагами ---------- */
.section-head { grid-template-columns: minmax(0, 1fr) minmax(0, 420px); }
.process .section-head { grid-template-columns: minmax(0, 1fr) minmax(0, 420px); }
.section-lead { text-wrap: pretty; }
.steps h3 { margin-top: 6px; }
.process .specs-row {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 22px 28px;
  margin: clamp(40px, 5vw, 64px) 0 0; padding: 22px clamp(20px, 3vw, 44px) 0; /* поля — как у плиты шагов: колонки на одной линии */
  border-top: 1px solid transparent; border-image: linear-gradient(90deg, rgba(232, 228, 220, .16), rgba(232, 228, 220, .05) 80%, transparent) 1;
}
.process .specs-row div, .process .specs-row div:last-child { display: block; padding: 0; border: 0; }
.process .specs-row dt { margin-bottom: 10px; color: var(--muted); }
.process .specs-row dd { text-align: left; font-size: 19px; line-height: 1.2; color: #e2dfd9; text-wrap: balance; }
@media (max-width: 1100px) { .process .specs-row { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 860px) {
  .section-head, .process .section-head { grid-template-columns: minmax(0, 1fr); }
  .process .specs-row { grid-template-columns: repeat(2, minmax(0, 1fr)); padding-inline: 22px; }
}
/* узкий телефон: «СВЕТОПРОПУСКАНИЕ» капителью (≈150 px) не помещается в половину строки — характеристики списком,
   подпись слева, значение справа по одной базовой линии, между строками волосяная линия */
@media (max-width: 440px) {
  .process .specs-row { grid-template-columns: minmax(0, 1fr); gap: 0; padding-top: 8px; }
  .process .specs-row div, .process .specs-row div:last-child { display: flex; justify-content: space-between; align-items: baseline; gap: 16px; padding: 13px 0; }
  .process .specs-row div:not(:first-child) { border-top: 1px solid var(--line); }
  .process .specs-row dt { margin: 0; }
  .process .specs-row dd { text-align: right; }
}

/* ---------- как рождается кольцо: мягче по контрасту, шаги — на плите жидкого стекла ---------- */
.process .h2 { color: #d9d6cf; }
.process .h2 em {
  background: linear-gradient(100deg, #b9b5ad 0%, #ece9e3 28%, #a6a29b 46%, #f1eee9 62%, #bdb9b1 80%, #d9d6cf 100%) 100% 0 / 240% 100%;
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
.js-motion .process .reveal-lines.in em { animation: ti-sheen 2800ms var(--ease-io) 500ms both; }
@keyframes ti-sheen { from { background-position: 100% 0; } to { background-position: 0 0; } }
.steps {
  position: relative; border-top: 0; border-radius: 28px; padding: 6px clamp(20px, 3vw, 44px) 2px;
  background: linear-gradient(165deg, rgba(232, 228, 220, .06), rgba(232, 228, 220, .018) 42%, rgba(232, 228, 220, .04));
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), inset 0 -1px 0 rgba(0, 0, 0, .28), inset 0 0 0 1px rgba(232, 228, 220, .07);
}
/* десктоп с плавной прокруткой: преломление, блик и тень плиты рисует шейдер; DOM — только кант */
html.ambient-glass .steps { background: linear-gradient(165deg, rgba(232, 228, 220, .028), transparent 42%, rgba(232, 228, 220, .018)); }
.steps li { position: relative; overflow: hidden; border-right-color: transparent; border-image: linear-gradient(180deg, transparent 8%, rgba(232, 228, 220, .13) 35%, rgba(232, 228, 220, .13) 70%, transparent 95%) 1; }
.steps h3 { color: #e2dfd9; }
.steps p { color: #9d9b96; }
.steps li::after { /* проход света сквозь стекло при появлении */
  content: ''; position: absolute; top: 0; bottom: 0; left: -20%; width: 140%; pointer-events: none; opacity: 0; transform: translateX(-100%);
  background: linear-gradient(100deg, transparent 36%, rgba(159, 180, 245, .08) 45%, rgba(255, 255, 255, .13) 50%, rgba(232, 200, 160, .07) 55%, transparent 64%);
}
/* появление: плита собирается из капли (та же кривая и длительность, что у шейдера), шаги — из-за стекла */
.js-motion .steps { opacity: 0; clip-path: inset(35% 20% 35% 20% round 200px); transition: clip-path 1700ms var(--ease-expo), opacity 700ms var(--ease-quart); }
.js-motion .steps.in { opacity: 1; clip-path: inset(0 0 0 0 round 28px); }
.js-motion .steps li { opacity: 0; filter: blur(12px); transform: translateY(24px) scale(.985); transition: opacity 1000ms var(--ease-quart), filter 1300ms var(--ease-expo), transform 1500ms var(--ease-expo); transition-delay: calc(420ms + var(--i, 0) * 150ms); }
.js-motion .steps.in li { opacity: 1; filter: none; transform: none; }
.js-motion .steps.in li::after { animation: step-sweep 1700ms var(--ease-io) calc(700ms + var(--i, 0) * 150ms) both; }
@keyframes step-sweep { 0% { opacity: 0; transform: translateX(-100%); } 25% { opacity: 1; } 100% { opacity: 0; transform: translateX(100%); } }

/* подвал: вместо рамки — тающая линия */
.footer { position: relative; }
.footer::before { content: ''; position: absolute; top: 0; left: 18%; right: 18%; height: 1px; background: linear-gradient(90deg, transparent, rgba(232, 228, 220, .12), transparent); }

@media (max-width: 1100px) {
  .steps li:nth-child(2) { border-image: none; }
}
@media (max-width: 860px) {
  .collection::before { height: min(56vh, 520px); }
  .card-obj { bottom: 28%; }
  /* панель на телефоне закрывает «прилипшую» сцену — стекло плотнее; низ панели стекает в «Материал» */
  .configurator .panel::before {
    background: linear-gradient(180deg, rgba(16, 18, 21, .95), rgba(14, 16, 19, .94));
    box-shadow: none; bottom: -14vh;
    -webkit-mask-image: linear-gradient(180deg, transparent, #000 40px, #000 calc(100% - 22vh), transparent);
    mask-image: linear-gradient(180deg, transparent, #000 40px, #000 calc(100% - 22vh), transparent);
  }
  .configurator .panel { border-top: 0; }
  .configurator .panel-foot { background: rgba(15, 17, 20, .94); border-image: none; border-top: 1px solid var(--line); }
  /* у конца раздела низ «прилипшего» подвала панели не обрывается, а стекает в поле */
  .configurator .panel-foot::after {
    content: ''; position: absolute; left: 0; right: 0; top: 100%; height: 120px; pointer-events: none;
    background: linear-gradient(180deg, rgba(15, 17, 20, .94), rgba(15, 17, 20, .62) 30%, rgba(15, 17, 20, .26) 62%, rgba(15, 17, 20, 0));
  }
  #viewer, #viewer-snapshot {
    -webkit-mask-image: linear-gradient(180deg, transparent, rgba(0, 0, 0, .5) 5%, #000 13%, #000 84%, rgba(0, 0, 0, .55) 93%, transparent);
    mask-image: linear-gradient(180deg, transparent, rgba(0, 0, 0, .5) 5%, #000 13%, #000 84%, rgba(0, 0, 0, .55) 93%, transparent);
  }
  .steps { border-radius: 22px; padding: 4px 22px 0; }
  .js-motion .steps { clip-path: inset(30% 12% 30% 12% round 160px); }
  .js-motion .steps.in { clip-path: inset(0 0 0 0 round 22px); }
}
@media (max-width: 560px) {
  .steps li { border-image: none; }
  .steps li + li, .steps li:nth-child(2) { border-top: 1px solid transparent; border-image: linear-gradient(90deg, transparent, rgba(232, 228, 220, .12) 20%, rgba(232, 228, 220, .12) 80%, transparent) 1; }
  .card-obj { bottom: 26%; }
}
@media (prefers-reduced-motion: reduce) {
  .mat-light { display: none; }
}

/* =====================================================================
   ЛУЧИ (2.7) — docs/research-hero-light.md
   Hero «Свет на титане»: холст #hero-light (js/ambient.js) лежит в сцене между плитой и кольцом — лучи
   ключевого света слева сверху и тихие отражения полированного титана; кольцо сверху не тронуто.
   Интро — одна история света: свет проходит по имени → экран загрузки растворяется в засвеченном кадре →
   засветка собирается в веер лучей, кадр проявляется от дальнего угла → один блик по титану пола и по кольцу.
   ===================================================================== */
.hero-light { position: absolute; inset: 0; display: block; width: 100%; height: 100%; pointer-events: none; opacity: 0; transition: opacity 1400ms var(--ease-quart); }
.hero-light.on { opacity: 1; transition: none; }   /* готов до снятия экрана загрузки — проявление ведёт сам холст */
.hero-light.on-late { opacity: 1; }                 /* опоздал — просто проявляется в покое */

/* экран загрузки: короче растворение (под ним кадр того же цвета), по имени и линии проходит свет —
   lighten с серым титаном не меняет светлый фон, а только поднимает тёмные буквы */
.loader { --sw: calc(clamp(28px, 4vw, 44px) * 5.4 + 170px); transition: opacity 700ms var(--ease-io) 60ms, visibility 0s 760ms; }
.loader::after {
  content: ''; position: absolute; left: 50%; top: 50%; width: 260px; height: 200px; margin: -114px 0 0 -130px; pointer-events: none;
  mix-blend-mode: lighten; translate: calc(var(--sw) * -1) 0;
  background: linear-gradient(100deg, transparent 20%, rgba(98, 99, 103, .5) 38%, rgba(172, 169, 162, .92) 50%, rgba(98, 99, 103, .5) 62%, transparent 80%);
}
.loader.shine::after { translate: var(--sw) 0; transition: translate 1150ms var(--ease-io); }

/* сцена проявляется вместе со светом: пол уходит в титан, кольцо появляется из засветки, блик — синхронно с бликом на полу */
.js-motion .hero-fade { opacity: 0; transition: opacity 1500ms var(--ease-io) 300ms; }
.js-motion .hero.in .hero-fade { opacity: 1; }
.js-motion .hero-ring img { transition: opacity 1500ms var(--ease-quart) 350ms, scale 2300ms var(--ease-expo) 350ms; }
.js-motion .hero.in .hero-glint i { animation: hero-glint 1600ms var(--ease-io) 1160ms both; }
/* P/T: светлые кнопки стоят на полу — появляются, когда пол уже проявился из засветки (контраст с первого кадра) */
@media not all and (min-aspect-ratio: 1/1) { .js-motion .hero .hero-actions.reveal-up { transition-delay: 1250ms; } }
@media (prefers-reduced-motion: reduce) {
  .loader::after { display: none; }
}
/* «Призма» (2.9, docs/research-hero-rays.md): блик по кольцу разложен как свет в призме — тёплый передний край,
   холодный задний (screen ×.5 — на стекле это лёгкий перелив, не радуга); остальной свет — в холсте #hero-light */
.hero-glint i { background: linear-gradient(100deg, transparent 22%, rgba(255, 228, 208, .42) 40%, rgba(255, 255, 255, .85) 50%, rgba(210, 228, 255, .42) 60%, transparent 78%); }

/* =====================================================================
   ТЕЛЕФОН: МОДЕЛЬ ВСЕГДА НАД ПОЛЗУНКАМИ (2.7.2)
   Сцена «прилипает» к верху экрана и лежит поверх панели: параметры прокручиваются под ней, кольцо видно
   всё время, пока двигаешь ползунок. Прилипшая сцена (.stuck — js/app.js) получает плотный фон, снизу —
   тень, под которую уходят параметры. Подвал панели — компактная строка «цена + заказ».
   ===================================================================== */
@media (max-width: 860px) {
  .stage { height: 46svh; z-index: 3; transition: background-color 250ms; }
  .stage.stuck { background: rgb(15, 17, 20); box-shadow: 0 1px 0 rgba(232, 228, 220, .07), 0 16px 22px -10px rgba(0, 0, 0, .75); }
  .configurator .panel { z-index: 1; }
  .stage-bottom { bottom: 12px; }
  .quick { bottom: 62px; }
  .stage.hint-seen .stage-hint { opacity: 0; }
  .configurator .panel-foot {
    display: grid; grid-template-columns: auto 1fr; align-items: center; column-gap: 18px;
    padding: 10px var(--pad) calc(10px + env(safe-area-inset-bottom));
  }
  .configurator .panel-foot .price-row { flex-direction: column; align-items: flex-start; gap: 2px; }
  .configurator .panel-foot .price { font-size: 26px; line-height: 1; }
  .configurator .panel-foot .btn { padding-inline: 16px; white-space: nowrap; }
  .configurator .panel-foot .spec, .configurator .panel-foot .foot-contact { display: none; }
}
/* 320–380 px: «ОРИЕНТИРОВОЧНО» и «ОФОРМИТЬ ЗАКАЗ» в одной строке — капитель плотнее, иначе надпись кнопки обрезается */
@media (max-width: 380px) {
  .configurator .panel-foot { column-gap: 12px; }
  .configurator .panel-foot .eyebrow, .configurator .panel-foot .btn { font-size: 10.5px; letter-spacing: .08em; }
  .configurator .panel-foot .btn { padding-inline: 12px; }
}

/* =====================================================================
   СЕНСОРНЫЕ ЭКРАНЫ И ТЕЛЕФОН (2.7.3)
   Ползунок ведётся пальцем по всей строке параметра (js/app.js → touchRange): горизонтальный жест — значение,
   вертикальный — прокрутка. Бегунок крупнее и «светится», пока его ведут. На телефоне над моделью нет надписей:
   номер раздела и статус сборки скрыты (о сборке говорит полоса прогресса), подсказка — в панели под заголовком.
   ===================================================================== */
@media (pointer: coarse) {
  .slider, .quick { touch-action: pan-y; -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; -webkit-tap-highlight-color: transparent; }
  .slider input[type="range"], .quick input[type="range"] { pointer-events: none; }
  input[type="range"]::-webkit-slider-thumb { width: 20px; height: 20px; margin-top: -9.5px; }
  input[type="range"]::-moz-range-thumb { width: 20px; height: 20px; }
  .slider.dragging input[type="range"]::-webkit-slider-thumb, .quick.dragging input[type="range"]::-webkit-slider-thumb {
    transform: scale(1.3); box-shadow: 0 0 0 1px rgba(0, 0, 0, .45), 0 0 0 9px rgba(79, 111, 232, .16), 0 0 18px rgba(79, 111, 232, .35);
  }
  .slider.dragging .slider-head label { color: var(--text); }
}
.panel-tip { display: none; margin: 14px 0 0; font: 400 13px/1.55 var(--sans); color: var(--muted); text-wrap: pretty; }
@media (max-width: 860px) {
  .stage-top { opacity: 0; pointer-events: none; }
  .stage-hint { display: none; }
  .panel-tip { display: block; }
  /* окно с моделью на 30 % выше (46 → 60 % экрана); кнопок над моделью нет: прокручивание — броском пальца,
     остановка — касанием (js/scene.js), свет и исходный ракурс — только на компьютере */
  .stage { height: 60svh; }
  .stage-tools { display: none; }
  .stage-bottom { bottom: 14px; }
  .quick { bottom: 40px; }
}

/* Страховка от горизонтального переполнения (2.8): ничто не делает страницу шире экрана — на iPhone её иначе можно
   отдалить так, что интерфейс становится уже окна. clip (а не hidden) не создаёт контейнер прокрутки, поэтому
   «прилипшая» сцена конструктора работает как прежде. */
main, .footer { overflow-x: clip; }

/* =====================================================================
   ВОЛНА 2.20 (до того: «Осколки» 2.14–2.19.1, «Стеклянные столбцы» 2.11–2.13) — js/ambient.js
   Первое намерение вниз на hero запускает переход целиком: лист жидкого стекла с мягкой волнистой кромкой несёт
   «Коллекцию» вверх над неподвижным hero (пружина ≈ 1,2 с, лёгкий перелёт); вверх с верха «Коллекции» — обратно.
   Стекло рисует холст #ambient — выше кромки он прозрачен, поэтому hero опущен под него: main — свой контекст
   наложения, в нём hero (−2) → холст (−1) → разделы. Именно main, а не корень: отрицательный z-index в корневом
   контексте оказался бы под блоками main/body, и они перехватывали бы нажатия на кнопки hero (у холста
   pointer-events: none). Всё, что должно быть над страницей (шапка, зерно, тост, экран загрузки), лежит вне main.
   Без WebGL класса .ambient-sheet нет: hero сверху, стык прежний. .glass-fly — волна включена (есть WebGL и стекло)
   ===================================================================== */
html.ambient-sheet main { position: relative; z-index: 0; }
html.ambient-sheet .hero { z-index: -2; }
/* слои затемнения пола сходятся на дробном пикселе (20svh = 168,8 px) — на стыке просвечивала светлая линия:
   сплошной слой заходит под градиент на 1 px (низ градиента уже #121519) */
.hero-fade { background-position: 0 0, 0 calc(var(--fl) - 1px); }
/* поле видно прямо от кромки: заливка #121519 сверху коллекции (под прежний стык «в цвет») не нужна */
html.ambient-sheet .collection::before { display: none; }
/* вуали пола (2.10–2.12) не используются: пол hero сам уходит в цвет страницы */
.hero-veil, .hero-veil-low { display: none; }
/* шапка: зона тона (.on-light, js/app.js) — весь hero. Прилипший hero IntersectionObserver не отпустит, поэтому в
   полёте тон ведёт js/ambient.js по поясу стекла под средней строкой шапки (зона сжимается в 0 — шапка темнеет) */
html.ambient-sheet .hero-tone { height: 100%; }
/* .nav-sheet — пока видна волна: подложка плотнее, БЕЗ backdrop-filter (под шапкой каждый кадр меняется холст —
   размытие пересчитывалось бы в каждом кадре): заранее тонированное «стекло», градиент и тонкая световая кромка */
html.ambient-sheet .nav.nav-sheet { transition: color 160ms var(--ease-quart), background-color 160ms var(--ease-quart), border-color 160ms, transform 600ms var(--ease-expo), opacity 900ms var(--ease-quart) 500ms; }
html.ambient-sheet .nav.nav-sheet.is-scrolled { background-color: transparent; border-color: transparent; backdrop-filter: none; -webkit-backdrop-filter: none; }
html.ambient-sheet .nav.nav-sheet::before {
  content: ''; position: absolute; left: 0; right: 0; top: 0; height: calc(100% + 24px); z-index: -1; pointer-events: none;
  background: linear-gradient(180deg, rgba(8, 9, 11, .86), rgba(8, 9, 11, .6));
  -webkit-mask-image: linear-gradient(180deg, #000 calc(100% - 34px), transparent); mask-image: linear-gradient(180deg, #000 calc(100% - 34px), transparent);
  opacity: 0; transition: opacity 160ms var(--ease-quart);
}
html.ambient-sheet .nav.nav-sheet.is-scrolled::before { opacity: 1; }
html.ambient-sheet .nav.nav-sheet.on-light::before { background: linear-gradient(180deg, rgba(246, 246, 245, .8), rgba(246, 246, 245, .62)); }
@media (min-aspect-ratio: 1/1) {
  /* подсказка «Scroll» привязана к низу hero; в первые 20 % пути она уходит вниз за его край */
  html.ambient-sheet.js-motion .hero-foot { translate: 0 calc(min(var(--p) * 5, 1) * 80px); }
}
/* Текст hero по группам (--tt, --tx, --tp пишет js/ambient.js; в 2.20 — всегда 1: волна просто накрывает hero).
   Гаснут фильтром: opacity этих элементов занята интро (.reveal-up, буквы заголовка) */
html.ambient-sheet .hero-copy { opacity: 1; }   /* блок целиком не гаснет (базовое 1 − 2,2·--p) */
html.ambient-sheet .hero-copy > .eyebrow, html.ambient-sheet .hero-title { filter: opacity(var(--tt, 1)); }
html.ambient-sheet .hero-actions { filter: opacity(var(--tx, 1)); }
html.ambient-sheet .hero-text, html.ambient-sheet .hero-lede { filter: opacity(var(--tp, 1)); }
/* 2.12e (docs/audit-transition-smoothness.md, п. 1): значения прокрутки — не наследуемые: js пишет их прямо на
   элементы, которые их читают (пересчёт стиля всего hero в каждом кадре — 1,4–1,5 мс на ПК, на телефоне в 4–6 раз дольше) */
@property --p { syntax: '<number>'; inherits: false; initial-value: 0; }
@property --tt { syntax: '<number>'; inherits: false; initial-value: 1; }
@property --tx { syntax: '<number>'; inherits: false; initial-value: 1; }
@property --tp { syntax: '<number>'; inherits: false; initial-value: 1; }
/* переход по якорю (js/motion.js) отдаёт фокус разделу-цели — без рамки вокруг всего раздела */
main > section[tabindex="-1"]:focus { outline: none; }
/* hero — неподвижная первая страница: без параллакса сцены и сдвига текста; пока волна на hero или в полёте, он
   прилип (.is-stuck — класс на самом hero, не на корне: смена не пересчитывает стиль всей страницы; sticky держит
   компоновщик — без дрожи и на нативной прокрутке телефона; hero выше окна — сначала доезжает его низ) */
html.glass-fly .hero-media { transform: none; }
html.glass-fly .hero-ring { scale: none; }
html.glass-fly .hero-copy { translate: none; }
.hero.is-stuck { position: sticky; top: var(--hero-stick, 0px); }
/* QA 4: hero — замкнутое поддерево (всё внутри и так обрезано overflow: hidden): смена классов и переменных в нём не
   пересчитывает стиль и раскладку остальной страницы, и наоборот */
html.glass-fly .hero { contain: layout style paint; }
/* «Коллекцию» приносит волна — без своего появления (.reveal-*, .card): она уже целиком на листе */
html.glass-fly #collection .reveal-up, html.glass-fly #collection .card { opacity: 1; transform: none; transition: none; }
html.glass-fly #collection .reveal-lines .line > span { transform: none; transition: none; }
/* QA v3: экран загрузки прятал полосу прокрутки (body.is-loading { overflow: hidden } уходит на окно); при его снятии
   окно сужалось на её ширину и весь первый экран сдвигался (CLS). Теперь полоса на месте с первого кадра (пустая),
   а прокрутку держит сам body высотой в окно (scrollbar-gutter у корня Chrome при overflow: hidden не соблюдал).
   Без :has — как прежде */
html:has(> body.is-loading) { overflow-y: scroll; }
html body.is-loading { height: 100vh; overflow: hidden; }
/* без WebGL у конструктора нет 3D-сцены (js/app.js): на её месте — спокойная подпись по центру сцены */
.stage-nogl {
  position: absolute; left: 50%; top: 50%; translate: -50% -50%; width: min(34ch, calc(100% - 48px)); margin: 0;
  text-align: center; color: var(--text-2); font-size: .9375rem; line-height: 1.6; pointer-events: none;
}
/* без WebGL на стыке — тихая световая линия */
html.no-ambient .hero + .collection::after {
  content: ''; position: absolute; left: 0; right: 0; top: 0; height: 1px; pointer-events: none;
  background: linear-gradient(90deg, transparent, rgba(236, 240, 246, .2) 26%, rgba(236, 240, 246, .05) 64%, transparent);
}

/* =====================================================================
   2.12 КОМФОРТНАЯ ПОСАДКА — docs/audit-comfort-fit.md
   Своя секция панели сразу за «Формой» (js/app.js → accFit). По просьбе владельца (2.13) в ней только ползунок —
   такой же, как у остальных параметров (подпись, значение, подсказка); без строки о пользе и сечения шинки
   ===================================================================== */
.acc-fit .note:empty { display: none; }
/* «Форма» — только выбор верха (детали — своей секцией): без пустого поля под ним */
.acc-content > .tops:last-child { margin-bottom: 0; }
/* цели нажатия ≥ 44 px без изменения рисунка: прозрачная зона касания вокруг (QA 2.12) — закрыть всплывающий ползунок
   (36 px), образцы цвета (30 px, кольцо выбора 42 px), переключатель «Соединить грани» (строка 35 px) */
.quick-close::before { content: ''; position: absolute; inset: -4px; }
.swatch::before { content: ''; position: absolute; inset: -7px; border-radius: 50%; }
.toggle-btn { position: relative; }
.toggle-btn::before { content: ''; position: absolute; left: 0; right: 0; top: -5px; bottom: -5px; }

/* =====================================================================
   2.13 ПО РЕВЬЮ АУДИТОРИИ (docs/review-212, panel-01…05): цена и «Сделать своим» в карточке коллекции, цвет на виду,
   доплата отделки на кнопке, подписанные габариты. Тихие кнопки и выбранные состояния — в блоке «ТИТАН» выше
   ===================================================================== */
/* карточка: под именем — цена «от» (та же, что покажет конструктор, открыв работу). Без наведения (телефон, планшет)
   кнопка на фото не появляется — «Сделать своим» стоит строкой справа от цены, с волосяной линией, как ссылка */
.card-buy { flex: 1 0 100%; display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.card-from { font: 400 14px/1.3 var(--sans); letter-spacing: .02em; color: var(--text-2); font-variant-numeric: lining-nums tabular-nums; white-space: nowrap; }
.card-go { display: none; }
@media (hover: none) {
  .collection-grid .card-cta { display: none; }
  .card-go {
    display: inline-block; margin-left: auto; padding: 6px 0 5px; white-space: nowrap; color: var(--text);
    font: var(--caps-weight) 11px/1 var(--sans); letter-spacing: var(--caps-track); text-transform: uppercase;
    background: linear-gradient(currentColor, currentColor) 0 100% / 100% 1px no-repeat;
  }
}
/* цвет — строка сразу под «Формой» высотой с заголовок секции: подпись и выбранный цвет слева, образцы справа.
   Узкая панель компьютера (861–1100 px, 296 px под содержимое) — образцы второй строкой, имя цвета не обрезается */
.color-row { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 12px; min-height: 57px; padding: 10px 0; border-top: 1px solid var(--line); }
.color-row .acc-title { flex: none; }
.color-name { flex: 1 1 auto; min-width: 0; font-size: 12.5px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.color-row .swatches { flex: none; flex-wrap: nowrap; gap: 10px; margin: 0; }
.color-row .swatch { width: 28px; height: 28px; }
@media (max-width: 400px) {
  .color-row { gap: 10px; }
  .color-row .swatches { gap: 8px; }
  .color-row .swatch { width: 26px; height: 26px; }
}
/* фокус с клавиатуры отличается от выбора: кольцо 2 px приглушённого кобальта (выбор — 1 px цвета текста) */
.top-choice:focus-visible, .pill:focus-visible { outline-width: 2px; }
.swatch:focus-visible { outline: 2px solid var(--ice); outline-offset: 4px; }
/* доплата отделки — тише названия, вместе с ним не рвётся */
.pill-price { color: var(--muted); white-space: nowrap; transition: color var(--d-hover); }
.pill:hover .pill-price, .pill[aria-checked="true"] .pill-price { color: var(--text-2); }
/* габариты под моделью: «Ш × В × Г» — тоньше значений */
.dims-key { font-weight: 400; letter-spacing: .04em; }
/* фокус кнопки на светлом hero (W/S) — тёмный кобальт, как у остальных ссылок hero */
@media (min-aspect-ratio: 1/1) { .hero .btn:focus-visible { outline-color: #3550c8; } }

/* =====================================================================
   ЗАКАЗ И СЕРВИС (config.js → service)
   Строка фактов под шагами «Приручения» — тем же языком, что характеристики материала: подпись капителью,
   значение антиквой, пояснение гротеском. «Доставка» с длинным пояснением занимает две колонки сетки (на 2 колонки —
   всю строку, «Изготовление» и «Полировка» встают рядом над ней). Плюс тихая строка у кнопки заказа и строка в окне заказа.
   ===================================================================== */
.process .service-row + .specs-row { margin-top: clamp(28px, 3.5vw, 44px); }
.process .service-row > div:nth-child(2) { grid-column: span 2; }
.process .spec-note { display: block; margin-top: 8px; font: 400 13px/1.45 var(--sans); color: var(--muted); text-wrap: balance; }
@media (max-width: 1100px) { .process .service-row { grid-auto-flow: row dense; } }
/* телефон: список «подпись — значение»; подпись не сжимается, пояснение переносится под значением */
@media (max-width: 440px) {
  .process .service-row > div:nth-child(2) { grid-column: auto; }
  .process .service-row dt { flex: none; }
  .process .spec-note { margin-top: 6px; }
}
.service-line { margin: 12px 0 0; font-size: 12px; line-height: 1.55; color: var(--muted); text-align: center; text-wrap: balance; }
@media (max-width: 860px) {
  .configurator .panel-foot .service-line { grid-column: 1 / -1; margin: 8px 0 0; font-size: 11.5px; line-height: 1.45; }
}
/* телефон: закреплённая панель с ценой не растёт (+40 px отняли бы у сцены) — условия есть в «Приручении» и в окне заказа */
@media (max-width: 600px) { .configurator .panel-foot .service-line { display: none; } }
/* окно заказа: строка «что дальше» — последней строкой блока сводки, над его нижней линией */
.order-recap:has(+ .order-next:not([hidden])) { border-bottom: 0; padding-bottom: 8px; }
.order-next { margin: -18px 0 0; padding: 0 0 14px; border-bottom: 1px solid var(--line); font-size: 12.5px; line-height: 1.6; color: var(--muted); text-wrap: pretty; }

/* =====================================================================
   «КАЖДАЯ ГРАНЬ» (2.15): секция панели и соседние параметры во всплывающем ползунке грани
   Вкладки граней — те же пилюли, что у отделки, ниже и плотнее; точка у вкладки — в ней есть настройки. Под ползунками —
   тихая ссылка «Вернуть исходные грани». Во всплывающем ползунке — строка мелких пилюль: свой параметр грани и общие
   рядом. Зоны касания добраны прозрачными полями до ≈ 44 px
   ===================================================================== */
.face-tabs { gap: 6px; margin: 2px 0 18px; }
.face-tabs .pill { position: relative; padding: 8px 14px; font-size: 13px; }
.face-tabs .pill[hidden] { display: none; }
.face-tabs .pill::before { content: ''; position: absolute; inset: -6px -3px; }
.face-tabs .pill[data-set="true"]::after {
  content: ''; position: absolute; top: 5px; right: 6px; width: 4px; height: 4px; border-radius: 50%; background: rgba(159, 180, 245, .9);
}
.face-reset {
  position: relative; display: block; margin: 16px 0 0; padding: 4px 0; background: none; border: 0; font: inherit; font-size: 12.5px;
  color: var(--muted); text-decoration: underline; text-decoration-color: var(--line-2); text-underline-offset: 3px; cursor: pointer;
  transition: color var(--d-hover);
}
.face-reset::before { content: ''; position: absolute; inset: -10px -4px; }
.face-reset:hover { color: var(--text-2); text-decoration-color: currentColor; }
.face-reset[hidden] { display: none; }
.quick-alt { display: flex; flex-wrap: wrap; gap: 6px; margin: -4px 0 12px; }
.quick-alt[hidden] { display: none; }
.quick-chip {
  position: relative; padding: 6px 11px; border-radius: 999px; background: transparent; border: 1px solid var(--line-2);
  color: var(--text-2); font: inherit; font-size: 12.5px; line-height: 1.2; cursor: pointer; white-space: nowrap;
}
.quick-chip::before { content: ''; position: absolute; inset: -7px -3px; }
.quick-chip[aria-pressed="true"] { color: var(--text); border-color: currentColor; background: rgba(232, 228, 220, .045); }
.quick-chip:focus-visible { outline: 2px solid var(--ice); outline-offset: 2px; }
/* недоступный ползунок с объяснением (config.js → idle): приглушены подпись и дорожка, подсказка читается */
.slider.disabled.idle { opacity: 1; }
.slider.idle .slider-head, .slider.idle input[type="range"] { opacity: .35; }
.slider-hint[hidden] { display: none; }

/* =====================================================================
   2.15.1 ПЕРВЫЙ ЭКРАН БЕЗ ЧЁРНОГО ПРОВАЛА
   Фон hero тёмный (#121519 — низ кадра), светлую студийную стену даёт фото плиты. На медленном мобильном интернете экран
   загрузки снимается по таймеру раньше, чем фото пришло, — и первый экран был почти чёрным (тёмный текст на тёмном).
   Теперь на месте плиты сразу её крошечная копия (≈ 600 байт, браузер растягивает — мягко размыта), настоящий кадр
   ложится сверху (опоздавший — мягко проявляется, js/app.js → .ready). Раскладки — как у <source> плиты в index.html:
   W ≥ 7/5, S ≥ 1/1, P ≥ 13/20, иначе T
   ===================================================================== */
/* 2.16: знак PLEXIFORM — одно слово, между PLEXI и FORM еле заметный зазор (чуть шире разрядки букв);
   js/app.js → brand.wordmark, экран загрузки — в разметке */
.wm-gap { display: inline-block; width: .16em; }
.loader-mark .wm-gap { animation: none; opacity: 1; transform: none; filter: none; }
.js-motion .hero-plate img { opacity: 0; transition: opacity 700ms var(--ease-quart); }
.js-motion .hero-plate img.ready { opacity: 1; }
.hero-plate { background: #d6d6d4 center / 100% 100% no-repeat; background-image: url("data:image/webp;base64,UklGRlACAABXRUJQVlA4WAoAAAAgAAAALwAAGgAASUNDUMgBAAAAAAHIAAAAAAQwAABtbnRyUkdCIFhZWiAH4AABAAEAAAAAAABhY3NwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA9tYAAQAAAADTLQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlkZXNjAAAA8AAAACRyWFlaAAABFAAAABRnWFlaAAABKAAAABRiWFlaAAABPAAAABR3dHB0AAABUAAAABRyVFJDAAABZAAAAChnVFJDAAABZAAAAChiVFJDAAABZAAAAChjcHJ0AAABjAAAADxtbHVjAAAAAAAAAAEAAAAMZW5VUwAAAAgAAAAcAHMAUgBHAEJYWVogAAAAAAAAb6IAADj1AAADkFhZWiAAAAAAAABimQAAt4UAABjaWFlaIAAAAAAAACSgAAAPhAAAts9YWVogAAAAAAAA9tYAAQAAAADTLXBhcmEAAAAAAAQAAAACZmYAAPKnAAANWQAAE9AAAApbAAAAAAAAAABtbHVjAAAAAAAAAAEAAAAMZW5VUwAAACAAAAAcAEcAbwBvAGcAbABlACAASQBuAGMALgAgADIAMAAxADZWUDggYgAAAPAEAJ0BKjAAGwA+hTiTSCUjoaE6vMgAoBCJaQABKyS3rqznnR2Yy/hCbmuLde88IAD++nNKo8G8Wqlg/EI5Z2POVr0YzAEEw3RGmlYdgY62FSX0UFKpJRWL1rn6mUBY2AAA"); }
@media not all and (min-aspect-ratio: 7/5) { .hero-plate { background-image: url("data:image/webp;base64,UklGRkoCAABXRUJQVlA4WAoAAAAgAAAAJwAAHQAASUNDUMgBAAAAAAHIAAAAAAQwAABtbnRyUkdCIFhZWiAH4AABAAEAAAAAAABhY3NwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA9tYAAQAAAADTLQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlkZXNjAAAA8AAAACRyWFlaAAABFAAAABRnWFlaAAABKAAAABRiWFlaAAABPAAAABR3dHB0AAABUAAAABRyVFJDAAABZAAAAChnVFJDAAABZAAAAChiVFJDAAABZAAAAChjcHJ0AAABjAAAADxtbHVjAAAAAAAAAAEAAAAMZW5VUwAAAAgAAAAcAHMAUgBHAEJYWVogAAAAAAAAb6IAADj1AAADkFhZWiAAAAAAAABimQAAt4UAABjaWFlaIAAAAAAAACSgAAAPhAAAts9YWVogAAAAAAAA9tYAAQAAAADTLXBhcmEAAAAAAAQAAAACZmYAAPKnAAANWQAAE9AAAApbAAAAAAAAAABtbHVjAAAAAAAAAAEAAAAMZW5VUwAAACAAAAAcAEcAbwBvAGcAbABlACAASQBuAGMALgAgADIAMAAxADZWUDggXAAAADAFAJ0BKigAHgA+hTqUSCUjoiE6uZgAoBCJaQABFPK15MYCinkBnwZgMef4pzwLNyTgAP76Fzsfjv1970Jm2x3PaUrN4NCrhZVMbqtI/+sUkP8Zs9Hx0v6mIAAA"); } }
@media not all and (min-aspect-ratio: 1/1) { .hero-plate { background-image: url("data:image/webp;base64,UklGRkwCAABXRUJQVlA4WAoAAAAgAAAAHQAAJwAASUNDUMgBAAAAAAHIAAAAAAQwAABtbnRyUkdCIFhZWiAH4AABAAEAAAAAAABhY3NwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA9tYAAQAAAADTLQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlkZXNjAAAA8AAAACRyWFlaAAABFAAAABRnWFlaAAABKAAAABRiWFlaAAABPAAAABR3dHB0AAABUAAAABRyVFJDAAABZAAAAChnVFJDAAABZAAAAChiVFJDAAABZAAAAChjcHJ0AAABjAAAADxtbHVjAAAAAAAAAAEAAAAMZW5VUwAAAAgAAAAcAHMAUgBHAEJYWVogAAAAAAAAb6IAADj1AAADkFhZWiAAAAAAAABimQAAt4UAABjaWFlaIAAAAAAAACSgAAAPhAAAts9YWVogAAAAAAAA9tYAAQAAAADTLXBhcmEAAAAAAAQAAAACZmYAAPKnAAANWQAAE9AAAApbAAAAAAAAAABtbHVjAAAAAAAAAAEAAAAMZW5VUwAAACAAAAAcAEcAbwBvAGcAbABlACAASQBuAGMALgAgADIAMAAxADZWUDggXgAAAJAFAJ0BKh4AKAA+gTqUSCUkIiE6vMgAoBAJaQABJ6t4MEVoTrB0P8mccyGseh4gtbFDRVAAAP76Gk0JZ37ZNk3MooX8tt5dNmmN1KwO4HErCtokoYSWR5pE5dXgAAA="); } }
@media not all and (min-aspect-ratio: 13/20) { .hero-plate { background-image: url("data:image/webp;base64,UklGRlACAABXRUJQVlA4WAoAAAAgAAAAGgAALwAASUNDUMgBAAAAAAHIAAAAAAQwAABtbnRyUkdCIFhZWiAH4AABAAEAAAAAAABhY3NwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA9tYAAQAAAADTLQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlkZXNjAAAA8AAAACRyWFlaAAABFAAAABRnWFlaAAABKAAAABRiWFlaAAABPAAAABR3dHB0AAABUAAAABRyVFJDAAABZAAAAChnVFJDAAABZAAAAChiVFJDAAABZAAAAChjcHJ0AAABjAAAADxtbHVjAAAAAAAAAAEAAAAMZW5VUwAAAAgAAAAcAHMAUgBHAEJYWVogAAAAAAAAb6IAADj1AAADkFhZWiAAAAAAAABimQAAt4UAABjaWFlaIAAAAAAAACSgAAAPhAAAts9YWVogAAAAAAAA9tYAAQAAAADTLXBhcmEAAAAAAAQAAAACZmYAAPKnAAANWQAAE9AAAApbAAAAAAAAAABtbHVjAAAAAAAAAAEAAAAMZW5VUwAAACAAAAAcAEcAbwBvAGcAbABlACAASQBuAGMALgAgADIAMAAxADZWUDggYgAAAHAFAJ0BKhsAMAA+hTaVSCUjIiE6uZgAoBCJaQABFPLv2GlJZZZJBQIztxGFOBmJrlZGRQAA/vpkJTQtOqzBgVhsNiSMCEDezbGKxEmwsWc0CxxqPusTjgpl08ivPIcewAAA"); } }

/* =====================================================================
   СТЕКЛЯННЫЙ ИНТЕРФЕЙС 2.20 — владелец: «весь интерфейс делай в стеклянном стиле, с такими же бликами и засветками,
   как этот референс» (docs/ref-shards-29.jpg: яркий кристалл, серебряные блики, тонкий спектр, волосяные кромки).
   Один рецепт на шапку, кнопки, карточки, плиту шагов, панель конструктора, аккордеоны, ползунки, образцы цвета,
   окно заказа и тост:
   * тело — полупрозрачное, заранее тонированное стекло (градиент светлее сверху слева), БЕЗ backdrop-filter: под
     интерфейсом живёт 3D-сцена и холст волны — размытие пересчитывалось бы в каждом кадре (на телефоне конструктор
     и так дорог); вместо размытия — плотнее тон там, где под ним движение;
   * кромка 1 px: светлая (серебро) сверху слева, к низу справа гаснет и уходит в холодный перелив;
   * у нижней кромки — тонкий спектр (тёплый → холодный), как у кромок референса, не ярче .34;
   * блик: на компьютере мягкое пятно идёт за указателем (js/motion.js → initGlass, только transform / opacity), на
     телефоне — медленный проход света по видимым крупным стёклам; за окном и через 8 с без касаний — стоит.
   Контраст текста — прежний (тела тёмные, подписи ≥ 4,5 : 1; светлая кнопка — тёмный текст 13 : 1)
   ===================================================================== */
:root {
  --gl-body: linear-gradient(160deg, rgba(255, 255, 255, .085), rgba(255, 255, 255, .028) 36%, rgba(255, 255, 255, .012) 62%, rgba(255, 255, 255, .04));
  --gl-tint: linear-gradient(rgba(17, 19, 23, .52), rgba(17, 19, 23, .52));
  --gl-tint-dense: linear-gradient(rgba(15, 17, 20, .86), rgba(15, 17, 20, .86));
  --gl-edge: linear-gradient(135deg, rgba(255, 255, 255, .5), rgba(255, 255, 255, .16) 18%, rgba(255, 255, 255, .06) 46%, rgba(255, 255, 255, .07) 74%, rgba(170, 196, 255, .26));
  --gl-prism: linear-gradient(90deg, transparent 10%, rgba(255, 168, 92, .3) 32%, rgba(168, 255, 196, .18) 48%, rgba(126, 168, 255, .34) 64%, transparent 88%);
  --gl-drop: 0 18px 40px -24px rgba(0, 0, 0, .8);
}
/* общий рецепт: тело (padding-box) + спектр по нижней кромке и сама кромка (border-box) */
.btn-ghost:not(.configurator *), .toast, dialog,
.collection-grid .card-cta, .field input, .field textarea {
  border: 1px solid transparent;
  background:
    var(--gl-body) padding-box,
    var(--gl-tint) padding-box,
    var(--gl-prism) 0 100% / 100% 1px no-repeat border-box,
    var(--gl-edge) border-box;
}
/* ---------- шапка: тёмное тонированное стекло без размытия (под ней — холст волны и 3D-сцена) ---------- */
.nav.is-scrolled {
  backdrop-filter: none; -webkit-backdrop-filter: none; border-bottom-color: transparent;
  background:
    linear-gradient(180deg, rgba(255, 255, 255, .05), rgba(255, 255, 255, 0) 60%),
    linear-gradient(rgba(12, 13, 16, .84), rgba(12, 13, 16, .84));
  box-shadow: inset 0 -1px 0 rgba(232, 228, 220, .09), 0 1px 0 rgba(0, 0, 0, .35);
}
/* волосяной спектр по низу шапки — отдельной нитью (у шапки ::before занят подложкой волны) */
.nav::after {
  content: ''; position: absolute; left: 12%; right: 12%; bottom: -1px; height: 1px; pointer-events: none;
  background: var(--gl-prism); opacity: 0; transition: opacity var(--d-ui) var(--ease-quart);
}
.nav.is-scrolled::after { opacity: .7; }
/* ---------- кнопки ---------- */
/* светлая — серебряное стекло: светлое тело с градиентом, кромка-блик сверху, спектр снизу; текст тёмный */
.btn-light:not(.configurator *) {
  border: 1px solid transparent;
  background:
    linear-gradient(170deg, rgba(255, 255, 255, .98), rgba(236, 234, 229, .94) 46%, rgba(214, 212, 207, .94)) padding-box,
    var(--gl-prism) 0 100% / 100% 1px no-repeat border-box,
    linear-gradient(135deg, #fff, rgba(255, 255, 255, .6) 30%, rgba(180, 186, 198, .7) 70%, rgba(150, 176, 240, .9)) border-box;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .9), inset 0 -8px 16px -10px rgba(120, 128, 140, .35), var(--gl-drop);
  transition: filter var(--d-ui) var(--ease-quart), opacity var(--d-ui), transform 400ms var(--ease-expo);
}
.btn-light:not(.configurator *):not(:disabled):hover { background-color: transparent; filter: brightness(1.04); }
.btn-light:not(.configurator *):not(:disabled):active { background-color: transparent; filter: brightness(.94); }
/* на светлом hero (W/S) — графитовое стекло: тёмное тело, светлая кромка, светлый текст */
@media (min-aspect-ratio: 1/1) {
  .hero .btn-light {
    color: #eeece7;
    background:
      linear-gradient(170deg, rgba(58, 60, 66, .96), rgba(27, 28, 32, .97) 48%, rgba(18, 19, 22, .98)) padding-box,
      var(--gl-prism) 0 100% / 100% 1px no-repeat border-box,
      linear-gradient(135deg, rgba(255, 255, 255, .7), rgba(255, 255, 255, .18) 30%, rgba(255, 255, 255, .06) 64%, rgba(150, 176, 240, .5)) border-box;
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .18), 0 16px 34px -20px rgba(0, 0, 0, .55);
  }
  .hero .btn-light:not(:disabled):hover { background-color: transparent; filter: brightness(1.18); }
  .hero .btn-light:not(:disabled):active { background-color: transparent; filter: brightness(.9); }
}
.btn-ghost:not(.configurator *) { color: var(--text); }
.btn-ghost:not(.configurator *)::before { display: none; }
.btn-ghost:not(.configurator *):not(:disabled):hover { filter: brightness(1.25); }
/* ---------- блик (общий слой ::after): мягкое пятно у указателя; на телефоне — проход света ---------- */
.btn:not(.configurator *), .collection-grid .card-media, .steps { --gx: -400px; --gy: -400px; }
.btn:not(.configurator *)::after, .collection-grid .card .card-media::after, .steps::after {
  content: ''; position: absolute; left: 0; top: 0; width: 240px; height: 240px; margin: -120px 0 0 -120px; border-radius: 50%;
  display: block; pointer-events: none; z-index: 0; opacity: 0;
  background: radial-gradient(closest-side, rgba(255, 255, 255, .26), rgba(226, 236, 255, .09) 46%, transparent);
  transform: translate(var(--gx), var(--gy));
  transition: opacity 360ms var(--ease-quart);
}
.btn-light:not(.configurator *)::after { background: radial-gradient(closest-side, rgba(255, 255, 255, .85), rgba(255, 255, 255, .25) 46%, transparent); }
.btn > span { z-index: 1; }
.gl-hot::after, .collection-grid .card .card-media.gl-hot::after { opacity: 1; }
/* телефон: проход света — узкая полоса поперёк, раз в ≈ 7 с (только .gl-run: видно на экране и было касание) */
@media (hover: none) {
  .btn::after, .collection-grid .card .card-media::after, .steps::after {
    left: 0; top: -50%; width: 46%; height: 200%; margin: 0; border-radius: 0;
    background: linear-gradient(100deg, transparent 20%, rgba(214, 226, 255, .1) 40%, rgba(255, 255, 255, .26) 50%, rgba(255, 232, 210, .1) 60%, transparent 80%);
    transform: translateX(-130%) rotate(12deg);
  }
  .btn-light::after { background: linear-gradient(100deg, transparent 20%, rgba(255, 255, 255, .5) 50%, transparent 80%); }
  .gl-run::after, .collection-grid .card .card-media.gl-run::after { opacity: 1; animation: gl-pass 7s var(--ease-io) var(--gl-delay, 0s) infinite; }
}
@keyframes gl-pass { 0%, 62% { transform: translateX(-130%) rotate(12deg); } 100% { transform: translateX(330%) rotate(12deg); } }
@media (prefers-reduced-motion: reduce) { .btn::after, .tool::after, .top-choice::after, .collection-grid .card .card-media::after, .steps::after { display: none; } }
/* ---------- карточки «Коллекции»: витрина — стеклянная плита (кромка, спектр, блик), кольцо стоит на ней ---------- */
.collection-grid .card .card-media { overflow: hidden; border-radius: 20px; isolation: isolate; }
.collection-grid .card .card-media::before {
  content: ''; position: absolute; inset: 0; border-radius: inherit; z-index: -1; pointer-events: none;
  border: 1px solid transparent;
  background:
    radial-gradient(70% 34% at 50% 86%, rgba(232, 228, 220, .07), transparent 70%) padding-box,
    var(--gl-body) padding-box,
    linear-gradient(rgba(16, 18, 22, .38), rgba(16, 18, 22, .38)) padding-box,
    var(--gl-prism) 0 100% / 100% 1px no-repeat border-box,
    var(--gl-edge) border-box;
  transition: filter 600ms var(--ease-quart);
}
.collection-grid .card:hover .card-media::before, .collection-grid .card:focus-visible .card-media::before { filter: brightness(1.25); }
.collection-grid .card-photo .card-media::before { display: none; }
.collection-grid .card-cta { color: #ece9e3; box-shadow: inset 0 1px 0 rgba(255, 255, 255, .22), 0 12px 30px -14px rgba(0, 0, 0, .7); }
/* ---------- плита шагов «Приручения»: кромка-блик и спектр поверх прежнего стекла ---------- */
.steps { overflow: hidden; isolation: isolate; }
.steps::before {
  content: ''; position: absolute; inset: 0; border-radius: inherit; pointer-events: none; z-index: 0; padding: 1px;
  background: var(--gl-prism) 0 100% / 100% 1px no-repeat, var(--gl-edge);
  -webkit-mask: linear-gradient(#000, #000) content-box, linear-gradient(#000, #000); -webkit-mask-composite: xor;
  mask: linear-gradient(#000, #000) content-box exclude, linear-gradient(#000, #000);
}
.steps li { z-index: 1; }
/* ---------- конструктор: 2.20.1 — по просьбе владельца прежний вид 2.19.1 (стекло 2.20 сюда не применяется) ---------- */
/* ---------- окно заказа: стекло без размытия (под ним — сцена), поля — стеклянные ---------- */
dialog {
  backdrop-filter: none; -webkit-backdrop-filter: none; border-radius: 22px;
  background: var(--gl-body) padding-box, linear-gradient(rgba(15, 16, 20, .95), rgba(15, 16, 20, .95)) padding-box, var(--gl-prism) 0 100% / 100% 1px no-repeat border-box, var(--gl-edge) border-box;
  box-shadow: 0 40px 90px -30px rgba(0, 0, 0, .9);
}
dialog::backdrop { backdrop-filter: none; -webkit-backdrop-filter: none; background: radial-gradient(120% 90% at 50% 40%, rgba(6, 7, 9, .62), rgba(3, 3, 4, .84)); }
.field input, .field textarea { padding: 12px 14px; border-radius: 12px; }
.field input:focus, .field textarea:focus {
  background: var(--gl-body) padding-box, var(--gl-tint) padding-box, linear-gradient(135deg, rgba(220, 230, 255, .8), var(--ice) 50%, rgba(159, 180, 245, .35)) border-box;
}
.field input[aria-invalid="true"] { background: var(--gl-body) padding-box, var(--gl-tint) padding-box, linear-gradient(var(--danger), var(--danger)) border-box; }
.order-recap, .order-next { border-color: rgba(232, 228, 220, .1); }
.toast { color: #141518; background: linear-gradient(170deg, rgba(255, 255, 255, .98), rgba(226, 224, 219, .95)) padding-box, var(--gl-prism) 0 100% / 100% 1px no-repeat border-box, linear-gradient(135deg, #fff, rgba(150, 176, 240, .9)) border-box; box-shadow: var(--gl-drop); }
/* контраст на стекле (WCAG AA): тело стекла светлее страницы — мелкие серые подписи на нём на ступень светлее
   (#9c9da2 на самом светлом месте открытой секции — ≥ 4,8 : 1) */
dialog .order-next, dialog .field em, .field input::placeholder, .field textarea::placeholder { color: #9c9da2; }
/* 2.20 (аудит конструктора на телефоне, п. 1): зерно — слой на весь экран с mix-blend-mode: overlay поверх холста; пока
   конструктор на экране телефона, композитор смешивал его с 3D-сценой в каждом кадре — там зерно снято (js/motion.js
   ставит .grain-off по IntersectionObserver раздела конструктора, класс — на самом слое, не на корне) */
.grain.grain-off { display: none; }

/* =====================================================================
   2.20.2 — ДОРОЖЕ И ЛЕГЧЕ (владелец: «элитно и дорого, при этом легко и современно»)
   1) без радуги: стекло интерфейса — только серебряная кромка (спектр и холодный перелив сняты);
   3) больше воздуха между разделами, подписи мельче и разреженнее. Конструктор — как в 2.19.1, его не касается
   ===================================================================== */
:root {
  --gl-prism: linear-gradient(transparent, transparent);
  --gl-edge: linear-gradient(135deg, rgba(255, 255, 255, .42), rgba(255, 255, 255, .14) 18%, rgba(255, 255, 255, .05) 46%, rgba(255, 255, 255, .05) 74%, rgba(255, 255, 255, .16));
  --section: clamp(120px, 17vw, 280px);
}
.btn-light:not(.configurator *) {
  background:
    linear-gradient(170deg, rgba(255, 255, 255, .98), rgba(238, 236, 231, .95) 46%, rgba(220, 218, 213, .95)) padding-box,
    linear-gradient(135deg, #fff, rgba(255, 255, 255, .6) 30%, rgba(190, 192, 196, .7)) border-box;
}
@media (min-aspect-ratio: 1/1) {
  .hero .btn-light {
    background:
      linear-gradient(170deg, rgba(58, 60, 66, .96), rgba(27, 28, 32, .97) 48%, rgba(18, 19, 22, .98)) padding-box,
      linear-gradient(135deg, rgba(255, 255, 255, .62), rgba(255, 255, 255, .16) 30%, rgba(255, 255, 255, .06) 64%, rgba(255, 255, 255, .22)) border-box;
  }
}
.nav::after, .configurator .panel::after { display: none; }
@media (hover: hover) { .btn:not(.btn-light)::after { background: radial-gradient(closest-side, rgba(255, 255, 255, .22), rgba(255, 255, 255, .07) 46%, transparent); } }
@media (hover: none) { .btn:not(.btn-light)::after, .collection-grid .card .card-media::after, .steps::after { background: linear-gradient(100deg, transparent 20%, rgba(255, 255, 255, .08) 40%, rgba(255, 255, 255, .22) 50%, rgba(255, 255, 255, .08) 60%, transparent 80%); } }
.section-head { margin-bottom: clamp(64px, 9vw, 150px); }
.eyebrow:not(.configurator *) { font-size: 10.5px; letter-spacing: .2em; }
.section-lead { font-size: 16px; line-height: 1.7; }
.hero-text { font-size: 16px; line-height: 1.7; }
/* 2.20.2: стеклянные стержни в заголовке hero сняты (владелец: «убирай эти линии») — строка без маски и копии */
.hero-title .line::before, .hero-title .line::after { display: none; }
.hero-title .line > span { -webkit-mask: none; mask: none; }

/* 2.21: работы коллекции на заднем плане после конструктора — крупно и хорошо видно, раскладку не меняют (слой
   absolute, высота страницы прежняя). «Монолит» справа и «Лёд» слева в «Приручении прозрачности», «Капля» в подвале;
   «Кристалл» — на первом экране. Тень и лёгкое парение (только transform) */
.process, .footer { position: relative; isolation: isolate; }
.process > :not(.bg-rings), .footer > :not(.bg-rings) { position: relative; z-index: 1; }
.bg-rings { position: absolute; inset: 0; z-index: 0; overflow: hidden; pointer-events: none; }
.bg-ring { position: absolute; display: block; height: auto; max-width: none; user-select: none; opacity: .55;
  filter: drop-shadow(0 40px 50px rgba(0, 0, 0, .6));
  animation: bg-float 10s var(--ease-io) infinite alternate; }
.bg-ring.r1 { width: clamp(420px, 44vw, 860px); right: -4%; top: 6%; rotate: -12deg; }
.bg-ring.r2 { width: clamp(400px, 40vw, 780px); left: -4%; bottom: -60px; rotate: 14deg; animation-delay: -5s; } /* большой; ниже характеристик — уходит на стык с подвалом, текст не закрывает */
.bg-ring.r3 { width: clamp(312px, 31.2vw, 552px); right: 3%; top: 50%; translate: 0 -50%; rotate: -10deg; animation-delay: -2.5s; }
@keyframes bg-float { from { transform: translateY(-10px); } to { transform: translateY(10px); } }
@media (prefers-reduced-motion: reduce) { .bg-ring { animation: none; } }
@media (max-width: 860px) {
  .bg-ring.r1 { width: 96vw; right: -26%; top: 8%; }
  .bg-ring.r2 { width: 90vw; left: -22%; bottom: -40px; }
  .bg-ring.r3 { width: 62.4vw; right: -8%; }
}
/* 2.21: «Капля» в подвале не срезается его высотой (подвал ≈ 290 px — увеличение было не видно): слой подвала без
   обрезки, кольцо стоит на нижнем краю и поднимается над подвалом, под содержимым «Приручения» */
.process { z-index: 1; }
.footer { z-index: 0; }
.footer .bg-rings { overflow: visible; }
.bg-ring.r3 { top: auto; bottom: 14%; translate: none; } /* «сферу чуть выше» */
/* лёд выходит ниже раздела (на стык с подвалом): по вертикали без обрезки, по горизонтали — обрезка (без прокрутки вбок) */
.process .bg-rings { overflow-x: clip; overflow-y: visible; }

/* 2.21: плита шагов «Форма · Модель · Изготовление · Доставка» — глянцевое стекло как кромка волны первого экрана:
   дымчатое тело, широкий серебряный блик по диагонали сверху, глянцевая дуга у верхнего края, яркий волосяной кант
   (свет сверху слева), тёмная грань снизу, глубокая тень. Блик-проход (::after) — прежний, ярче */
html .steps {
  background:
    radial-gradient(120% 60% at 50% -18%, rgba(255, 255, 255, .24), rgba(255, 255, 255, .07) 45%, transparent 70%),
    linear-gradient(118deg, transparent 18%, rgba(255, 255, 255, .17) 30%, rgba(236, 240, 248, .07) 38%, transparent 52%),
    linear-gradient(118deg, transparent 58%, rgba(255, 255, 255, .05) 66%, transparent 74%),
    linear-gradient(180deg, rgba(40, 43, 50, .62), rgba(18, 20, 24, .72) 55%, rgba(10, 11, 14, .8));
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .55), inset 1px 0 0 rgba(255, 255, 255, .16), inset 0 -1px 0 rgba(0, 0, 0, .5),
    inset 0 18px 30px -22px rgba(255, 255, 255, .35), inset 0 -30px 50px -30px rgba(0, 0, 0, .55),
    0 40px 80px -40px rgba(0, 0, 0, .9), 0 0 0 1px rgba(255, 255, 255, .05);
}
html .steps::before { background: linear-gradient(135deg, rgba(255, 255, 255, .85), rgba(255, 255, 255, .22) 22%, rgba(255, 255, 255, .06) 50%, rgba(255, 255, 255, .1) 78%, rgba(255, 255, 255, .45)); }
html .steps::after { background: linear-gradient(100deg, transparent 22%, rgba(255, 255, 255, .06) 40%, rgba(255, 255, 255, .3) 50%, rgba(255, 255, 255, .06) 60%, transparent 78%) !important;
  left: 0; top: -50%; width: 40%; height: 200%; margin: 0; border-radius: 0; transform: translateX(-130%) rotate(12deg); }
.js-motion .steps.in::after { opacity: 1; animation: gl-pass 9s var(--ease-io) 1.2s infinite; }
@media (prefers-reduced-motion: reduce) { .js-motion .steps.in::after { animation: none; opacity: 0; } }
.steps h3 { color: #f1eee8; text-shadow: 0 1px 0 rgba(0, 0, 0, .35); }
.steps p { color: #b4b2ad; }
/* 2.21: появление плиты — как жидкое стекло (начальная капля ≥ 12 % площади: иначе IntersectionObserver initReveals не видит плиту и она не появляется): капля растекается (скругление «плывёт»), лист пружинит с перелётом и
   успокаивается, глянец пробегает после; только clip-path / transform / opacity */
.js-motion .steps { opacity: 0; clip-path: inset(30% 20% 30% 20% round 300px); transform: scale(.94, .86); transition: none; }
.js-motion .steps.in { animation: steps-liquid 1900ms cubic-bezier(.2, .9, .25, 1) both; }
@keyframes steps-liquid {
  0%   { opacity: 0; clip-path: inset(30% 20% 30% 20% round 300px); transform: scale(.94, .86); }
  18%  { opacity: 1; }
  45%  { clip-path: inset(-2% -1% -3% -1% round 60px 90px 50px 80px); transform: scale(1.025, 1.04); }
  62%  { clip-path: inset(0 0 0 0 round 34px 22px 38px 26px); transform: scale(.99, .985); }
  80%  { clip-path: inset(0 0 0 0 round 26px 30px 26px 30px); transform: scale(1.004, 1.006); }
  100% { opacity: 1; clip-path: inset(0 0 0 0 round 28px); transform: none; }
}
@media (max-width: 860px) { .js-motion .steps.in { animation-name: steps-liquid; } }
@media (prefers-reduced-motion: reduce) { .js-motion .steps, .js-motion .steps.in { animation: none; opacity: 1; clip-path: none; transform: none; } }
/* 2.21: плита шагов — без проходящего блика и без белой засветки по внутреннему периметру (владелец); вместо — блик на
   кромке, который следует за указателем (js/motion.js initGlass пишет --gx/--gy, класс .gl-hot), плавно гаснет вне плиты */
@property --gk { syntax: '<number>'; inherits: true; initial-value: 0; }
html .steps { --gk: 0; transition: --gk 600ms var(--ease-quart);
  box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .5), 0 40px 80px -40px rgba(0, 0, 0, .9);
  background:
    radial-gradient(120% 60% at 50% -18%, rgba(255, 255, 255, .1), rgba(255, 255, 255, .03) 45%, transparent 70%),
    linear-gradient(118deg, transparent 18%, rgba(255, 255, 255, .12) 30%, rgba(236, 240, 248, .05) 38%, transparent 52%),
    linear-gradient(180deg, rgba(40, 43, 50, .62), rgba(18, 20, 24, .72) 55%, rgba(10, 11, 14, .8)); }
html .steps.gl-hot { --gk: 1; }
html .steps::after, .js-motion .steps.in::after { display: none; animation: none; }
html .steps::before {
  background:
    radial-gradient(260px circle at var(--gx) var(--gy), rgba(255, 255, 255, calc(.95 * var(--gk))), rgba(236, 242, 255, calc(.35 * var(--gk))) 35%, transparent 70%),
    linear-gradient(135deg, rgba(255, 255, 255, .34), rgba(255, 255, 255, .1) 30%, rgba(255, 255, 255, .05) 60%, rgba(255, 255, 255, .16));
}
/* 2.21b: сборка заметнее — капля из середины (масштаб, а не обрезка: обрезка уменьшала видимую площадь, и
   IntersectionObserver не запускал появление) растекается в плиту с пружинным перелётом, шаги проступают после */
.js-motion .steps { opacity: 0; clip-path: inset(0 0 0 0 round 400px); transform: scale(.22, .14); }
.js-motion .steps.in { animation: steps-assemble 2100ms cubic-bezier(.2, .9, .25, 1) both; }
@keyframes steps-assemble {
  0%   { opacity: 0; transform: scale(.22, .14); clip-path: inset(0 0 0 0 round 400px); }
  12%  { opacity: 1; }
  38%  { transform: scale(1.06, .82); clip-path: inset(0 0 0 0 round 140px 200px 120px 180px); }
  56%  { transform: scale(.97, 1.07); clip-path: inset(0 0 0 0 round 60px 40px 70px 50px); }
  72%  { transform: scale(1.015, .985); clip-path: inset(0 0 0 0 round 34px 26px 36px 28px); }
  86%  { transform: scale(.996, 1.004); }
  100% { opacity: 1; transform: none; clip-path: inset(0 0 0 0 round 28px); }
}
.js-motion .steps li { transition-delay: calc(900ms + var(--i, 0) * 140ms); }
@media (prefers-reduced-motion: reduce) { .js-motion .steps, .js-motion .steps.in { animation: none; opacity: 1; clip-path: none; transform: none; } }

/* 2.22: телефон — кольца на заднем плане по всей высоте «Приручения», а не комом у подвала: «Монолит» у заголовка
   справа, «Лёд» посередине слева, «Капля» ниже справа (копия r4 — только на телефоне; в подвале «Капля» скрыта) */
.bg-ring.r4 { display: none; }
@media (max-width: 860px) {
  .bg-ring { opacity: .42; }
  .bg-ring.r1 { width: 74vw; right: -24%; top: 3%; bottom: auto; }
  .bg-ring.r2 { width: 78vw; left: -28%; top: 40%; bottom: auto; }
  .bg-ring.r4 { display: block; width: 64vw; right: -22%; top: 70%; rotate: -10deg; animation-delay: -2.5s; }
  .footer .bg-rings { display: none; }
}
.order-terms { margin: 14px 0 0; font-size: 13px; line-height: 1.5; color: #9c9da2; text-align: center; }
.order-terms a { color: inherit; }
/* 2.22b: телефон — «Лёд» и «Капля» парой в свободной полосе под кнопкой «Открыть конструктор», не под текстом */
@media (max-width: 860px) {
  .bg-ring.r2 { width: 42vw; left: 4%; top: auto; bottom: 6px; rotate: 12deg; opacity: .6; }
  .bg-ring.r4 { width: 40vw; right: 4%; top: auto; bottom: 10px; rotate: -10deg; opacity: .6; }
}
/* 2.22c: телефон — кольца крупно и вразброс по всему «Приручению» (не мелкой парой): видно не меньше двух третей */
@media (max-width: 860px) {
  .bg-ring { opacity: .45; }
  .bg-ring.r1 { width: 92vw; right: -30%; left: auto; top: 1%; bottom: auto; rotate: -18deg; }
  .bg-ring.r2 { width: 96vw; left: -34%; right: auto; top: 50%; bottom: auto; rotate: 24deg; opacity: .42; }
  .bg-ring.r4 { width: 84vw; right: -28%; left: auto; top: 77%; bottom: auto; rotate: -12deg; opacity: .45; }
}

/* =====================================================================
   ВЛЁТ В КОЛЬЦО v2 (тест) — js/flyin.js, config.js → enter: 'flyin' ('wave' — прежняя волна)
   Слои в main (свой контекст наложения): hero (−2) → холст поля (−1) → вуаль цвета раздела (0) → конструктор, сдвинутый
   на экран, с прозрачным фоном (1) → вырезка кольца (2) → засветки подмены (3). Движется только transform / opacity —
   без фильтров и масок (каждый такой слой — лишний проход компоновщика в кадре)
   ===================================================================== */
.flyin-veil { position: fixed; inset: 0; z-index: 0; pointer-events: none; will-change: opacity; }
.flyin-ring { position: fixed; left: 0; top: 0; z-index: 2; pointer-events: none; will-change: transform, opacity; }
.flyin-ring img { display: block; width: 100%; height: 100%; }
/* края сцены, пока она не на своём месте, — растушёвка в цвет раздела (один растр, двигается вместе со сценой) */
.flyin-edge { position: absolute; inset: 0; z-index: 1; pointer-events: none; will-change: opacity;
  background:
    radial-gradient(ellipse 72% 70% at 50% 50%, rgba(11, 12, 14, 0) 58%, rgba(11, 12, 14, .7) 84%, #0b0c0e 100%),
    linear-gradient(90deg, #0b0c0e, rgba(11, 12, 14, 0)) left / var(--ex, 80px) 100% no-repeat,
    linear-gradient(270deg, #0b0c0e, rgba(11, 12, 14, 0)) right / var(--ex, 80px) 100% no-repeat,
    linear-gradient(180deg, #0b0c0e, rgba(11, 12, 14, 0)) top / 100% var(--ey, 80px) no-repeat,
    linear-gradient(0deg, #0b0c0e, rgba(11, 12, 14, 0)) bottom / 100% var(--ey, 80px) no-repeat; }
/* засветки подмены фото → модель (≈ 0,26 с; по разбору дизайнера — тише и короче): свет из глубины (холодный белый),
   тонкий белый штрих по линии верхней грани, искра на ребре плато. Блок — рамка силуэта кольца, идёт за ним тем же transform */
.flyin-flare { position: fixed; left: 0; top: 0; z-index: 3; pointer-events: none; will-change: transform, opacity; }
.flyin-flare i { position: absolute; display: block; opacity: 0; will-change: transform, opacity; }
.flyin-flare .ff-bloom { inset: -16% -4%; border-radius: 50%;
  background: radial-gradient(closest-side, rgba(238, 243, 255, .7), rgba(238, 243, 255, .26) 36%, rgba(238, 243, 255, .06) 64%, rgba(238, 243, 255, 0) 80%); }
.flyin-flare .ff-streak { left: 3%; width: 90%; top: 24%; height: 7%; margin-top: -3.5%;
  background: radial-gradient(50% 50% at 50% 50%, rgba(255, 255, 255, .95), rgba(255, 255, 255, .4) 9%, rgba(255, 255, 255, .08) 30%, rgba(255, 255, 255, 0) 60%); }
.flyin-flare .ff-star { left: 84%; top: 13%; width: 26%; aspect-ratio: 1; margin: -13% 0 0 -13%;
  background:
    linear-gradient(90deg, rgba(255, 255, 255, 0), rgba(255, 255, 255, .95) 50%, rgba(255, 255, 255, 0)) center / 100% 1.5px no-repeat,
    linear-gradient(0deg, rgba(255, 255, 255, 0), rgba(255, 255, 255, .95) 50%, rgba(255, 255, 255, 0)) center / 1.5px 100% no-repeat,
    radial-gradient(circle, rgba(255, 255, 255, .95), rgba(225, 236, 255, .3) 12%, rgba(225, 236, 255, 0) 34%); }.hero.flyin-hot { cursor: pointer; }

/* =====================================================================
   2.24 ТЕЛЕФОН: КОНСТРУКТОР — КАК ПРИЛОЖЕНИЕ; СТЕКЛО ПЕРЕХОДА — ТЕКСТУРОЙ (js/app.js, js/ambient.js)
   Владелец: «движение в меню ползунков влияет на зону конфигурации модели, она постоянно двигается». Замер (390 × 844):
   прокрутка меню двигала страницу (435 px), шапка пряталась и показывалась, поля сцены менялись 183 кадра подряд —
   модель перецентровывалась. Теперь на сенсорном телефоне раздел — ровно экран (100dvh): сцена закреплена сверху
   (60svh — панель браузера её не меняет), меню ползунков — своя прокрутка под ней (без передачи странице); цена и
   заказ — строкой внизу всегда. Страница стоит, пока посетитель в конструкторе. Ушёл в конец меню — следующий жест
   вверх ведёт страницу дальше (к «Приручению» и подвалу); назад на hero — как прежде, протяжкой с шапки панели
   ===================================================================== */
@media (max-width: 860px) and (pointer: coarse) {
  .configurator { height: 100vh; height: 100dvh; min-height: 0; grid-template-rows: auto minmax(0, 1fr); }
  .stage { position: relative; top: auto; height: 60svh; }
  .stage.stuck { background: none; box-shadow: none; }
  .configurator .panel { display: flex; flex-direction: column; min-height: 0; overflow: hidden; }
  .configurator .panel-scroll { flex: 1 1 auto; min-height: 0; overflow-x: hidden; overflow-y: auto; overscroll-behavior-y: contain; -webkit-overflow-scrolling: touch; }
  .configurator .panel-foot { position: relative; bottom: auto; flex: none; touch-action: none; }
}
/* без WebGL-волны (телефон, js/ambient.js → .amb-lite): фон конструктора — свой, неподвижный (поле под ним не рисуется,
   пока посетитель в конструкторе); кромка стекла перехода — текстура над верхом раздела, едет вместе с ним */
html.amb-lite #configurator {
  background:
    radial-gradient(120% 55% at 18% 62%, rgba(58, 74, 112, .22), rgba(58, 74, 112, 0) 70%),
    radial-gradient(90% 45% at 88% 88%, rgba(120, 92, 70, .14), rgba(120, 92, 70, 0) 70%),
    linear-gradient(180deg, #0e1014, #0b0c0e 60%, #0a0b0d);
}
html.amb-lite #configurator::before {
  content: ''; position: absolute; left: 0; right: 0; bottom: 100%; height: 56px; pointer-events: none; z-index: 4;
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0) calc(100% - 4px), rgba(255, 255, 255, .92) calc(100% - 3px), rgba(255, 255, 255, .5) calc(100% - 2px), rgba(14, 16, 20, .7) 100%),
    radial-gradient(60% 120% at 28% 100%, rgba(255, 255, 255, .26), rgba(255, 255, 255, 0) 62%),
    radial-gradient(45% 110% at 76% 100%, rgba(214, 228, 255, .22), rgba(214, 228, 255, 0) 62%),
    linear-gradient(180deg, rgba(240, 244, 252, 0), rgba(240, 244, 252, .1) 50%, rgba(225, 232, 245, .24) 92%);
}

/* 2.24 (QA 2.23): ярлык возврата на hero на сенсорных экранах (js/ambient.js) — над «Персональное кольцо»; тянуть назад
   можно только за него и за эту строку (подсказку панели листают — она больше не уводит на hero) */
.panel-grab {
  display: inline-flex; align-items: center; gap: 6px; min-height: 44px; margin: -10px 0 4px -10px; padding: 0 12px 0 10px;
  font: var(--caps-weight, 500) 10.5px/1 var(--sans); letter-spacing: .14em; text-transform: uppercase; color: var(--text-2);
  background: none; border: 0; border-radius: 22px; cursor: pointer; touch-action: none; -webkit-tap-highlight-color: transparent;
}
.panel-grab span { font-size: 13px; letter-spacing: 0; color: var(--text); }
.panel-grab:active { color: var(--text); background: rgba(232, 228, 220, .06); }
.configurator .panel-head > .eyebrow { touch-action: none; }
/* 2.24 (QA 2.23): телефон в ландшафте (932 × 430): конструктор помещается в экран — сцена и панель рядом, панель листается
   сама, цена и заказ видны; лишние строки подвала панели скрыты */
@media (pointer: coarse) and (orientation: landscape) and (max-height: 500px) {
  .configurator { height: 100vh; height: 100dvh; min-height: 0; grid-template-columns: minmax(0, 1fr) min(400px, 46vw); grid-template-rows: minmax(0, 1fr); }
  .stage { height: auto; min-height: 0; }
  .configurator .panel { display: flex; flex-direction: column; min-height: 0; overflow: hidden; }
  .configurator .panel-scroll { flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior-y: contain; padding: calc(var(--nav-h) + 6px) 22px 12px; }
  .configurator .panel-foot { flex: none; padding: 10px 22px calc(10px + env(safe-area-inset-bottom)); touch-action: none; }
  .configurator .panel-foot .spec, .configurator .panel-foot .service-line, .configurator .panel-foot .foot-contact { display: none; }
  .configurator .panel-foot .price { font-size: 28px; }
  .configurator .panel-foot .btn { margin-top: 8px; }
  .stage-bottom { bottom: 10px; }
  .stage-hint { display: none; }
}

/* 2.24 UI — правки по QA-пользователям
   =====================================================================
   Только переопределения: раскладку сцены и панели и блоки перехода не трогает. Отчёты — qa-snapshot-2.23/_qa,
   снимки до/после — docs/ref-ui-224 */

/* ---------- зоны нажатия ≥ 44 px (рисунок прежний: зона — прозрачный слой или поля с отрицательным отступом) ---------- */
/* «Заказ» / «Конструктор» в шапке: было 41 × 28 */
.nav-side a::before { content: ''; position: absolute; inset: -8px -10px; }
/* ссылки подвала: было 12 px высотой */
.footer-links a { display: inline-flex; align-items: center; min-height: 44px; margin: -16px -6px; padding: 0 6px; }
/* образцы цвета (26–28 px): зона 44 px; на сенсорном экране образцы — своей строкой под «Цвет» с шагом 46 px,
   чтобы зоны соседей не перекрывались и имя цвета не обрезалось */
@media (pointer: coarse) {
  .swatch::before { inset: -9px; border-radius: 12px; }
  .color-row .swatches { flex: 1 0 100%; gap: 18px; padding: 4px 0 6px 9px; }
  .color-row .swatch { width: 28px; height: 28px; }
}

/* ---------- окно заказа ---------- */
/* сквозь окно не просвечивает конструктор: тело — плотное, подложка — почти глухая */
dialog {
  background: var(--gl-body) padding-box, linear-gradient(#121317, #0f1013) padding-box, var(--gl-prism) 0 100% / 100% 1px no-repeat border-box, var(--gl-edge) border-box;
}
dialog::backdrop { background: radial-gradient(120% 90% at 50% 40%, rgba(6, 7, 9, .9), rgba(3, 3, 4, .96)); }
/* подписи полей: 11 → 12,5 px */
.field > span { font-size: 12.5px; }
.field em { font-size: 12.5px; }
/* номера телефонов не рвутся по строкам (js/app.js → nowrapPhones) */
.nw-phone, dialog a[href^="tel:"] { white-space: nowrap; }
/* согласие: свой квадрат в стиле тёмного стекла (нативный checkbox — та же доступность). Видимый квадрат 22 px, зона
   нажатия 44 px — прозрачная рамка 11 px вокруг него; ссылки — только на словах «согласие» и «политикой» */
.check { gap: 12px; align-items: flex-start; min-height: 44px; font-size: 14px; line-height: 1.55; cursor: pointer;
  margin: -11px 0 -11px -11px; padding: 11px 0 11px 11px; } /* подпись накрывает и скруглённые углы зоны квадрата */
.check input {
  -webkit-appearance: none; appearance: none; flex: none; box-sizing: content-box; width: 22px; height: 22px; padding: 0;
  margin: -11px -11px -11px -11px; border: 11px solid transparent; border-radius: 17px; cursor: pointer; accent-color: auto;
  background: linear-gradient(160deg, rgba(255, 255, 255, .09), rgba(255, 255, 255, .025)) padding-box;
  box-shadow: inset 0 0 0 1px rgba(232, 228, 220, .38), inset 0 1px 0 rgba(255, 255, 255, .12);
  transition: background-color 250ms var(--ease-quart), box-shadow 250ms var(--ease-quart);
}
.check:hover input { box-shadow: inset 0 0 0 1px rgba(232, 228, 220, .62), inset 0 1px 0 rgba(255, 255, 255, .16); }
.check input:checked {
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M6.2 12.6l3.9 3.8 7.7-8.6' fill='none' stroke='%23141518' stroke-width='1.9' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / 18px no-repeat padding-box,
    linear-gradient(170deg, #fbfaf7, #e4e2dd) padding-box;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .9), 0 0 0 0 transparent;
}
.check input[aria-invalid="true"]:not(:checked) { box-shadow: inset 0 0 0 1px var(--danger); }
.check input:focus { outline: none; }
.check input:focus-visible { outline: 2px solid var(--ice); outline-offset: -9px; }
.check > span { padding-top: 1px; }
.check a { color: var(--text); text-decoration-thickness: 1px; text-underline-offset: 3px; text-decoration-color: rgba(232, 228, 220, .45); }

/* ---------- размеры текста на телефоне (и сенсорном экране) ---------- */
@media (max-width: 860px), (pointer: coarse) {
  /* подписи форм верха: 9,5 → 11 px (разрядка чуть уже — «Пирамида» в колонку 74 px на 360) */
  .top-choice { font-size: 11px; letter-spacing: .07em; }
  /* заголовки секций меню: 11,5 → 12,5 px */
  .acc-title { font-size: 12.5px; }
}

/* ---------- первый экран: кнопка «Создать своё кольцо» — вместе с заголовком, а не через 1,25 с после него
   (QA планшет: кнопка появлялась ≈ через 4 с после начала загрузки) ---------- */
.js-motion .hero .hero-actions.reveal-up { transition-delay: 160ms; }

/* ---------- телефон в ландшафте: «Конструктор» один раз — в шапке; подпись над сценой скрыта ---------- */
@media (pointer: coarse) and (max-height: 500px) { .stage-top .eyebrow { visibility: hidden; } }

/* ---------- кольца на заднем плане «Приручения» и подвала: крупно и вразброс, но не под текстом ----------
   Свободные места: справа от заголовка раздела, полоса кнопки «Открыть конструктор» (по бокам от неё) и стык
   с подвалом над «PLEXIFORM». Плита шагов — стекло: кольцо за ней приглушено, текст на ней читается */
@media (min-width: 601px) and (max-width: 860px) {
  .bg-ring.r1 { width: 54vw; right: -20%; left: auto; top: -3%; bottom: auto; rotate: -16deg; opacity: .5; }
  .bg-ring.r2 { width: 36vw; left: -12%; right: auto; top: auto; bottom: -70px; rotate: 20deg; opacity: .5; }
  .bg-ring.r4 { width: 33vw; right: -10%; left: auto; top: auto; bottom: -72px; rotate: -12deg; opacity: .5; }
}
@media (min-width: 861px) and (max-width: 1100px) {
  .bg-ring.r1 { width: 40vw; right: -11%; top: 19%; rotate: -12deg; }
  .bg-ring.r2 { width: 30vw; left: -9%; bottom: -66px; }
  .bg-ring.r3 { width: 27vw; right: -7%; bottom: calc(100% - 66px); }
}
@media (max-width: 600px) {
  .bg-ring.r2 { top: 26%; }
  .bg-ring.r4 { width: 56vw; right: -26%; top: auto; bottom: -58px; }
}

/* 2.24: планшет — кольца крупнее (владелец: «не делай их мелкими»), места прежние — сбоку от текста */
@media (min-width: 601px) and (max-width: 860px) {
  .bg-ring.r1 { width: 62vw; } .bg-ring.r2 { width: 42vw; } .bg-ring.r4 { width: 40vw; }
}
@media (min-width: 861px) and (max-width: 1100px) {
  .bg-ring.r1 { width: 46vw; } .bg-ring.r2 { width: 36vw; } .bg-ring.r3 { width: 32vw; }
}