:root{
  /* ---- палитра ---- */
  --field:#0000f2;
  --fg:#f5f5f5;
  --accent:#edff45;
  --paper:#ffffff;
  --grey:#eceaf5;
  --ink:#000000;

  /* ---- гарнитуры ---- */
  --font-display:"Cormorant Garamond", Georgia, serif;
  --font-rules:"Archivo", "Helvetica Neue", Helvetica, sans-serif;
  --font-mono:"Courier Prime", "Courier New", monospace;

  /* ---- шкала типа ---- */
  --fs-display:clamp(2rem, 8.6vw, 8rem);
  --fs-h2:clamp(2rem, 4.4vw, 3.5rem);
  --fs-h3:clamp(1.5rem, 2.2vw, 2.25rem);
  --fs-sum:clamp(2.75rem, 9vw, 7rem);
  --fs-numeral:clamp(2.25rem, 4.6vw, 4rem);
  --fs-statement:clamp(1.25rem, 2.4vw, 2rem);
  --fs-lead:clamp(1.0625rem, 1.6vw, 1.375rem);
  --fs-body:clamp(0.9375rem, 1.05vw, 1.0625rem);
  --fs-mono:0.875rem;
  --fs-mono-s:0.8rem;
  --fs-mono-l:0.9375rem;

  /* интерфейсные подписи и кнопки — гротеск, без засечек */
  --fs-ui:0.8125rem;
  --ls-ui:0.09em;
  --w-ui:600;

  --lh-display:0.88;
  --lh-body:1.5;
  --lh-tight:1.15;

  --ls-mono:0.14em;
  --ls-mono-wide:0.18em;
  --ls-mono-tight:0.1em;

  --w-display:300;
  --w-rules:400;
  --w-rules-md:500;
  --w-rules-sb:600;

  /* ---- метрика ---- */
  --frame:16px;
  --pad-x:clamp(1.5rem, 4vw, 4rem);
  --rule:1px;
  --rule-thick:2px;
  --radius:0px;
  --radius-input:4px;

  --s-1:0.375rem;
  --s-2:0.75rem;
  --s-3:1.25rem;
  --s-4:2rem;
  --s-5:3rem;
  --s-6:4.5rem;
  --s-7:7rem;
  --s-8:clamp(4.5rem, 11vh, 9rem);

  --col-gap:clamp(1.75rem, 3.5vw, 4rem);
  --measure:34ch;
  --measure-wide:52ch;
  --col-label:16rem;
  --form-w:min(100%, 62rem);
  --dur:.18s;

  /* ---- motion ---- */
  --dur-mid:.28s;
  --dur-slow:.6s;
  --ease-out:cubic-bezier(0, 0, .2, 1);
  --reveal-y:12px;
  --lift:2px;

  /* ---- фактура и гравюры ---- */
  --grain-op:.055;
  --vignette:color-mix(in srgb, var(--ink) 26%, transparent);
  --art-op-hero:.42;
  --art-op-plate:.85;
  --art-op-back:.3;     /* плотный кадр за текстом */
  --art-op-sparse:.32;  /* разреженная схема, но её линии проходят прямо через набор */
  --art-op-draft:.55;   /* патентный чертёж на белой панели */
  --art-scale:1.18;
  --tint:color-mix(in oklab, var(--fg) 7%, transparent);
  --z-grain:80;

  /* приглушение для блока-фильтра «когда мы не подойдём» */
  --op-muted:.62;
  --op-soft:.7;
}

*,*::before,*::after{box-sizing:border-box}

html{-webkit-text-size-adjust:100%}

/* штатный lenis.css — без него библиотека вешает класс, но скролл не работает */
html.lenis,
html.lenis body{height:auto}
.lenis.lenis-smooth{scroll-behavior:auto !important}
.lenis.lenis-smooth [data-lenis-prevent]{overscroll-behavior:contain}
.lenis.lenis-stopped{overflow:hidden}

body{
  margin:0;
  background:var(--field);
  color:var(--fg);
  font-family:var(--font-rules);
  font-size:var(--fs-body);
  line-height:var(--lh-body);
  font-weight:var(--w-rules);
  /* overflow-x на body конфликтует с Lenis; горизонтальный вылет
     гасится на самих виновниках — см. .has-art{overflow-x:clip} */
  -webkit-font-smoothing:antialiased;
}

/* фиксированная рамка по краю экрана */
.frame{
  position:fixed;
  inset:0;
  border:var(--frame) solid var(--fg);
  pointer-events:none;
  z-index:90;
}

.shell{padding-inline:var(--pad-x)}

/* ---------- служебная типографика ---------- */
.mono{
  font-family:var(--font-mono);
  font-size:var(--fs-mono);
  letter-spacing:var(--ls-mono);
  text-transform:uppercase;
  line-height:1.4;
}
.mono--s{font-size:var(--fs-mono-s);letter-spacing:var(--ls-mono-wide)}
.mono--l{font-size:var(--fs-mono-l);letter-spacing:var(--ls-mono-tight)}

.rule{border:0;border-top:var(--rule) solid currentColor;margin:0;opacity:.55}

.display{
  font-family:var(--font-display);
  font-weight:var(--w-display);
  line-height:var(--lh-display);
  letter-spacing:0.012em;
  text-transform:uppercase;
  margin:0;
}

