/* ============================================================================
   site/wall.css — СТЕНА ПОСТАВЩИКОВ и КАРТОЧКА-ПОРТАЛ.

   Устройство в трёх словах: барабан из светлых плит над сеточным полом.
   Нажали на плиту — из середины экрана раскрывается жидкое кольцо, и внутри
   кольца лежит карточка поставщика.

   Почему плиты СВЕТЛЫЕ на тёмной сцене. Логотипы придут чужие: у одного знак
   чёрный, у другого цветной, у третьего белый с тонкой линией. На тёмном
   фоне половина из них пропадёт, и стена развалится на «видимые» и
   «невидимые» бренды. Светлая плита — это лист, на котором любой знак стоит
   одинаково уверенно; тёмная плита остаётся только для знаков, нарисованных
   белым (в списке это mono:true).

   Три состояния у одной и той же разметки:
     • без JS      — обычная сетка карточек, страница целая и в поиске;
     • .is-live    — барабан в перспективе (ставит wall.js);
     • .is-flat    — на телефоне и при «уменьшить движение»: лента с
                     прилипанием, родная прокрутка пальцем.

   Движение здесь — transform и opacity. Никаких фильтров на карточках:
   blur/brightness на десяти плитах роняют кадр на слабой машине, а глубину
   так же честно даёт затемняющая накладка.
   ========================================================================== */

/* Секция БЕЗ overflow:hidden. Обрезает барабан сама сцена (.wall-stage), а
   на секции клип срезал бы ровной линией и цветной замес стыка, и чёрную
   вымывку комнаты — ту самую линию во всю ширину, из-за которой раздел
   читался «вставленным прямоугольником». */
.wall-sect{ position:relative }

/* Сцена во всю ширину, а шапка раздела — в общей колонке. Барабану нужна
   ширина: обрезанные по краям соседние плиты и есть ощущение, что стена
   продолжается за экран. */
.wall{ position:relative; margin-top:clamp(28px,3.6vw,56px) }

/* ─────────────────────────── плита ───────────────────────────
   Одна разметка на все три состояния: меняется только раскладка. */

.wall-track{ list-style:none; margin:0 auto; padding:0 var(--pad);
  max-width:var(--maxw);
  display:grid; gap:var(--gap);
  grid-template-columns:repeat(auto-fill,minmax(min(100%,230px),1fr)) }

.wall-card{ --tint:var(--cta); --k:0; position:relative }

