/* ============================================================================
   site/run.css — «Рейс» (site/run.js): каталог как поездка фургона.

   Два состояния одной разметки, как у скролл-фильма:
   • без класса run-on (узкий экран, «уменьшить движение», нет JS или
     WebGL2) — прежний каталог: фургон в середине, плитки рамкой
     (pantry.css, xray.js); части «Рейса» — главы, маршрут, подсказка —
     скрыты;
   • с run-on — раздел в пять экранов пути, внутри липкая сцена во весь
     экран: мир на холсте, поверх — тот же заголовок и та же сетка каталога,
     в которую фургон приезжает и из которой в конце вылетают плитки.

   Класс ставит синхронный скрипт в шапке (build.mjs), до первой раскладки.
   Всё, что двигается, двигает run.js — отдельными свойствами translate /
   scale / rotate и transform пластины; здесь только опоры и состояния.
   ========================================================================== */

/* ── без «Рейса» ───────────────────────────────────────────────────────── */

.run-cap, .run-hud, .run-hint{ display:none }
/* Лид теперь в обёртке (рядом с главами): место в шапке раздела держит она. */
.run-lead{ justify-self:end; max-width:440px }
.run-fit{ display:contents }
@media (max-width:900px){ .run-lead{ justify-self:start; max-width:600px } }

/* ── «Рейс» ────────────────────────────────────────────────────────────── */

.run-on #catalog{
  padding:0; scroll-margin-top:0;
  /* путь меряется замороженным экраном (--vh из шапки), как у фильма */
  height:540vh; height:calc(var(--vh, 1svh) * 540);
}
.run-on #catalog .run-stage{
  position:sticky; top:0;
  height:100vh; height:100svh;
  overflow:hidden; isolation:isolate;
}
.run-canvas{
  position:absolute; inset:0; width:100%; height:100%;
  display:block; z-index:0; pointer-events:none;
}
.run-on #catalog .run-stage > .wrap{
  position:relative; z-index:1; height:100%;
  display:flex; flex-direction:column;
  padding-top:calc(76px + clamp(10px, 2.2vh, 26px));
  padding-bottom:clamp(12px, 2.2vh, 24px);
}
/* Заголовок и главы стоят прямо на чертеже мира: провода, телебашня и
   макушки тополей шли через буквы. Под шапкой раздела — мягкая тень ночи,
   как затемнение под текст в фильме: линии мира гаснут к буквам, а не
   режут их. Слой за текстом, но над холстом (у .wrap свой z-index). */