/* ---------- шапка ---------- */
.head{
  position:relative;
  z-index:85;   /* ниже рамки (90), выше зерна (80) */
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:var(--s-4);
  padding-block:var(--s-4) var(--s-3);
}
.logo{
  font-family:var(--font-display);
  font-weight:var(--w-display);
  font-size:clamp(1.5rem,2.4vw,2rem);
  line-height:1;
  letter-spacing:0.01em;
  text-transform:none;
  text-decoration:none;
  color:var(--fg);
}
.nav{display:flex;flex-wrap:wrap;gap:var(--s-3);align-items:center}
.nav a{
  position:relative;
  color:var(--fg);
  text-decoration:none;
  padding-bottom:2px;
  transition:color var(--dur) linear;
}
/* подчёркивание выезжает слева направо, а не проявляется целиком */
.nav a::after{
  content:"";
  position:absolute;
  left:0;
  right:0;
  bottom:0;
  height:var(--rule);
  background:currentColor;
  transform:scaleX(0);
  transform-origin:left center;
  transition:transform var(--dur-mid) var(--ease-out);
}
.nav a:hover{color:var(--accent)}
.nav a:hover::after,
.nav a:focus-visible::after{transform:scaleX(1)}
.nav .dot{opacity:.45}
/* «Консультация» — та же кнопка, что на первом экране, но кратно меньше:
   она встаёт в ряд навигации по базовой линии и не спорит с его ритмом */
.btn--mini{
  /* размер задаёт padding, а не кегль: кнопка остаётся на UI-шкале */
  font-size:var(--fs-ui);
  padding:var(--s-1) var(--s-2);
  border-width:var(--rule);
}
/* .nav a (0,1,1) перебивал бы цвет кнопки — поднимаем вес до (0,2,x) */
.nav .btn{color:var(--ink)}
.nav .btn:hover{color:var(--accent)}
.nav .btn::after{display:none}

/* Кнопка в шапке: у .btn отступы 20px сверху и 32px по бокам, а .nav a
   добивает padding-bottom:2px — кнопка получалась несимметричной и
   вылезала на 23px над строкой навигации, к самой рамке экрана.
   Вес (0,2,0) перебивает и .btn, и .nav a. */
.nav .btn--mini{
  align-self:center;
  font-size:0.6875rem;
  letter-spacing:0.08em;
  line-height:1.2;
  padding:0.4rem 0.8rem;
}

/* ---------- первый экран ---------- */
.hero{
  min-height:100vh;
  min-height:100svh;
  display:flex;
  flex-direction:column;
  padding-bottom:var(--s-3);
}
.hero__top{opacity:.8;padding-block:var(--s-5) 0}
.hero__mid{
  flex:1;
  display:flex;
  flex-direction:column;
  justify-content:center;
  gap:var(--s-5);
  padding-block:var(--s-6);
}
.hero__title{font-size:var(--fs-display)}
.hero__title span{display:block}
.hero__grid{
  display:grid;
  grid-template-columns:minmax(0,1.15fr) minmax(0,1fr);
  gap:var(--col-gap);
  align-items:end;
}
.hero__lead{
  font-size:var(--fs-lead);
  line-height:1.35;
  max-width:var(--measure-wide);
  margin:0;
}
.hero__cta{display:flex;flex-direction:column;align-items:flex-start;gap:var(--s-2)}

.btn{
  font-family:var(--font-rules);
  font-size:var(--fs-ui);
  letter-spacing:var(--ls-ui);
  text-transform:uppercase;
  font-weight:var(--w-ui);
  background:var(--accent);
  color:var(--ink);
  border:var(--rule-thick) solid var(--accent);
  border-radius:var(--radius);
  padding:var(--s-3) var(--s-4);
  cursor:pointer;
  display:inline-block;
  text-decoration:none;
  transition:background var(--dur) linear,color var(--dur) linear,
             transform var(--dur-mid) var(--ease-out);
}
.btn:hover{
  background:transparent;
  color:var(--accent);
  transform:translate3d(0,calc(var(--lift) * -1),0);
}
.btn:active{transform:translate3d(0,0,0)}


/* ---------- общая секция ---------- */
.section{padding-block:var(--s-8)}
.section__head{
  display:flex;
  align-items:baseline;
  justify-content:space-between;
  gap:var(--s-4);
  padding-bottom:var(--s-3);
  border-bottom:var(--rule) solid currentColor;
}
.section__title{font-size:var(--fs-h2)}
.section__meta{opacity:.7;text-align:right;white-space:nowrap;flex:none}

/* ---------- три колонки ---------- */
.cols{
  display:grid;
  grid-template-columns:repeat(3,minmax(0,1fr));
  margin-top:var(--s-5);
}
.col{
  position:relative;
  padding:0 var(--col-gap);
  border-left:var(--rule) solid currentColor;
  display:flex;
  flex-direction:column;
  gap:var(--s-3);
}
.col:first-child{padding-left:0;border-left:0}
.col:last-child{padding-right:0}
.col__label{position:relative;display:flex;gap:var(--s-1)}
.col__title,.col__text{position:relative}
.col__num{color:var(--accent)}
.col__num,.case__place{opacity:.85;transition:opacity var(--dur-mid) linear}
.col:hover .col__num,.col:hover .case__place{opacity:1}
.col__title{font-size:var(--fs-h3);line-height:var(--lh-tight)}
.col__text{margin:0;max-width:var(--measure);opacity:.92}