.wall-plate{
  appearance:none; -webkit-appearance:none; width:100%; margin:0; border:0;
  /* Без этого Android на каждый тап по невидимой кнопке-плите кладёт серую
     вспышку ПОВЕРХ картинки WebGL — лента читается сломанной. */
  -webkit-tap-highlight-color:transparent;
  font:inherit; color:var(--paper-ink); text-align:left; cursor:pointer;
  display:grid; grid-template-rows:1fr auto; gap:10px;
  padding:clamp(16px,1.5vw,24px);
  border-radius:clamp(18px,1.6vw,26px);
  background:linear-gradient(168deg,#FCFDFC 0%, #EBF1EC 58%, #DDE6DF 100%);
  /* Третья тень — не тень, а цветная подошва в цвет знака. Она делает стену
     из десяти светлых прямоугольников стеной из десяти РАЗНЫХ брендов,
     ничего не добавляя в разметку. */
  box-shadow:0 1px 2px rgba(6,14,11,.22), 0 26px 52px -34px rgba(0,0,0,.9),
    inset 0 -3px 0 0 var(--tint);
  position:relative; overflow:hidden; isolation:isolate;
  transition:transform .32s var(--e-micro), box-shadow .32s var(--e-micro);
}

/* Цвет бренда — не заливка, а свечение под знаком. Четверть непрозрачности:
   чужой оттенок так не спорит с зелёной палитрой сайта. */
.wall-plate::before{
  content:''; position:absolute; inset:0; z-index:-1; opacity:.26;
  background:radial-gradient(115% 82% at 50% 6%, var(--tint), transparent 68%);
}

/* Тёмная плита — для знаков, нарисованных белым. */
.wall-card.is-mono .wall-plate{
  background:linear-gradient(168deg,#17241F 0%, #101A16 60%, #0B1310 100%);
  color:var(--ink);
  box-shadow:0 1px 2px rgba(0,0,0,.5), 0 26px 52px -34px rgba(0,0,0,.9),
    inset 0 -3px 0 0 var(--tint) }
.wall-card.is-mono .wall-plate::before{ opacity:.34 }
.wall-card.is-mono .wall-nm i{ color:var(--muted) }
.wall-card.is-mono .wall-mono{ color:var(--ink) }

.wall-mark{ display:grid; place-items:center; min-height:clamp(74px,7vw,116px) }
.wall-mark img{ max-width:78%; max-height:clamp(58px,5.4vw,92px);
  width:auto; height:auto; object-fit:contain; display:block }

/* Знака ещё нет — стоит монограмма. Это не «заглушка на потом», а рабочий
   запасной вариант: маленькие поставщики часто приходят вовсе без логотипа. */
.wall-mono{ font-family:var(--disp); font-weight:700; letter-spacing:.02em;
  font-size:clamp(30px,3.4vw,52px); line-height:1; color:var(--paper-ink);
  opacity:.86 }

.wall-nm{ display:grid; gap:3px; min-width:0 }
.wall-nm b{ font-family:var(--disp); font-weight:600; letter-spacing:-.01em;
  font-size:clamp(15px,1.15vw,19px); line-height:1.18;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap }
.wall-nm i{ font-style:normal; font-size:13px; font-weight:600; color:var(--paper-mut);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap }

/* Строка о деле нужна поиску и читателю без JS. В барабане её место занимает
   карточка-портал, поэтому там она уходит из потока, оставаясь в разметке. */
.wall-li{ margin:6px 0 0; font-size:13.5px; line-height:1.45; color:var(--paper-mut) }
.wall-card.is-mono .wall-li{ color:var(--muted) }

/* ── фото во всю плиту (.is-cover) ─────────────────────────────
   Флаг владельца из админки. Непрозрачная фотография, поставленная по центру
   светлого листа, выглядит наклейкой — белый прямоугольник со швом. Cover
   закрывает ею плиту целиком, как в видеообразце стены (там плиты и есть
   фотографии). Подпись переезжает НА фото и получает тёмный низ — читаться
   она обязана на любом снимке, светлом и пёстром.

   Порядок слоёв внутри плиты: фон плиты → свечение ::before → фото (оба в
   отрицательном слое, фото позже — оно сверху) → подпись. */
.wall-card.is-cover .wall-plate{ aspect-ratio:1.42; color:#F4F8F5 }
.wall-card.is-cover .wall-mark{ position:absolute; inset:0; min-height:0; z-index:-1 }
.wall-card.is-cover .wall-mark img{ width:100%; height:100%;
  max-width:none; max-height:none; object-fit:cover }
.wall-card.is-cover .wall-mark::after{ content:''; position:absolute;
  inset:auto 0 0 0; height:52%;
  background:linear-gradient(to top, rgba(4,10,8,.82), transparent) }
.wall-card.is-cover .wall-nm i{ color:rgba(244,248,245,.72) }
.wall-card.is-cover .wall-li{ color:rgba(244,248,245,.78) }

.wall-plate:hover{ transform:translateY(-4px);
  box-shadow:0 1px 2px rgba(6,14,11,.24), 0 34px 64px -34px rgba(0,0,0,.95),
    inset 0 -3px 0 0 var(--tint) }

/* Служебное: в сетке без JS ни подсказки, ни счётчика, ни стрелок. */
.wall-bar,.wall-floor,.wall-open{ display:none }

/* ═══════════════════════ БАРАБАН (.is-live) ═══════════════════════ */

/* Сцена и строка под ней — разные коробки. Барабану нужны своя высота и
   overflow:hidden (плиты обязаны уезжать за край), а подсказке со стрелками
   внутри такой коробки места нет — её бы срезало вместе с плитами. */
.wall-stage{ position:relative }

.wall.is-live .wall-stage{
  height:clamp(540px,78vh,860px);
  perspective:1600px; perspective-origin:50% 46%;
  cursor:grab; touch-action:pan-y; user-select:none; -webkit-user-select:none;
  overflow:hidden;
}
.wall.is-live.is-drag .wall-stage{ cursor:grabbing }

/* Тёмная комната. Сцена видеообразца стоит в черноте, а не на общем фоне
   страницы.

   Чернота — часть ФОНА ПЛИТЫ раздела, а не отдельный слой внутри сцены.
   Слой пробовали дважды, и оба раза он давал линию во всю ширину: на
   .wall-stage его резал собственный overflow:hidden (без него плиты барабана
   не уезжают за край), а на .wall — собственная кромка, потому что
   радиальное пятно доходит до края блока ещё непрозрачным. У фона плиты
   краёв нет вовсе: он тянется от скруглённого верха до низа раздела и гаснет
   там, где кончается его собственный градиент.

   Селектор с `main >`: замес тёмных плит объявлен в style.css с той же
   силой, и без него общий фон побеждал бы этот. */
main > section.wall-sect{
  --slab-mix:
    radial-gradient(86% 48% at 50% 66%, rgba(2,5,4,.92), rgba(2,5,4,0) 100%),
    radial-gradient(70% 40% at 14% 4%, rgba(29,158,117,.16), transparent 70%),
    radial-gradient(80% 46% at 92% 12%, rgba(94,138,46,.12), transparent 74%),
    var(--bg);
}

/* Пол. Сетка в перспективе, растворяется к горизонту — единственное, что
   объясняет глазу, где в этой сцене «низ».

   Перспектива у пола ОБЩАЯ со сценой, а не своя. Со своим perspective()
   внутри transform горизонт уезжал вниз и от пола оставалась полоска в
   сотню пикселей у самого края — грязь, а не пол. Общая перспектива ставит
   горизонт там, где стоит perspective-origin сцены (46 % высоты), то есть
   ровно за плитами: они начинают стоять НА полу, а не висеть над ним.

   Плоскость приколота верхним краем к горизонту (transform-origin 50% 0) и
   уходит вниз-на-зрителя. Высота в пикселях, а не в процентах: это глубина
   пола, и от высоты сцены она не зависит. */
.wall.is-live .wall-floor{
  /* Горизонт сетки — ПОД плитами, как в образце: между плитами наверху
     чернота, пол читается только у их подножия. */
  display:block; position:absolute; left:50%; top:64%; width:300%; height:1200px;
  z-index:1;
  transform:translateX(-50%) rotateX(78deg);
  transform-origin:50% 0; pointer-events:none;
  /* Сетка нейтрально-серая, как в образце: пол — тёмная студия,
     а не зелёная канва. Цвет сцене дают плиты и свечение, не линии. */
  background:
    repeating-linear-gradient(90deg, rgba(208,220,214,.5) 0 1px, transparent 1px 74px),
    repeating-linear-gradient(0deg,  rgba(208,220,214,.42) 0 1px, transparent 1px 74px);
  /* У горизонта сетка проявляется, у ног — снова гаснет: иначе ближние
     линии бьют ярче плит, а нижний край сцены режет их по линейке. */
  -webkit-mask-image:linear-gradient(to bottom, transparent 0, rgba(0,0,0,.8) 5%, #000 20%, rgba(0,0,0,.6) 62%, rgba(0,0,0,.18) 100%);
  mask-image:linear-gradient(to bottom, transparent 0, rgba(0,0,0,.8) 5%, #000 20%, rgba(0,0,0,.6) 62%, rgba(0,0,0,.18) 100%);
  opacity:.5;
}

/* Свечение под серединой берёт цвет активного знака: сцена подхватывает
   бренд, на который сейчас смотрят. Цвет кладёт wall.js в --stage-tint. */
.wall.is-live .wall-stage::before{
  content:''; position:absolute; z-index:2; left:50%; bottom:2%;
  width:min(1100px,86%); height:44%; transform:translateX(-50%);
  background:radial-gradient(60% 100% at 50% 100%, var(--stage-tint,var(--cta)), transparent 72%);
  opacity:.13; filter:blur(28px); pointer-events:none;
  transition:background .6s linear;
}

/* Холст WebGL с плитами — между полом и невидимыми плитами-кнопками. */
.wall-gl{ position:absolute; inset:0; z-index:3; width:100%; height:100%;
  display:block; pointer-events:none }

.wall.is-live .wall-track{
  position:absolute; inset:0; display:block; padding:0; max-width:none;
  transform-style:preserve-3d; z-index:4;
}

/* Позицию на барабане ставит wall.js; туда же он кладёт --k — насколько
   плита ушла от середины.

   Ширина — как у экрана в видеообразце: чуть больше половины сцены, но не
   выше пола (второй аргумент min — это 86% высоты сцены × 1.42). */
.wall.is-live .wall-card{
  position:absolute; left:50%; top:50%;
  /* Пропорции образца: плита ~0.95 полувысоты кадра в мире, ближний горб
     S-ленты докручивает её в кадре примерно в 1.2 раза. */
  width:min(34vw, calc(clamp(540px,78vh,860px) * .68));
  aspect-ratio:1.42;
  transform-style:preserve-3d; will-change:transform;
}
.wall.is-live .wall-card[hidden]{ display:none }

.wall.is-live .wall-plate{
  height:100%; grid-template-rows:1fr auto;
  transition:transform .38s var(--e-micro), box-shadow .38s var(--e-micro);
}

/* Глубина накладкой, а не фильтром: одна плоскость поверх плиты дешевле
   любого filter и не заставляет браузер перерисовывать саму плиту.

   Накладка почти чёрная, а не серая. Серая на светлой плите даёт «серый
   пластик» — дальние знаки читаются не как ушедшие в тень, а как выцветшие.
   Чёрная уводит плиту в темноту сцены, и глубина появляется. */
.wall.is-live .wall-plate::after{
  content:''; position:absolute; inset:0; pointer-events:none;
  border-radius:inherit;
  background:rgba(3,9,7,.95);
  opacity:calc(var(--k) * .88);
  transition:opacity .28s linear;
}

.wall.is-live .wall-card.is-on .wall-plate{
  box-shadow:0 1px 2px rgba(6,14,11,.3), 0 44px 80px -38px rgba(0,0,0,1),
    inset 0 -3px 0 0 var(--tint),
    0 0 0 1.5px color-mix(in srgb, var(--tint) 55%, transparent);
}
/* Движки без color-mix просто не увидят третью тень — кромка пропадёт,
   остальное останется на месте. */
@supports not (color:color-mix(in srgb,#000 50%,#fff)){
  .wall.is-live .wall-card.is-on .wall-plate{
    box-shadow:0 1px 2px rgba(6,14,11,.3), 0 44px 80px -38px rgba(0,0,0,1),
      inset 0 -3px 0 0 var(--tint) }
}

.wall.is-live .wall-plate:hover{ transform:none }
.wall.is-live .wall-card.is-on .wall-plate:hover{ transform:translateZ(26px) }

/* «Открыть» — только на средней плите: подсказка появляется там, где
   нажатие что-то откроет, а не на всех десяти сразу. */
.wall.is-live .wall-open{
  display:inline-flex; align-items:center; gap:6px;
  position:absolute; right:clamp(12px,1.2vw,18px); top:clamp(12px,1.2vw,18px);
  padding:6px 11px; border-radius:999px;
  font-size:11.5px; font-weight:700; letter-spacing:.08em; text-transform:uppercase;
  background:rgba(13,26,21,.9); color:var(--cta);
  opacity:0; transform:translateY(-4px); transition:opacity .3s, transform .3s;
}
.wall.is-live .wall-card.is-on .wall-open{ opacity:1; transform:none }
.wall.is-live .wall-li{ position:absolute; width:1px; height:1px;
  overflow:hidden; clip-path:inset(50%) }

/* ═════════════════ WEBGL-РЕЖИМ (.is-gl, ставит wall-gl.js) ═════════════════
   Пиксели рисует холст, а CSS-плиты остаются невидимыми кнопками: нажатие,
   фокус и клавиатура живут в разметке, картинка — в GL. Прячем непрозрачность
   нулём, а не visibility: скрытый элемент перестал бы ловить нажатия. */

/* Только вместе с .is-live: на телефоне барабан выключен, и лента обязана
   остаться видимой, даже если модуль GL уже загрузился. */
.wall.is-live.is-gl .wall-plate{ opacity:0; transition:none }
.wall.is-live.is-gl .wall-plate:hover,
.wall.is-live.is-gl .wall-card.is-on .wall-plate:hover{ transform:none }
.wall.is-live.is-gl .wall-open{ display:none }
.wall:not(.is-live) .wall-gl{ display:none }
/* Клавиатуре нужен видимый фокус и над холстом: рамка на самой карточке. */
.wall.is-live.is-gl .wall-card:has(.wall-plate:focus-visible){
  outline:2px solid var(--cta); outline-offset:6px;
  border-radius:clamp(18px,1.6vw,26px);
}

/* Строка под сценой: подсказка, счётчик, стрелки. */
.wall.is-live .wall-bar,.wall.is-flat .wall-bar{
  display:flex; align-items:center; gap:clamp(14px,2vw,28px);
  max-width:var(--maxw); margin:clamp(16px,1.8vw,26px) auto 0; padding-inline:var(--pad);
}
.wall-hint{ margin:0; font-size:13px; color:var(--dim); flex:1 1 auto }
.wall-count{ margin:0; font-size:14px; color:var(--muted); letter-spacing:.04em }
.wall-count b{ color:var(--ink) }
.wall-count span{ opacity:.4; margin:0 4px }
.wall-count i{ font-style:normal }

/* Подпись «пример» под стеной. Она ВСЕГДА лежит в разметке и прячется
   атрибутом: словарь сайта переводит только то, что было в странице к моменту
   переключения языка, а флаг «список ещё демонстрационный» стоит в админке и
   переключается на живой странице. Правило явное, чтобы hidden не проиграл
   какому-нибудь div{display:block} из сброса. */
.wall-demo[hidden]{ display:none }
.wall-nav{ display:flex; gap:8px }
.wall-arw{
  width:42px; height:42px; border-radius:50%; cursor:pointer;
  -webkit-tap-highlight-color:transparent;
  display:grid; place-items:center; padding:0;
  background:rgba(255,255,255,.06); border:var(--hair); color:var(--ink);
  transition:background .2s, transform .2s, border-color .2s;
}
.wall-arw:hover{ background:rgba(255,255,255,.12); border-color:rgba(255,255,255,.22) }
.wall-arw:active{ transform:scale(.94) }
.wall-arw svg{ width:18px; height:18px; fill:none; stroke:currentColor;
  stroke-width:2; stroke-linecap:round; stroke-linejoin:round }

/* ═══════════════════════ ЛЕНТА (.is-flat) ═══════════════════════
   Телефон и «уменьшить движение»: барабан здесь и не нужен, и вреден.
   Родная прокрутка с прилипанием — то же содержимое, только честным
   способом. */

.wall.is-flat .wall-track{
  display:flex; gap:var(--gap); max-width:none; padding-inline:var(--pad);
  overflow-x:auto; overflow-y:hidden; scroll-snap-type:x mandatory;
  scrollbar-width:none; -webkit-overflow-scrolling:touch;
}
.wall.is-flat .wall-track::-webkit-scrollbar{ display:none }
.wall.is-flat .wall-card{ flex:0 0 min(74vw,320px); scroll-snap-align:center }
/* Правое поле у ленты: padding-inline на прокручиваемой коробке в конце
   списка съедается, и последняя плита прилипает к краю экрана. */
.wall.is-flat .wall-card:last-child{ margin-right:var(--pad) }
.wall.is-flat .wall-plate{ height:100%; aspect-ratio:4/3 }
.wall.is-flat .wall-li{ display:none }
.wall.is-flat .wall-hint{ display:none }

/* ───────────────── ТЕЛЕФОН: тот же барабан, свои размеры ─────────────────
   Узкому экрану лента не выключается (see wall.js) — ей выдаются размеры
   под ладонь. Плита меряется от ширины экрана, но не выше доли сцены;
   лента WebGL пересчитывает мир от сцены сама, ей отдельных правил не надо.
   Сетка пола мельче: клетка 74px на 390-пиксельном экране — это четыре
   линии на весь пол, сцена читалась бы пустой. */
@media (max-width:760px){
  .wall.is-live .wall-stage{ height:clamp(340px,54vh,500px); perspective:1200px }
  .wall.is-live .wall-card{ width:min(70vw, calc(clamp(340px,54vh,500px) * .62)) }
  .wall.is-live .wall-floor{ top:66%; height:640px;
    background:
      repeating-linear-gradient(90deg, rgba(208,220,214,.5) 0 1px, transparent 1px 46px),
      repeating-linear-gradient(0deg,  rgba(208,220,214,.42) 0 1px, transparent 1px 46px) }
  .wall.is-live .wall-bar{ gap:12px }
  .wall.is-live .wall-hint{ font-size:12px }
}

/* Телефон на боку: базовая высота сцены (от 540px) не влезает в экран
   390px ростом — сцена по высоте окна, плита от неё. */
@media (max-height:520px){
  .wall.is-live .wall-stage{ height:clamp(250px,74vh,430px) }
  .wall.is-live .wall-card{ width:min(34vw, calc(clamp(250px,74vh,430px) * .66)) }
}

/* ═══════════════════════ КАРТОЧКА-ПОРТАЛ ═══════════════════════ */

.pf[hidden]{ display:none }
.pf{
  position:fixed; inset:0; z-index:95;
  display:grid; place-items:center;
  --hole:520px; --holeh:86vh;
}
/* У карточки половина строк необязательная: нет города — нет строки, нет
   цифр — нет ряда цифр. Прячем их атрибутом hidden, но у списков стоит
   display:flex, а он атрибут перебивает — поэтому правило явное. */
.pf [hidden]{ display:none !important }
.pf-scrim{
  position:absolute; inset:0; background:rgba(4,9,7,.62);
  -webkit-backdrop-filter:blur(4px); backdrop-filter:blur(4px);
  opacity:0; transition:opacity .34s var(--e-reveal);
}
.pf.is-open .pf-scrim{ opacity:1 }

/* Кольцо. Холст на весь экран: жидкой кромке нужен запас за пределами круга,
   иначе её срежет по прямоугольнику и вся «жидкость» превратится в
   подстриженный овал. */
.pf-ring{ position:absolute; inset:0; width:100%; height:100%; display:block;
  pointer-events:none }

/* WebGL-кольцо (кладёт wall-gl.js). В этом режиме 2D-холст спит, а фон НЕ
   затемняется: в видеообразце сцена за кольцом остаётся как была. */
.pf-gl{ position:absolute; inset:0; width:100%; height:100%; display:none;
  pointer-events:none }
.pf.is-gl .pf-ring{ display:none }
/* Прозрачный фон — правило РЕЖИМА КОЛЬЦА (в образце сцена за кольцом не
   темнеет). Листу на телефоне скрим нужен как раньше: класс is-gl стоит на
   портале всегда, когда GL собрался, — даже там, где кольца не будет. */
.pf.is-gl:not(.is-sheet) .pf-scrim{ background:transparent;
  -webkit-backdrop-filter:none; backdrop-filter:none }

.pf-in{
  position:relative; z-index:2;
  /* Ширина и высота карточки — от дырки в кольце (их считает wall.js):
     строка обязана кончаться раньше кромки, иначе текст лезет на жгут. */
  width:min(var(--hole), 90vw); max-height:min(var(--holeh), 86vh); overflow:auto;
  padding:clamp(6px,1vw,14px); text-align:center;
  display:grid; gap:clamp(8px,.85vw,13px); justify-items:center;
  opacity:0; transform:translate3d(0,16px,0);
  transition:opacity .34s var(--e-reveal), transform .44s var(--e-reveal);
  scrollbar-width:none;
}
.pf-in::-webkit-scrollbar{ display:none }
.pf.is-in .pf-in{ opacity:1; transform:none }

/* Строки карточки проявляются каскадом, как в видеообразце: каждая чуть
   позже предыдущей, снизу и из лёгкой размытости. Задержки живут только под
   .is-in — закрытие уходит разом, без очереди. */
.pf-in > *{ opacity:0; transform:translate3d(0,18px,0); filter:blur(6px);
  transition:opacity .45s var(--e-reveal), transform .55s var(--e-reveal),
    filter .45s var(--e-reveal) }
.pf.is-in .pf-in > *{ opacity:1; transform:none; filter:none }
.pf.is-in .pf-in > :nth-child(1){ transition-delay:.03s }
.pf.is-in .pf-in > :nth-child(2){ transition-delay:.08s }
.pf.is-in .pf-in > :nth-child(3){ transition-delay:.13s }
.pf.is-in .pf-in > :nth-child(4){ transition-delay:.18s }
.pf.is-in .pf-in > :nth-child(5){ transition-delay:.23s }
.pf.is-in .pf-in > :nth-child(6){ transition-delay:.28s }
.pf.is-in .pf-in > :nth-child(7){ transition-delay:.33s }
.pf.is-in .pf-in > :nth-child(8){ transition-delay:.38s }
.pf.is-in .pf-in > :nth-child(9){ transition-delay:.43s }

/* Лист на телефоне въезжает целиком — каскад там не нужен. */
.pf.is-sheet .pf-in > *{ opacity:1; transform:none; filter:none;
  transition:none }

.pf-logo{
  width:clamp(54px,4.6vw,70px); aspect-ratio:1; border-radius:19px;
  display:grid; place-items:center; overflow:hidden;
  background:linear-gradient(168deg,#FCFDFC,#E4EBE6);
  box-shadow:0 18px 34px -22px rgba(0,0,0,.9), var(--bevel);
  color:var(--paper-ink); font-family:var(--disp); font-weight:700; font-size:22px;
}
.pf-logo img{ max-width:74%; max-height:74%; object-fit:contain }
.pf-logo.is-mono{ background:linear-gradient(168deg,#17241F,#0C1411); color:var(--ink) }
/* Фото-знак заполняет и квадратик в карточке — та же логика, что на плите. */
.pf-logo.is-cover img{ width:100%; height:100%;
  max-width:none; max-height:none; object-fit:cover }

.pf-cat{ margin:0; font-size:12px; font-weight:700; letter-spacing:.14em;
  text-transform:uppercase; color:var(--cta) }
.pf-name{ margin:0; font-family:var(--disp); font-weight:700; letter-spacing:-.02em;
  font-size:clamp(22px,2.2vw,34px); line-height:1.08 }
.pf-where{ margin:0; font-size:13.5px; color:var(--dim) }
.pf-line{ margin:0; max-width:38ch; font-size:clamp(14.5px,1.05vw,16.5px);
  line-height:1.48; color:var(--muted) }

.pf-goods{ list-style:none; margin:0; padding:0;
  display:flex; flex-wrap:wrap; gap:7px; justify-content:center; max-width:36ch }
.pf-goods li{ padding:4px 10px; border-radius:999px; font-size:12px;
  background:rgba(255,255,255,.07); border:var(--hair); color:var(--ink) }

.pf-stats{ list-style:none; margin:0; padding:0;
  display:flex; flex-wrap:wrap; gap:clamp(14px,2vw,28px); justify-content:center }
.pf-stats li[hidden]{ display:none }
.pf-stats li{ display:grid; gap:2px; justify-items:center }
.pf-stats b{ font-family:"Space Grotesk", Manrope, sans-serif;
  font-variant-numeric:tabular-nums;
  font-weight:600; font-size:clamp(19px,1.7vw,26px); color:var(--ink) }
/* Единица при числе — мельче самого числа: «6 мин», а не «6 МИН». */
.pf-stats b span + span{ font-size:.6em; font-weight:600; color:var(--muted) }
.pf-stats span{ font-size:11.5px; color:var(--dim); max-width:16ch; line-height:1.25;
  text-align:center }

.pf-go{ margin-top:2px }

/* Закрыть — в том же углу, где на плите стояло «открыть». */
.pf-x{
  position:absolute; z-index:3; top:clamp(14px,2vw,26px); right:clamp(14px,2vw,26px);
  display:inline-flex; align-items:center; gap:8px; cursor:pointer;
  padding:9px 15px; border-radius:999px; font:inherit;
  font-size:12px; font-weight:700; letter-spacing:.1em; text-transform:uppercase;
  background:rgba(255,255,255,.08); border:var(--hair); color:var(--ink);
  -webkit-backdrop-filter:blur(10px); backdrop-filter:blur(10px);
  opacity:0; transition:opacity .3s, background .2s;
}
.pf.is-in .pf-x{ opacity:1 }
.pf-x:hover{ background:rgba(255,255,255,.15) }
.pf-x svg{ width:14px; height:14px; fill:none; stroke:currentColor; stroke-width:2.2;
  stroke-linecap:round }

/* ───────────────── МАЛОЕ КОЛЬЦО: телефон ─────────────────
   Кольцо на телефоне то же, только меньше — а значит, дырка размером с
   ладонь. Влезает в неё не всё, и решает это ОДНО правило: в дырке
   остаётся то, ради чего карточку открывали — знак, имя, чем занят,
   откуда, что возит, как быстро отвечает и кнопка. Уходят описание
   строкой, хвост списка товаров и третья цифра: они и на большом экране
   читаются последними.

   Прячем показом, а не разметкой: список приходит один и тот же, и
   поворот телефона обязан возвращать строки на место без перезагрузки. */
.pf.is-mini .pf-in{ gap:3px; padding:0 }
.pf.is-mini .pf-logo{ width:40px; border-radius:12px; font-size:15px }
.pf.is-mini .pf-cat{ font-size:9.5px; letter-spacing:.1em }
.pf.is-mini .pf-name{ font-size:18px; line-height:1.05 }
/* Строка «город · на FLUX с 2025» — самая длинная в дырке. На экране
   375 px она при 11 px переносится и уводит кнопку за кромку, поэтому
   кегль здесь считается от ширины экрана, а не назначен на глаз. */
.pf.is-mini .pf-where{ font-size:clamp(9.5px,2.7vw,11px) }
.pf.is-mini .pf-line{ display:none }
/* Подпись «что возит» уходит: три чипа подряд читаются списком и без неё,
   а строка подписи — это ещё 18 px, которых в дырке нет. */
.pf.is-mini .pf-goods-t{ display:none }
.pf.is-mini .pf-goods{ gap:4px; max-width:none }
.pf.is-mini .pf-goods li{ padding:2px 7px; font-size:10px }
/* Четвёртый товар начинает вторую строку и выдавливает кнопку на жгут. */
.pf.is-mini .pf-goods li:nth-child(n+4){ display:none }
.pf.is-mini .pf-stats{ gap:14px }
/* «Ресторанов обслужено» — единственная цифра, которая ничего не говорит
   ресторану о нём самом: она про чужой опыт. Её и убираем первой. */
.pf.is-mini .pf-stats li[data-s="rest"]{ display:none }
.pf.is-mini .pf-stats b{ font-size:16px }
.pf.is-mini .pf-stats span{ font-size:9px; max-width:11ch; line-height:1.15 }
/* Кнопка — строго в одну строку: перенос стоит 20 px, а их нет. */
/* Кегль кнопки — от ширины экрана: на узбекском подпись длиннее русской
   на четверть, а переносить её некуда (перенос стоит 20 px высоты, и они
   уже розданы). Узкий экран уменьшает буквы, а не ломает строку. */
.pf.is-mini .pf-go{ margin-top:0; padding:2px 0; gap:5px; white-space:nowrap;
  font-size:clamp(9.5px,2.9vw,11.5px) }
.pf.is-mini .pf-go .ic{ width:14px; height:14px }
.pf.is-mini .pf-x{ top:12px; right:12px; padding:7px 12px; font-size:11px }

/* Лист вместо кольца — только при «уменьшить движение»: там кольцо не
   раскрывается вовсе, и карточке нужен обычный лист снизу. */
.pf.is-sheet{ place-items:end stretch }
.pf.is-sheet .pf-ring{ display:none }
.pf.is-sheet .pf-in{
  width:auto; max-height:88vh; text-align:left; justify-items:start;
  margin:0 8px 8px; padding:clamp(20px,5vw,28px);
  border-radius:26px 26px 20px 20px;
  background:var(--glass); background-color:rgba(10,20,16,.92);
  border:var(--hair); box-shadow:var(--shadow), var(--bevel);
  transform:translate3d(0,26px,0);
}
.pf.is-sheet.is-in .pf-in{ transform:none }
.pf.is-sheet .pf-line,.pf.is-sheet .pf-goods{ max-width:none }
.pf.is-sheet .pf-goods,.pf.is-sheet .pf-stats{ justify-content:flex-start }
.pf.is-sheet .pf-stats li{ justify-items:start }
.pf.is-sheet .pf-stats span{ text-align:left }

/* Пока портал открыт, страница под ним не едет. */
body.pf-lock{ overflow:hidden }

/* ─────────────────────── меньше движения ───────────────────────
   Барабан выключен на уровне JS (раздел остаётся лентой), здесь гасим
   переходы, чтобы ничего не выезжало. */
@media (prefers-reduced-motion: reduce){
  .wall-plate,.pf-in,.pf-in > *,.pf-scrim,.pf-x,.wall-open{ transition:none !important }
  .pf-in > *{ filter:none }
  .wall-plate:hover{ transform:none }
}