.run-on #catalog .run-stage > .wrap::before{
  content:""; position:absolute; z-index:-1; left:0; right:0; top:0;
  height:clamp(230px, 38vh, 360px); pointer-events:none;
  background:
    radial-gradient(46% 76% at 21% 50%, rgba(4,7,6,.96), rgba(4,7,6,.86) 42%, transparent),
    radial-gradient(32% 60% at 79% 40%, rgba(4,7,6,.94), rgba(4,7,6,.8) 40%, transparent);
  background:
    radial-gradient(46% 76% at 21% 50%, color-mix(in srgb, var(--night, #040706) 96%, transparent),
      color-mix(in srgb, var(--night, #040706) 86%, transparent) 42%, transparent),
    radial-gradient(32% 60% at 79% 40%, color-mix(in srgb, var(--night, #040706) 94%, transparent),
      color-mix(in srgb, var(--night, #040706) 80%, transparent) 40%, transparent);
}
@media (max-width:999px){
  .run-on #catalog .run-stage > .wrap::before{
    height:clamp(250px, 36vh, 330px);
    background:radial-gradient(95% 80% at 30% 42%, rgba(4,7,6,.95), rgba(4,7,6,.84) 44%, transparent);
    background:radial-gradient(95% 80% at 30% 42%, color-mix(in srgb, var(--night, #040706) 95%, transparent),
      color-mix(in srgb, var(--night, #040706) 84%, transparent) 44%, transparent);
  }
}
.run-on #catalog .provisions-heading{ flex:none; margin-bottom:clamp(12px, 2.4vh, 28px); align-items:start }
.run-on #catalog .provisions-heading h2{ font-size:clamp(26px, min(3.4vw, 5.6vh), 56px) }

/* Сетка каталога вписывается в остаток сцены: 5 колонок × 4 ряда плиток
   1.6:1 при зазоре 12 px — высота = ширина / 2 + 12. Поэтому ширина —
   меньшее из ширины места и (высоты − 12) × 2. */
.run-on .run-fit{ display:grid; place-items:center; flex:1; min-height:0; container-type:size }
@media (min-width:1000px){
  .run-on #catalog .pantry{ width:min(100cqw, (100cqh - 12px) * 2) }
}

/* Пластина фургона ездит целиком (картинка, ценники, пометка): матрицу
   пишет run.js, опора — левый верх, чтобы сдвиг считался от её места в
   сетке. Появление .rv ей не нужно — фургон здесь приезжает сам. */
.run-on #catalog .pantry-van.rv{ opacity:1; transform:none; transition:none }
/* вес — сильнее «клевка» въезда (fx/arrive.css), у которого своя опора */
.run-on #catalog .xr-plate{ transform-origin:0 0; will-change:transform }
/* На общем плане пластина уменьшена, а ценники — нет: читаются тем же
   кеглем (--inv = 1 / масштаб, run.js). */
.run-on .xr-chip{ scale:var(--inv, 1) }
/* Холст нарисовал фургон — картинка под ним больше не нужна. */
.run-gl .xr-img{ opacity:0 }
/* Пометка «пример заказа» — только в каталоге, не посреди рейса. */
.run-on .xr-note{ transition:opacity .4s var(--e-micro) }
.run-on .run-stage:not(.run-end) .xr-note{ opacity:0 }

/* Плитки сидят в кузове до финала. До запуска модуля — тоже: иначе на
   первом кадре каталог стоял бы готовым. Модуль не поднялся — шапка
   снимает run-on через 10 с, и всё видно. Прячем прозрачностью, а не
   visibility: экранный диктор должен читать категории и посреди рейса. */
.run-on:not(.run-boot) #catalog .provision,
.run-hid{ opacity:0; pointer-events:none }

/* Подсказки мышью и пальцем — разные слова: пальцем фургон не протирают,
   а касаются (касание проводит сканер по грузу, run.js). */
.run-touch{ display:none }
@media (hover:none), (pointer:coarse){
  .run-fine{ display:none }
  .run-touch{ display:inline }
}

/* ── главы: на месте лида ──────────────────────────────────────────────── */

.run-on .run-lead{ position:relative }
.run-on .run-cap{ display:block; position:absolute; inset:0; pointer-events:none }
/* Смена глав — по очереди, а не наплывом: уходящая гаснет быстро, новая
   входит с задержкой. При наплыве две фразы на полсекунды читались одна
   поверх другой. */
.run-cap-i{
  position:absolute; left:0; right:0; top:0; margin:0;
  display:grid; gap:6px;
  opacity:0; translate:0 -6px;
  transition:opacity .18s var(--e-micro), translate .18s var(--e-micro);
}
.run-cap-i.is-on{ opacity:1; translate:0 0;
  transition:opacity .42s var(--e-reveal) .16s, translate .42s var(--e-reveal) .16s }
.run-cap-i b{
  font:700 12.5px/1.2 var(--font-body, Manrope, system-ui, sans-serif);
  letter-spacing:.12em; text-transform:uppercase; color:var(--cta);
}
.run-cap-i > span{ font-size:clamp(15px, 1.15vw, 18px); line-height:1.45; color:var(--ink) }
.run-count{ font-style:normal; font-size:13px; color:var(--muted) }
.run-count strong{ font:600 13px/1 "Space Grotesk", Manrope, sans-serif; color:var(--cta); font-variant-numeric:tabular-nums }
.run-on .run-lead .lead{ transition:opacity .42s var(--e-reveal) .16s, translate .42s var(--e-reveal) .16s }
.run-on .run-lead .lead.is-off{ opacity:0; translate:0 -6px; transition:opacity .18s var(--e-micro), translate .18s var(--e-micro) }

/* ── маршрут заказа ────────────────────────────────────────────────────── */

/* Маршрут лежит на месте нижнего ряда плиток — поверх сетки, а не в ней:
   элемент сетки в четвёртом ряду выдавил бы плитки в лишние колонки. */
.run-on #catalog .pantry{ position:relative }
.run-on .run-hud{
  display:grid; align-content:center;
  position:absolute; left:0; right:0; bottom:0; height:calc((100% - 36px) / 4);
  grid-template-columns:minmax(0, 1fr) auto; column-gap:clamp(24px, 4vw, 64px);
  z-index:2; pointer-events:none;
  padding:0 clamp(4px, 1vw, 16px);
}
.run-route, .run-bar{ grid-area:1 / 1 }
.run-route{
  position:relative; z-index:1; margin:0; padding:0; list-style:none;
  display:flex; justify-content:space-between;
}
/* Узлы — точки нулевой ширины по краям и на третях линии; метки висят
   под ними абсолютно (у сетки в нулевом элементе дорожка растягивалась
   под текст, и крайний узел съезжал вправо). */
.run-route li{ position:relative; width:0; min-width:0; height:40px }
.run-route i{
  position:absolute; left:-5.5px; top:0;
  display:block; width:11px; height:11px; border-radius:50%;
  background:var(--night, #040706); box-shadow:inset 0 0 0 1.5px rgba(234,243,239,.32);
  transition:background .3s var(--e-micro), box-shadow .3s var(--e-micro);
}
.run-route span{
  position:absolute; top:23px; left:0; translate:-50% 0;
  white-space:nowrap; font-size:12.5px; letter-spacing:.02em; color:var(--dim);
  transition:color .3s var(--e-micro);
}
.run-route li:first-child span{ translate:-5.5px 0 }
.run-route li:last-child span{ left:auto; right:-5.5px; translate:none }
.run-route li.is-done i{ background:var(--cta); box-shadow:none }
.run-route li.is-now i{ background:var(--night, #040706); box-shadow:inset 0 0 0 2.5px var(--cta), 0 0 14px rgba(217,246,92,.45) }
.run-route li.is-done span, .run-route li.is-now span{ color:var(--ink) }

.run-bar{
  position:relative; align-self:start; margin-top:4.5px; height:2px;
  background:rgba(234,243,239,.14); container-type:inline-size;
}
.run-fill{
  position:absolute; inset:0; background:var(--cta);
  transform-origin:0 50%; transform:scaleX(0);
}
.run-glyph{
  position:absolute; left:0; top:-24px; width:28px; height:14px;
  translate:-50% 0; color:var(--cta);
}
.run-glyph svg{ display:block; width:100%; height:100%; fill:none; stroke:currentColor; stroke-width:1.5; stroke-linecap:round; stroke-linejoin:round }

.run-trip{
  grid-area:1 / 2; margin:0; display:grid; justify-items:end; gap:3px;
  font-variant-numeric:tabular-nums;
}
.run-clock{ font:600 clamp(20px, 1.7vw, 28px)/1 "Space Grotesk", Manrope, sans-serif; color:var(--ink); letter-spacing:-.01em }
.run-dist{ font:500 13px/1.2 "Space Grotesk", Manrope, sans-serif; color:var(--muted) }
.run-items{ font-size:12px; color:var(--dim) }

/* ── подсказка у фургона ───────────────────────────────────────────────── */

.run-on .run-hint{
  display:flex; align-items:center; gap:8px;
  position:absolute; left:0; top:0; z-index:3; margin:0;
  padding:8px 14px 8px 11px; border-radius:999px;
  background:rgba(7,17,14,.8); border:1px solid rgba(143,227,196,.28);
  -webkit-backdrop-filter:blur(10px); backdrop-filter:blur(10px);
  font-size:13px; color:var(--ink); white-space:nowrap;
  opacity:0; pointer-events:none;
  transition:opacity .4s var(--e-micro);
}
.run-on .run-hint.is-on{ opacity:1 }
.run-hint .ic{ width:15px; height:15px; rotate:135deg; color:var(--blue, #8FE3C4);
  fill:none; stroke:currentColor; stroke-width:1.8; stroke-linecap:round; stroke-linejoin:round }

/* ── узкий экран: кадр вертикальный ─────────────────────────────────────
   Фургон почти во всю ширину, над ним город, под ним дорога. Каталог в
   финале — те же плитки тремя колонками под фургоном (pantry.css держит
   фургон сверху до 999 px); вся сетка обязана влезть в сцену: высота =
   ширина / 1.6 + 4 ряда плиток + зазоры ≈ 1.458 · ширина + 24 px. */
@media (max-width:999px){
  .run-on #catalog{ height:480vh; height:calc(var(--vh, 1svh) * 480) }
  .run-on #catalog .run-stage > .wrap{ padding-top:calc(64px + clamp(8px, 1.6vh, 18px)); padding-bottom:12px }
  .run-on #catalog .provisions-heading{ gap:10px; margin-bottom:12px }
  .run-on #catalog .provisions-heading h2{ font-size:clamp(24px, 6.6vw, 34px) }
  .run-on .run-lead{ min-height:5.4em }
  .run-on .run-lead .lead{ font-size:15px }
  .run-cap-i > span{ font-size:14.5px }
  .run-on #catalog .pantry{
    grid-template-columns:repeat(3, minmax(0, 1fr));
    width:min(100cqw, (100cqh - 24px) * 0.6857);
  }
  .run-on #catalog .pantry .provision:nth-child(10){ grid-column:span 2; aspect-ratio:auto }
  .run-on #catalog .pantry .provision:nth-child(11){ grid-column:auto; aspect-ratio:1.6 }
  .run-on #catalog .pantry .provision-top{ left:8px; right:8px; top:6px }
  .run-on #catalog .pantry .provision h3{ font-size:11.5px }
  /* Плитка здесь ~110 px, и имя в две строки («Рыба и морепродукты»,
     «Упаковка и хозтовары») второй строкой ложилось на снимок — тёмные
     буквы по рыбе и коробкам. Светлое поле под именем — выше; еда на
     снимках прижата к низу и остаётся видна. */
  .run-on #catalog .pantry .provision img{
    -webkit-mask-image:linear-gradient(to bottom, transparent 0, transparent 26%, #000 64%);
            mask-image:linear-gradient(to bottom, transparent 0, transparent 26%, #000 64%);
  }
  /* маршрут: поездка сверху строкой, шаги под ней */
  .run-on .run-hud{
    height:auto; bottom:6px; grid-template-columns:minmax(0, 1fr); row-gap:26px; padding:0 2px;
  }
  .run-glyph{ top:-19px; width:24px; height:12px }
  .run-trip{ grid-area:1 / 1; display:flex; justify-content:space-between; align-items:baseline; gap:12px }
  .run-route, .run-bar{ grid-area:2 / 1 }
  .run-route span{ font-size:11px }
  .run-clock{ font-size:22px }
}

/* Пока идёт рейс, топографические линии полотна почти гаснут: у мира свой
   чертёж, два рисунка друг поверх друга читались бы сеткой. */
.run-deep .fx-contours.is-on{ opacity:.02 }

@media (prefers-reduced-motion: reduce){
  .run-cap-i, .run-on .run-lead .lead, .run-route i, .run-route span, .run-hint{ transition:none }
}