/* ---------- инверсия: калькулятор ---------- */
.paper{
  background:var(--paper);
  color:var(--field);
  margin-block:var(--s-6);
  padding:var(--s-6) clamp(1.5rem,4vw,4rem);
  border:var(--rule-thick) solid var(--field);
}
.calc{
  display:grid;
  /* верхний ряд — поля и рядом счетовод за машиной, нижний ряд — ответ
     во всю ширину: слева считают вручную, ниже сумма, посчитанная за вас */
  grid-template-columns:minmax(0,1fr) minmax(0,1fr);
  gap:var(--col-gap);
  margin-top:var(--s-5);
  align-items:start;
}
.fields{grid-column:1;grid-row:1}
.calc__art{grid-column:2;grid-row:1;align-self:center}   /* у сетки align-items:start — фигура ниже полей и прижималась к верху строки */
.result{grid-column:1 / -1;grid-row:2}
.fields{display:grid;gap:var(--s-3)}
.field{display:grid;gap:var(--s-1)}

/* подписи полей — гротеск, а не Courier: у моноширинной антиквы
   на мелком кегле засечки дробят строку и мешают читать форму */
.field label{
  font-family:var(--font-rules);
  font-size:var(--fs-ui);
  letter-spacing:var(--ls-ui);
  font-weight:var(--w-ui);
  text-transform:uppercase;
  opacity:.75;
}
.field input{
  font-family:var(--font-mono);
  font-size:clamp(1.125rem,2vw,1.5rem);
  color:var(--field);
  background:transparent;
  border:var(--rule-thick) solid var(--field);
  border-radius:var(--radius-input);
  padding:var(--s-2) var(--s-3);
  width:100%;
  min-height:56px;
  appearance:textfield;
  -moz-appearance:textfield;
  /* «утолщение рамки» сделано outline'ом: он не участвует в раскладке,
     поэтому анимация не вызывает пересчёта */
  outline:0 solid currentColor;
  transition:outline-width var(--dur-mid) var(--ease-out);
}
.field input:hover{outline-width:var(--rule-thick)}
.field input::-webkit-outer-spin-button,
.field input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}
.field input:focus{outline:var(--rule-thick) solid var(--field);outline-offset:2px}

.result{
  border:var(--rule-thick) solid var(--field);
  border-radius:var(--radius);
  padding:var(--s-4);
  display:flex;
  flex-direction:column;
  gap:var(--s-2);
  background:var(--grey);
  min-width:0;
}
.result__sum{
  font-family:var(--font-display);
  font-weight:var(--w-display);
  font-size:var(--fs-sum);
  line-height:0.95;
  letter-spacing:0;
  overflow-wrap:anywhere;
}
.result__note{opacity:.7;max-width:var(--measure)}
/* у абзацев внутри блока остаются дефолтные margin в 1em — на кегле суммы
   это 112px сверху и снизу, из-за чего широкая полоса ответа пустеет */
.result > *{margin:0}
.result__line{border-top:var(--rule) solid var(--field);opacity:.4;margin:0}

/* ---------- кейсы ---------- */
.case__place{color:var(--accent)}

/* ---------- финал ---------- */
.final{
  min-height:100vh;
  min-height:100svh;
  display:flex;
  flex-direction:column;
  justify-content:center;
  gap:var(--s-5);
  padding-block:var(--s-8);
}
.final__title{font-size:var(--fs-display)}
.form{
  display:grid;
  grid-template-columns:minmax(0,1fr) minmax(0,1fr) auto;
  gap:var(--s-3);
  align-items:end;
  max-width:var(--form-w);
  width:100%;
}
.form .field label{opacity:.75}
.form .field input{
  color:var(--fg);
  border-color:var(--fg);
  font-size:clamp(1rem,1.4vw,1.125rem);
}
.form .field input:focus{outline-color:var(--fg)}
.form .field input::placeholder{color:var(--fg);opacity:.4}

/* ---------- общие текстовые блоки ---------- */
.lede{
  font-size:var(--fs-lead);
  line-height:1.35;
  max-width:var(--measure-wide);
  margin:var(--s-4) 0 0;
}
.statement{
  font-size:var(--fs-statement);
  line-height:1.25;
  max-width:var(--measure-wide);
  margin:var(--s-5) 0 0;
}
.note{
  margin:var(--s-4) 0 0;
  max-width:var(--measure-wide);
  opacity:var(--op-soft);
}
.note--s{font-size:var(--fs-ui)}
.note a{
  color:inherit;
  text-decoration:underline;
  text-underline-offset:0.25em;
  transition:color var(--dur) linear;
}
.note a:hover{color:var(--accent)}

/* ---------- сетка 2×2 с жёсткими линиями ---------- */
.grid2{
  display:grid;
  grid-template-columns:repeat(2,minmax(0,1fr));
  margin-top:var(--s-5);
}
.grid2 > *{
  padding:var(--s-4) var(--col-gap);
  border-top:var(--rule) solid currentColor;
  border-left:var(--rule) solid currentColor;
  display:flex;
  flex-direction:column;
  gap:var(--s-2);
}
.grid2 > *:nth-child(odd){padding-left:0;border-left:0}
.grid2 > *:nth-child(even){padding-right:0}

.cell__num{
  font-family:var(--font-mono);
  font-size:var(--fs-numeral);
  line-height:1;
  letter-spacing:-0.02em;
  color:var(--accent);
}
.cell__lede{
  margin:0;
  font-size:var(--fs-lead);
  line-height:1.28;
  max-width:var(--measure);
}
.cell__lede--sb{font-weight:var(--w-rules-sb)}
.cell__text{margin:0;max-width:var(--measure);opacity:.88}

/* ---------- таблица интеграций ---------- */
.rows{margin-top:var(--s-5);border-top:var(--rule) solid currentColor}
.row{
  display:grid;
  grid-template-columns:minmax(0,var(--col-label)) minmax(0,1fr);
  gap:var(--col-gap);
  align-items:baseline;
  padding-block:var(--s-3);
  border-bottom:var(--rule) solid currentColor;
}
.row__label{margin:0;color:var(--accent)}
.row__value{margin:0;font-size:var(--fs-lead);line-height:1.35}

/* ---------- кто мы ---------- */
.paper--air{padding-block:var(--s-8)}
.manifest{
  display:grid;
  grid-template-columns:minmax(0,1.5fr) minmax(0,1fr);
  gap:var(--col-gap);
  align-items:start;
  margin-top:var(--s-6);
}
.manifest__claim{font-size:var(--fs-h2)}
.facts{border-top:var(--rule) solid currentColor}
.fact{
  display:flex;
  align-items:baseline;
  gap:var(--s-2);
  margin:0;
  padding-block:var(--s-3);
  border-bottom:var(--rule) solid currentColor;
}
.fact__num{
  font-family:var(--font-mono);
  font-size:var(--fs-h3);
  line-height:1;
  flex:none;
}
.fact__label{opacity:var(--op-soft)}

/* ---------- блок-фильтр ---------- */
/* Секция про границы — не список, а замкнутый объект: жёсткая рамка в две
   линии и есть та самая граница, о которой говорит текст. Внутри поле
   разделено на четыре клетки, в каждой крупный моноширинный крест.
   Набор идёт в полную силу — блок отсекает уверенно, а не виновато;
   приглушены только сами кресты, чтобы они не спорили с текстом. */
.filter{
  margin-top:var(--s-5);
  display:grid;
  grid-template-columns:repeat(2, minmax(0,1fr));
  border:var(--rule-thick) solid currentColor;
}
.filter__cell{
  display:flex;
  flex-direction:column;
  gap:var(--s-3);
  padding:var(--s-5) var(--col-gap);
  border-top:var(--rule) solid currentColor;
  border-left:var(--rule) solid currentColor;
}
.filter__cell:nth-child(-n+2){border-top:0}
.filter__cell:nth-child(odd){border-left:0}
.filter__mark{
  font-family:var(--font-mono);
  font-size:var(--fs-numeral);
  line-height:1;
  opacity:.4;
}
.filter__text{
  margin:0;
  font-size:var(--fs-lead);
  line-height:1.3;
  max-width:var(--measure);
}

/* ============ МАРШРУТ: «с чего начинаем» ============ */

/* ---------- с чего начинаем: вертикальный маршрут ---------- */
/* Путь идёт сверху вниз — направление совпадает с жестом прокрутки,
   поэтому прочерчивание читается буквально. Слева рельс, от него засечка
   к номеру шага, справа текст. Ступени разделены линиями во всю ширину. */
.section--air{padding-block:calc(var(--s-8) + var(--s-4))}
.route{
  --route-p:1;          /* доля прочерченного пути: без JS — весь */
  --route-gut:clamp(5rem, 11vw, 9rem);
  position:relative;
  margin:var(--s-6) 0 0;
  padding:0;
  list-style:none;
}
/* трек во всю длину и поверх него прочерченная часть; растёт scaleY,
   раскладка при этом не пересчитывается */
.route::before,
.route::after{
  content:"";
  position:absolute;
  left:0;
  top:0;
  bottom:0;
  width:var(--rule);
}
.route::before{background:currentColor;opacity:.22}
.route::after{
  background:var(--accent);
  transform-origin:top center;
  transform:scaleY(var(--route-p));
}
/* остриё на конце пути: две линии, без заливок */
.route__end{
  position:absolute;
  left:0;
  bottom:0;
  width:var(--s-2);
  height:var(--s-2);
  border-right:var(--rule) solid var(--accent);
  border-bottom:var(--rule) solid var(--accent);
  transform:translate(-50%, 50%) rotate(45deg) scale(1);
  transition:transform var(--dur-mid) var(--ease-out);
}

.route__step{
  position:relative;
  display:grid;
  grid-template-columns:var(--route-gut) minmax(0,1fr);
  gap:0 var(--col-gap);
  align-items:center;
  padding:var(--s-5) 0;
  border-top:var(--rule) solid currentColor;
}
.route__step:last-child{border-bottom:var(--rule) solid currentColor}

/* засечка и номер стоят в одной строке: засечка тянется от рельса
   и упирается в номер */
.route__mark{
  display:flex;
  align-items:center;
  gap:var(--s-2);
  align-self:center;
}
.route__tick{
  flex:1;
  height:var(--rule);
  background:currentColor;
  transform:scaleX(1);
  transform-origin:left center;
  transition:transform var(--dur-mid) var(--ease-out);
}
.route__num{
  flex:none;
  font-family:var(--font-mono);
  font-size:var(--fs-numeral);
  line-height:1;
  letter-spacing:-0.02em;
  transition:opacity var(--dur-mid) var(--ease-out),
             color var(--dur-mid) linear;
}
.route__text{
  margin:0;
  font-size:var(--fs-lead);
  line-height:1.3;
  max-width:var(--measure-wide);
  transition:opacity var(--dur-slow) var(--ease-out),
             transform var(--dur-slow) var(--ease-out);
}

/* Начальное состояние вешается только под js-anim и завёрнуто в :where(),
   чтобы правила подсветки выигрывали по специфичности, а не по порядку.
   Без JS и под prefers-reduced-motion класса нет — путь прочерчен целиком,
   все шаги видны и спокойны. */
html.js-anim .route{--route-p:0}
html.js-anim :where(.route__tick){transform:scaleX(0)}
html.js-anim :where(.route__num){opacity:.26}
html.js-anim :where(.route__text){
  opacity:.28;
  transform:translate3d(0, var(--reveal-y), 0);
}
html.js-anim :where(.route__end){transform:translate(-50%, 50%) rotate(45deg) scale(0)}

/* линия дошла до шага — он зажигается */
.route__step.is-lit .route__tick{transform:scaleX(1)}
.route__step.is-lit .route__num{opacity:1}
.route__step.is-lit .route__text{opacity:.92;transform:translate3d(0,0,0)}
/* активен ровно один; пройденные возвращаются в спокойное состояние */
.route__step.is-active .route__num{color:var(--accent)}
.route__step.is-active .route__text{opacity:1}
.route.is-complete .route__end{transform:translate(-50%, 50%) rotate(45deg) scale(1)}

.start__cta{margin-top:var(--s-6)}

/* ---------- вопросы ---------- */
.faq{margin-top:0}
.faq details{border-bottom:var(--rule) solid currentColor}
.faq summary{
  display:flex;
  align-items:baseline;
  justify-content:space-between;
  gap:var(--col-gap);
  padding-block:var(--s-4);
  font-size:var(--fs-lead);
  line-height:1.3;
  cursor:pointer;
  list-style:none;
  transition:color var(--dur) linear;
}
.faq summary::-webkit-details-marker{display:none}
.faq summary:hover{color:var(--accent)}
.faq summary:focus-visible{outline:var(--rule) solid currentColor;outline-offset:var(--s-1)}
.faq__sign{
  font-family:var(--font-mono);
  font-size:var(--fs-lead);
  flex:none;
  line-height:1;
  display:inline-block;
  transition:transform var(--dur-mid) var(--ease-out);
}
.faq__sign::after{content:"+"}
/* знак синхронизирован с анимацией, а не с атрибутом open:
   при закрытии он поворачивается вместе со схлопыванием */
.faq details.is-open .faq__sign{transform:rotate(45deg)}
.faq__answer{
  margin:0;
  padding-block:0 var(--s-4);
  max-width:var(--measure-wide);
  opacity:.88;
}
/* Раскрытие через grid-template-rows: 0fr → 1fr. Правила включаются только
   после того, как скрипт пометит список классом is-enhanced, — без JS
   остаётся штатное поведение <details> и ответ виден. */
.faq.is-enhanced .faq__wrap{
  display:grid;
  grid-template-rows:0fr;
  transition:grid-template-rows var(--dur-slow) var(--ease-out),
             opacity var(--dur-mid) var(--ease-out);
  opacity:0;
}
.faq.is-enhanced details.is-open .faq__wrap{
  grid-template-rows:1fr;
  opacity:1;
}
.faq.is-enhanced .faq__inner{overflow:hidden;min-height:0}

/* ---------- зерно и виньетка поверх всего ---------- */
.grain{
  position:fixed;
  inset:0;
  pointer-events:none;
  z-index:var(--z-grain);
}
/* тайл шума генерирует canvas на старте; без JS слой просто пустой */
.grain::before{
  content:"";
  position:absolute;
  inset:0;
  background-image:var(--noise, none);
  background-repeat:repeat;
  background-size:128px 128px;
  opacity:var(--grain-op);
}
.grain::after{
  content:"";
  position:absolute;
  inset:0;
  background:radial-gradient(ellipse at center, transparent 52%, var(--vignette) 100%);
}

/* ---------- гравюры ---------- */
.hero{position:relative}
.hero__top,.hero__mid{position:relative;z-index:1}
/* гравюра занимает верхнюю правую четверть и не заходит на нижнюю строку
   с лидом, кнопкой и подписью — там текст должен остаться чистым */
.hero__art{
  position:absolute;
  top:0;
  right:calc(var(--pad-x) * -1);
  bottom:38%;
  width:min(54vw, 820px);
  z-index:0;
  overflow:hidden;
  pointer-events:none;
  display:flex;
  align-items:center;
  justify-content:flex-end;
  /* правый край уходит под рамку экрана, поэтому он единственный резкий */
  --fade-t:34%;
  --fade-r:18%;
  --fade-b:54%;
  --fade-l:26%;
}
.hero__art img{
  width:100%;
  height:auto;
  opacity:var(--art-op-hero);
  transform:translate3d(0, var(--py, 0px), 0) scale(var(--art-scale));
  transform-origin:center right;
  will-change:transform;
}

.plate{
  position:relative;
  --fade-t:12%;
  --fade-r:10%;
  --fade-b:18%;
  --fade-l:10%;
  margin:var(--s-5) 0 0;
  height:clamp(200px, 38vh, 420px);
  overflow:hidden;
  pointer-events:none;
}
.plate img{
  width:100%;
  height:100%;
  object-fit:cover;
  object-position:center 42%;
  opacity:var(--art-op-plate);
  transform:translate3d(0, var(--py, 0px), 0) scale(var(--art-scale));
  will-change:transform;
}

/* Общий приём для всех гравюр: маска гасит изображение в прозрачность
   по каждому краю, выходящему в поле. Глубина затухания настраивается
   на месте через --fade-t/-r/-b/-l; 0% оставляет край резким. */
.art-fade{
  --fade-t:12%;
  --fade-r:12%;
  --fade-b:12%;
  --fade-l:12%;
  /* сход по S-кривой: у линейного градиента место, где он выходит на
     полную непрозрачность, читается полосой — промежуточные стопы её убирают */
  -webkit-mask-image:
    linear-gradient(to bottom,
      transparent 0%,
      rgba(0,0,0,.10) calc(var(--fade-t) * .30),
      rgba(0,0,0,.42) calc(var(--fade-t) * .58),
      rgba(0,0,0,.80) calc(var(--fade-t) * .82),
      #000 var(--fade-t),
      #000 calc(100% - var(--fade-b)),
      rgba(0,0,0,.80) calc(100% - var(--fade-b) * .82),
      rgba(0,0,0,.42) calc(100% - var(--fade-b) * .58),
      rgba(0,0,0,.10) calc(100% - var(--fade-b) * .30),
      transparent 100%),
    linear-gradient(to right,
      transparent 0%,
      rgba(0,0,0,.10) calc(var(--fade-l) * .30),
      rgba(0,0,0,.42) calc(var(--fade-l) * .58),
      rgba(0,0,0,.80) calc(var(--fade-l) * .82),
      #000 var(--fade-l),
      #000 calc(100% - var(--fade-r)),
      rgba(0,0,0,.80) calc(100% - var(--fade-r) * .82),
      rgba(0,0,0,.42) calc(100% - var(--fade-r) * .58),
      rgba(0,0,0,.10) calc(100% - var(--fade-r) * .30),
      transparent 100%);
  mask-image:
    linear-gradient(to bottom,
      transparent 0%,
      rgba(0,0,0,.10) calc(var(--fade-t) * .30),
      rgba(0,0,0,.42) calc(var(--fade-t) * .58),
      rgba(0,0,0,.80) calc(var(--fade-t) * .82),
      #000 var(--fade-t),
      #000 calc(100% - var(--fade-b)),
      rgba(0,0,0,.80) calc(100% - var(--fade-b) * .82),
      rgba(0,0,0,.42) calc(100% - var(--fade-b) * .58),
      rgba(0,0,0,.10) calc(100% - var(--fade-b) * .30),
      transparent 100%),
    linear-gradient(to right,
      transparent 0%,
      rgba(0,0,0,.10) calc(var(--fade-l) * .30),
      rgba(0,0,0,.42) calc(var(--fade-l) * .58),
      rgba(0,0,0,.80) calc(var(--fade-l) * .82),
      #000 var(--fade-l),
      #000 calc(100% - var(--fade-r)),
      rgba(0,0,0,.80) calc(100% - var(--fade-r) * .82),
      rgba(0,0,0,.42) calc(100% - var(--fade-r) * .58),
      rgba(0,0,0,.10) calc(100% - var(--fade-r) * .30),
      transparent 100%);
  -webkit-mask-composite:source-in;
  mask-composite:intersect;
}

/* секция-носитель гравюры: своя система координат, чтобы z-index:-1
   у подложки уходил под набор, но оставался над фоном самой секции.
   overflow-x:clip держит вылетающие за край кадры, не создавая
   скролл-контейнер, — липкие шапки внутри продолжают работать */
.has-art{position:relative;isolation:isolate;overflow-x:clip}
.art{
  position:absolute;
  z-index:-1;
  overflow:hidden;
  pointer-events:none;
  display:flex;
}
/* ПРАВИЛО ДЛЯ ВСЕХ ПОДЛОЖЕК.
   Маска обязана жить на том же боксе, который режет изображение. Если бокс
   уходит за своего отсекающего предка (.has-art{overflow-x:clip}), градиент
   доходит до нуля уже ЗА линией реза, и на ней остаётся ступенька — сколько
   ни увеличивай --fade-r. Поэтому подложки прижаты к внутреннему краю секции,
   а «больше кадра» даёт --art-bleed: изображение шире своего бокса и режется
   им же, так что растворение и рез совпадают по определению.
   Обратный случай — картинка ýже бокса (.col__art, .calc__art): там маска
   висит на самом <img>, иначе она села бы на пустое поле летербокса. */
.art img{
  display:block;
  flex:none;
  width:calc(100% + var(--art-bleed, 0px));
  max-width:none;
  height:auto;
  transform:translate3d(0, var(--py, 0px), 0) scale(var(--art-scale));
}

/* «Проблема» — полоса в потоке, уже, чем плита в «Кейсах» */
.plate--slim{height:clamp(160px, 26vh, 300px);--fade-b:32%;--fade-t:16%}

/* Калькулятор — чертёж занял собственную, третью колонку сетки:
   блок результата больше его не накрывает */
.calc__art{
  position:relative;
  --fade-t:12%;
  --fade-r:14%;
  --fade-b:12%;
  --fade-l:10%;
  margin:0;
  height:clamp(280px, 34vh, 470px);
  display:flex;
  align-items:center;
  justify-content:center;
  overflow:hidden;
  pointer-events:none;
}
/* маска накладывается на сам <img>: на боксе фигуры она не достала бы
   до краёв кадра, и он остался бы с резким прямоугольным обрезом */
.calc__art img{
  height:100%;
  width:auto;
  max-width:100%;
  display:block;
  opacity:var(--art-op-draft);
  transform:translate3d(0, var(--py, 0px), 0);
}

/* «Три слоя» — своя гравюра в каждой колонке, над меткой.
   Общая высота бокса держит колонки на одной линии, contain
   сохраняет каждый кадр целиком, нижняя привязка ставит их
   на общую опорную линию */
.col__art{
  position:relative;
  --fade-t:18%;
  --fade-r:14%;
  --fade-b:16%;
  --fade-l:14%;
  margin:0;
  height:clamp(150px, 19vh, 230px);
  display:flex;
  align-items:flex-end;
  justify-content:center;
  overflow:hidden;
  pointer-events:none;
}
/* высота фиксирована, ширина считается от пропорций файла — бокс совпадает
   с изображением, поэтому маска гасит именно его края, а не пустое поле
   вокруг летербокса (из-за него у телетайпа был резкий прямоугольник) */
.col__art img{
  height:100%;
  width:auto;
  max-width:100%;
  display:block;
  opacity:var(--art-op-plate);
  transform:translate3d(0, var(--py, 0px), 0);
}

/* «Отличие» — дисковый аппарат вынесен за правый край экрана */
.art--dial{
  top:26%;
  right:0;
  width:min(34vw, 420px);
  --art-bleed:8vw;
  --fade-t:26%;
  --fade-r:26%;
  --fade-b:26%;
  --fade-l:34%;
}
.art--dial img{opacity:var(--art-op-back)}

/* «Интеграции» — схема уведена вбок, в правую половину: колонка меток
   и начало перечислений остаются на чистом поле */
.art--wiring{
  right:0;
  top:18%;
  bottom:4%;
  width:min(50vw, 700px);
  align-items:center;
  --art-bleed:6vw;
  --fade-t:14%;
  --fade-r:20%;
  --fade-b:14%;
  --fade-l:34%;
}
.art--wiring img{opacity:var(--art-op-sparse)}

/* «Поговорим» — арка уходит крупно за правый край, заголовок ложится
   на неё, форма собрана в сетку 2×2 под ним */
.final__art{
  position:absolute;
  z-index:-1;
  top:50%;
  right:0;
  width:min(52vw, 720px);
  --art-bleed:10vw;
  /* у фигуры не было собственного overflow — резала секция, поэтому
     градиент заканчивался за линией реза. Теперь режет она сама */
  overflow:hidden;
  --fade-t:14%;
  --fade-r:20%;
  --fade-b:16%;
  --fade-l:22%;
  margin:0;
  /* поднята так, чтобы арка перекрывала правую часть заголовка,
     а не висела отдельным пятном под формой */
  transform:translateY(-58%);
  pointer-events:none;
}
.final__art img{
  display:block;
  width:calc(100% + var(--art-bleed, 0px));
  max-width:none;
  height:auto;
  opacity:calc(var(--art-op-back) * 1.35);
  transform:translate3d(0, var(--py, 0px), 0);
}
.form--final{
  grid-template-columns:repeat(2, minmax(0,1fr));
  max-width:min(100%, 46rem);
  gap:var(--s-3) var(--col-gap);
}
.form--final > .btn{grid-column:1 / -1;justify-self:start;margin-top:var(--s-2)}

/* крупные цифры едут медленнее полосы набора */
.cell__num{
  display:inline-block;
  transform:translate3d(0, var(--py, 0px), 0);
}

/* одна линия на одну смысловую границу:
   в «Проблеме» плита стыкуется с сеткой без зазора,
   в «Интеграциях» подчёркивание заголовка служит верхом таблицы */
#problem .plate--slim{margin-top:var(--s-4)}
#problem .plate + .grid2{margin-top:0}
.rows{margin-top:0;border-top:0}

/* ---------- появление по скроллу ---------- */
/* Список целей завёрнут в :where() — он не добавляет специфичности,
   поэтому начальное состояние весит ровно (0,1,1) для ЛЮБОЙ цели,
   включая селекторы с тегом (.hero__title span, .faq details).
   Правило показа (0,2,1) выигрывает у всех гарантированно, а не по
   порядку следования. */
html.js-anim :where(
  .section__head,
  .hero__top,
  .hero__title span,
  .hero__grid,
  .grid2 > *,
  .col,
  .row,
  .fact,
  .filter__cell,
  .faq details,
  .lede,
  .statement,
  .note,
  .plate,
  .calc,
  .manifest__claim,
  .start__cta,
  .final__title,
  .form,
  .foot,
  .section > .rule
){
  opacity:0;
  transform:translate3d(0, var(--reveal-y), 0);
  transition:opacity var(--dur-slow) var(--ease-out),
             transform var(--dur-slow) var(--ease-out);
}
html.js-anim .is-in{
  opacity:1;
  transform:translate3d(0, 0, 0);
}
/* ---------- подвал ---------- */
.foot{
  border-top:var(--rule) solid currentColor;
  padding-block:var(--s-5) var(--s-4);
  margin-top:var(--s-6);
  overflow-x:clip;
}
.foot__mark{
  display:block;
  font-size:clamp(3.5rem, 43vw, 40rem);
  line-height:.8;
  text-transform:none;
  letter-spacing:0.005em;
  color:inherit;
  text-decoration:none;
}
.foot__row{
  display:flex;
  flex-wrap:wrap;
  align-items:baseline;
  justify-content:space-between;
  gap:var(--s-3) var(--col-gap);
  margin-top:var(--s-4);
  padding-top:var(--s-3);
  border-top:var(--rule) solid currentColor;
  opacity:.8;
}
.foot__nav{display:flex;flex-wrap:wrap;gap:var(--s-3)}
.foot__meta{display:flex;flex-wrap:wrap;gap:var(--s-3)}
.foot__row a{
  color:inherit;
  text-decoration:none;
  border-bottom:var(--rule) solid transparent;
  transition:color var(--dur) linear,border-color var(--dur) linear;
}
.foot__row a:hover{color:var(--accent);border-bottom-color:var(--accent)}

@media (max-width:900px){
  :root{--frame:8px}
  .hero__grid{grid-template-columns:minmax(0,1fr)}
  .cols{grid-template-columns:minmax(0,1fr);gap:var(--s-5)}
  .col{padding:var(--s-4) 0 0;border-left:0;border-top:var(--rule) solid currentColor}
  .col:first-child{padding-top:var(--s-4);border-top:var(--rule) solid currentColor}
  .calc{grid-template-columns:minmax(0,1fr)}
  .form{grid-template-columns:minmax(0,1fr)}
  .section__head{flex-direction:column;align-items:flex-start;gap:var(--s-2)}
  .section__meta{text-align:left}
  .nav{gap:var(--s-2)}
  .paper{padding:var(--s-5) var(--s-3)}
  .paper--air{padding-block:var(--s-6)}

  .grid2{grid-template-columns:minmax(0,1fr)}
  .grid2 > *{padding:var(--s-4) 0;border-left:0}

  .row{grid-template-columns:minmax(0,1fr);gap:var(--s-2)}

  .manifest{grid-template-columns:minmax(0,1fr);margin-top:var(--s-5)}

  .route{--route-gut:clamp(3.5rem, 16vw, 5.5rem);margin-top:var(--s-5)}
  .route__step{padding:var(--s-4) 0;gap:var(--s-3) var(--s-3)}
  .filter{grid-template-columns:minmax(0,1fr)}
  .filter__cell{padding:var(--s-4) var(--s-3);border-left:0;border-top:var(--rule) solid currentColor}
  .filter__cell:first-child{border-top:0}

  .faq summary{gap:var(--s-3)}
  .section--air{padding-block:var(--s-8)}

  /* на узком экране гравюра уходит за текст целиком и притухает,
     иначе она конкурирует с заголовком */
  .hero__art{
    left:calc(var(--pad-x) * -1);
    right:calc(var(--pad-x) * -1);
    width:auto;
    bottom:34%;
    justify-content:center;
  }
  .hero__art img{width:160%;opacity:calc(var(--art-op-hero) * .75)}
  .plate{height:clamp(180px, 30vh, 280px)}
  .plate--slim{height:clamp(140px, 22vh, 220px)}
  .col__art{height:clamp(130px, 16vh, 190px)}
  .calc__art{
    grid-column:1;
    grid-row:auto;
    height:clamp(200px, 26vh, 300px);
    margin-top:var(--s-4);
  }
  .fields,.result{grid-column:1;grid-row:auto;margin-top:0}
  .form--final{grid-template-columns:minmax(0,1fr)}
  .final__art{
    right:0;
    width:100%;
    --art-bleed:26vw;
    --fade-l:22%;
  }
  .final__art img{opacity:calc(var(--art-op-back) * .7)}
  .foot__mark{font-size:clamp(3rem, 40vw, 12rem)}
  .foot__row{flex-direction:column;align-items:flex-start}

  .art--dial{top:auto;bottom:2%;right:0;width:66vw;--art-bleed:12vw}
  .art--wiring{top:14%;bottom:2%;width:auto;left:0;right:0;--art-bleed:0px}
  .art--wiring img{opacity:calc(var(--art-op-sparse) * .8)}
}

/* ---------- без анимации ---------- */
@media (prefers-reduced-motion: reduce){
  *,
  *::before,
  *::after{
    animation-duration:.01ms !important;
    animation-iteration-count:1 !important;
    transition-duration:.01ms !important;
  }
  .hero__art img,
  .plate img,
  .art img,
  .col__art img,
  .calc__art img,
  .final__art img,
  .cell__num{transform:none !important}
}

/* поле-ловушка от спам-ботов: убрано с экрана и из обхода клавиатурой,
   человек его не видит и не заполнит, автомат — заполнит */
.hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}
.form__error{padding-top:var(--s-2);color:var(--accent)}
.btn[disabled]{opacity:.6;cursor:progress}

/* Без этого правила скрытие не работает: у .form стоит display:grid,
   а вес у него тот же, что у браузерного [hidden]{display:none} —
   побеждает то, что ниже по файлу, то есть grid. */
[hidden]{display:none !important}

/* состояние «отправлено»: занимает место формы, текст по центру её ширины.
   Набор гротеском, а не антиквой — это служебное сообщение, не заголовок. */
.sent{
  width:100%;
  max-width:min(100%, 46rem);
  display:flex;
  flex-direction:column;
  align-items:center;
  gap:var(--s-2);
  padding-block:var(--s-5);
  text-align:center;
}
.sent__title{
  margin:0;
  font-family:var(--font-rules);
  font-size:clamp(1.5rem, 3vw, 2.25rem);
  font-weight:var(--w-rules-md);
  line-height:1.15;
  letter-spacing:-0.01em;
  color:var(--accent);
}
.sent__note{
  margin:0;
  font-family:var(--font-rules);
  font-size:var(--fs-lead);
  opacity:.85;
}
