@charset "utf-8";
/* ============================================================================
   comfortable table — общая дизайн-система сайта
   Стилистика «Нить» (утверждена Дарьей): тёплая бумага, терракотовая нить,
   бумажные бирки, вязаное полотно, деревянный стол.

   ВАЖНО ДЛЯ ДРУГИХ АГЕНТОВ:
   — :root пишется ТОЛЬКО в этом файле. Свои переменные не заводить.
   — На страницах не задавать background у html/body: фон живёт здесь и
     продолжается на любой высоте экрана (слои фиксированные).
   — На body не ставить transform/filter/opacity/isolation: это создаст
     контекст наложения и спрячет фоновые слои (z-index:-1).
   — Анимации только transform/opacity. Никакого filter/blur в бесконечных.
   ========================================================================== */

/* ───────────────────────── 1. ТОКЕНЫ ───────────────────────────────────── */
:root{
  /* бумага и полотно */
  --paper:        #f6efe3;
  --paper-lit:    #f9f2e6;
  --paper-shade:  #f1e6d2;
  --paper-deep:   #efe5d3;
  --card:         #fffaf0;
  --card-2:       #fdf5e7;

  /* дерево стола (подвал, тёплые подложки) */
  --wood-lit:     #f1d8a6;
  --wood:         #e9cb93;
  --wood-deep:    #deba7e;
  --wood-line:    rgba(129,84,38,.10);

  /* нить и терракота */
  --thread:       #be5f35;
  --clay:         #b2562d;   /* заливка кнопок, верх градиента */
  --clay-deep:    #9c4720;   /* низ градиента */
  --clay-lit:     #cd7346;   /* ховер, блики */
  --clay-ink:     #8a3d1a;   /* терракотовый ТЕКСТ (контрастный) */
  --ball:         #c2693a;
  --ball-dark:    #9a4c25;
  --ball-lit:     #dd925e;

  /* бумажные бирки */
  --tag:          #efdfc0;
  --tag-2:        #e7d3ac;
  --tag-ink:      #5c4630;

  /* шалфей — второй, спокойный акцент */
  --sage:         #7e9678;
  --sage-deep:    #5b7052;
  --sage-ink:     #4c6244;

  /* чернила */
  --ink:          #4a3b30;   /* заголовки, основное */
  --ink-2:        #6b5647;   /* текст абзацев      6.0:1 */
  --ink-soft:     #7a6553;   /* подписи, мелкое    4.8:1 */
  --ink-faint:    #8f7a63;   /* ТОЛЬКО декоратив ≥24px, не для текста */
  --cream:        #fff8f0;   /* текст на терракоте 4.7:1 */
  --cream-2:      #fff6ea;

  /* ЛИНИИ. Два смысла, два токена — третьего не заводить.
     --hair — контур предмета (карточка, панель, лупа, чип).
     --seam — шов: только там, где две части ОДНОГО предмета сшиты
              (фото и текст в карточке, разделители в корзине). */
  --hair:  1px solid rgba(140,100,64,.16);
  --seam:  2px dashed rgba(190,95,53,.28);
  --line:         rgba(140,100,64,.22);
  --line-soft:    rgba(140,100,64,.16);

  /* ТЕНИ. Ровно три уровня, четвёртого не заводить.
     --sh-1 — предмет лежит на столе (карточки, бирки, чипсы, бейджи, панели);
     --sh-2 — предмет приподняли пальцем (только :hover);
     --sh-3 — предмет накрыл страницу (шторка корзины, лупа, липкая шапка). */
  --sh-1: 0 1px 2px rgba(120,80,45,.06), 0 6px 14px rgba(120,80,45,.10);
  --sh-2: 0 2px 5px rgba(120,80,45,.09), 0 16px 28px rgba(120,80,45,.15);
  --sh-3: 0 24px 56px rgba(90,58,30,.30);
  --sh-3-side: -24px 0 56px rgba(90,58,30,.30);   /* тот же вес, но вбок — шторка */
  /* старые имена оставлены как псевдонимы: их знают четыре страницы */
  --sh-tag:       var(--sh-1);
  --sh-card:      var(--sh-1);
  --sh-card-up:   var(--sh-2);
  --sh-btn:       0 2px 4px rgba(140,64,28,.20), 0 8px 16px rgba(140,64,28,.16);
  --sh-btn-up:    0 3px 7px rgba(140,64,28,.22), 0 14px 24px rgba(140,64,28,.20);
  --sh-drawer:    var(--sh-3-side);
  --sh-head:      var(--sh-3);

  /* СТАТУСЫ КАРТОЧЕК — теперь это только цвет точки на бумажном чипе.
     Заливать бейдж целиком нельзя: он начинает кричать громче игрушки.
     «в наличии» → --sage-deep, «возможен повтор» → --tag-2,
     «повтор невозможен» → --ink-soft, «гача» → --clay. */
  --st-ok:  #5b7052;   /* = --sage-deep */
  /* «возможен повтор»: было --tag-2 (#e7d3ac) — светлее самой бумаги чипа,
     контраст 1,2:1, и рядом с плотной зелёной точкой «в наличии» она
     читалась как выключенный, недоступный кружок. Тёмная терракота из той
     же палитры даёт 4,9:1 (2026-08-12) */
  --st-may: #9a4c25;   /* = --ball-dark */
  --st-no:  #7a6553;   /* = --ink-soft */

  /* шрифты */
  --font-display: 'Comfortaa', 'Trebuchet MS', system-ui, sans-serif;
  --font-text:    'Nunito', 'Segoe UI', system-ui, sans-serif;
  --font-hand:    'Caveat', 'Comic Sans MS', cursive;

  /* размеры текста */
  --fs-h1:      clamp(34px, 7.4vw, 68px);   /* только главная: имя бренда */
  --fs-h1-page: clamp(28px, 4.2vw, 44px);   /* каталог, бинго, отзывы */
  --fs-h2:    clamp(26px, 4.4vw, 40px);
  --fs-h3:    clamp(19px, 2.4vw, 24px);
  --fs-lead:  clamp(16px, 1.6vw, 19px);
  --fs-body:  16px;
  --fs-small: 14px;
  --fs-tiny:  13.5px;
  --fs-hand:  clamp(19px, 2.2vw, 24px);

  /* РИТМ. Одна шкала отступов на весь сайт. Своих чисел не писать:
     всё, что не из этой шкалы, со временем разъезжается. */
  --sp-1: 8px;   --sp-2: 12px;  --sp-3: 20px;
  --sp-4: 32px;  --sp-5: 52px;  --sp-6: 84px;

  /* сетка и отступы */
  --wrap:        1200px;
  --wrap-narrow: 820px;
  --pad-page:    clamp(16px, 4vw, 40px);
  --gap:         clamp(14px, 2vw, 22px);
  --sec-gap:     clamp(40px, 6vw, 84px);          /* = --sp-6 на широком */
  --sec-gap-tight: clamp(24px, 3.4vw, 44px);
  --tap:         44px;

  /* скругления */
  --r-xs: 7px;  --r-sm: 10px;  --r-md: 14px;
  --r-lg: 20px; --r-xl: 28px;  --r-pill: 999px;

  /* ДВИЖЕНИЕ. Один язык на весь сайт, четвёртой скорости не заводить:
       отклик на палец      --t-fast .18s / --t .28s   (150–280 мс)
       появление блока      --t-in .5s / --t-in-lg .62s (420–620 мс)
       догон соседа         --step 58 мс, не больше шести шагов подряд
       фоновая жизнь        5–9 с (качание бирок, дыхание нити)
     Кривые: --ease-out — всё, что появляется (быстро стартует, мягко встаёт);
     --ease-back — то, что «встало на место» с доводкой (печать, счётчик). */
  --ease:      cubic-bezier(.2,.7,.2,1);
  --ease-soft: cubic-bezier(.4,0,.2,1);
  --ease-out:  cubic-bezier(.16,.84,.44,1);
  --ease-back: cubic-bezier(.34,1.42,.64,1);
  --t-fast: .18s;  --t: .28s;  --t-slow: .45s;
  --t-in: .5s;     --t-in-lg: .62s;   --step: 58ms;

  /* слои. Фон занимает −3 (градиент), −2 (полотно), −1 (свет) —
     содержимое страниц кладём от 0 и выше */
  --z-bg: -1; --z-head: 40; --z-veil: 80; --z-drawer: 90;
  --z-toast: 95; --z-fly: 99;

  /* мотивы (переиспользуемые картинки-паттерны) */
  --knit: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="26" height="20"><path d="M0 14 L6.5 6 L13 14 L19.5 6 L26 14" fill="none" stroke="%23a8886b" stroke-opacity="0.14" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"/></svg>');
  --stitch: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="34" height="12"><path d="M1 9 L9 3 L17 9 L25 3 L33 9" fill="none" stroke="%23be5f35" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/></svg>');
  --grain: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="280" height="148"><g fill="none" stroke="%23815426" stroke-opacity="0.10" stroke-width="1.5" stroke-linecap="round"><path d="M16,12 q52,5 100,1 t92,2"/><path d="M40,25 q60,-4 112,0"/><path d="M150,33 q44,3 86,-1"/><path d="M12,58 q56,4 104,0 t96,3"/><path d="M70,71 q52,-4 98,1"/><path d="M20,96 q50,4 96,-1 t90,2"/><path d="M120,108 q48,-3 92,1"/><path d="M34,131 q56,4 104,0 t88,-2"/></g></svg>');
}

/* ───────────────────────── 2. БАЗА И ФОН ───────────────────────────────── */
*, *::before, *::after{ box-sizing:border-box; }
* { margin:0; padding:0; }

html{
  /* сплошной цвет-подложка: он не может оборваться ни на какой высоте.
     Всё остальное (свет, полотно) — тремя фиксированными слоями ниже,
     поэтому кромок и «прямоугольников» на длинных страницах не бывает.
     background-attachment: fixed намеренно не используется — на iOS он врёт. */
  background: var(--paper);
  scroll-behavior: smooth;
  scroll-padding-top: 126px;      /* якоря не уезжают под липкую шапку (113 + воздух) */
  -webkit-text-size-adjust: 100%;
}

body{
  min-height: 100svh;
  background: transparent;         /* всё небо рисует html + слои ниже */
  font-family: var(--font-text);
  font-size: var(--fs-body);
  line-height: 1.6;
  color: var(--ink-2);
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
}

/* мягкий тёплый градиент бумаги */
html::before{
  content:''; position:fixed; inset:0; z-index:-3; pointer-events:none;
  background-image: linear-gradient(168deg, var(--paper-lit) 0%, var(--paper) 46%, var(--paper-shade) 100%);
}

/* вязаное полотно — фиксированный слой, поэтому кромок не бывает */
body::before{
  content:''; position:fixed; inset:-40px; z-index:-2;
  background-image: var(--knit);
  animation: knit-drift 52s linear infinite;
  pointer-events:none; will-change: transform;
}
@keyframes knit-drift{ to{ transform: translate3d(-26px,-20px,0); } }

/* дневной свет из окна — «дышит» opacity, ничего не перерисовывается */
body::after{
  content:''; position:fixed; inset:0; z-index:var(--z-bg);
  background:
    radial-gradient(ellipse 900px 640px at 14% 2%,  rgba(255,253,244,.85), rgba(255,253,244,0) 62%),
    radial-gradient(ellipse 760px 560px at 88% 92%, rgba(214,168,120,.16), rgba(214,168,120,0) 66%);
  animation: light-breath 13s ease-in-out infinite alternate;
  pointer-events:none;
}
@keyframes light-breath{ from{ opacity:.82; } to{ opacity:1; } }

img, svg, video{ display:block; max-width:100%; }
img{ height:auto; }
button, input, select, textarea{ font:inherit; color:inherit; }
button{ background:none; border:0; cursor:pointer; }
a{ color: var(--clay-ink); }

/* фокус виден всегда и везде — одинаковой пунктирной нитью */
:where(a, button, input, select, textarea, [tabindex]):focus-visible{
  outline: 3px dashed var(--thread);
  outline-offset: 3px;
  border-radius: var(--r-xs);
}

.skip-link{
  position:absolute; left:-9999px; top:0; z-index:100;
  background: var(--clay); color: var(--cream);
  padding: 12px 18px; border-radius: 0 0 var(--r-sm) 0; font-weight:700;
}
.skip-link:focus{ left:0; }

.visually-hidden{
  position:absolute!important; width:1px; height:1px; overflow:hidden;
  clip:rect(0 0 0 0); clip-path:inset(50%); white-space:nowrap;
}

/* ───────────────────────── 3. ТИПОГРАФИКА И РАСКЛАДКА ──────────────────── */
.wrap{ width:100%; max-width: var(--wrap); margin-inline:auto; padding-inline: var(--pad-page); }
.wrap--narrow{ max-width: var(--wrap-narrow); }

.section{ position:relative; padding-block: var(--sec-gap); }
.section--tight{ position:relative; padding-block: var(--sec-gap-tight); }

/* шов между секциями: вместо пустоты — стежок, как в каталоге между мирами.
   Идёт по ширине контентной колонки, а не во всю страницу. */
:is(.section, .section--tight) + :is(.section, .section--tight)::before{
  content:''; position:absolute; top:0; height:12px; pointer-events:none;
  left:  max(var(--pad-page), (100% - var(--wrap) + 2 * var(--pad-page)) / 2);
  right: max(var(--pad-page), (100% - var(--wrap) + 2 * var(--pad-page)) / 2);
  background-image: var(--stitch); background-repeat: repeat-x; background-size: 34px 12px;
  opacity:.3;
}

h1, h2, h3, h4{
  font-family: var(--font-display); font-weight:700; color: var(--ink);
  line-height:1.14; text-wrap: balance;
}
h1{ font-size: var(--fs-h1); letter-spacing:-.012em; }
h2{ font-size: var(--fs-h2); }
h3{ font-size: var(--fs-h3); }

/* заголовок внутренней страницы меньше, чем имя бренда на главной:
   слово «Каталог» в 68 px съедало весь первый экран */
h1.section-title,
.catalog-top h1, .bingo-top h1, .reviews-hero h1{ font-size: var(--fs-h1-page); }

/* надзаголовок всегда отдельной строкой над заголовком: .section-title —
   inline-block, и строчный надзаголовок вставал с ним в одну строку
   (на главной выходило «своя вселенная Гача слаймиков») */
.overline{
  display:block; margin-bottom: var(--sp-1);
  font-size: 12px; font-weight:800; letter-spacing:.24em; text-transform:uppercase;
  color: var(--sage-ink);
}
.lead{ font-size: var(--fs-lead); line-height:1.6; color: var(--ink-2); }
.lead b{ color: var(--ink); font-weight:800; }
.hand{ font-family: var(--font-hand); font-weight:600; font-size: var(--fs-hand); color: var(--sage-ink); line-height:1.2; }
.muted{ color: var(--ink-soft); }
.small{ font-size: var(--fs-small); }
.tiny{ font-size: var(--fs-tiny); }
.accent{ color: var(--clay-ink); font-weight:800; }

/* заголовок секции с подчёркиванием-стежком */
.section-head{ margin-bottom: clamp(18px, 2.2vw, 28px); }
.section-head .overline{ display:block; margin-bottom: var(--sp-1); }
.section-title{ display:inline-block; }
.section-title::after{
  content:''; display:block; height:12px; width: clamp(84px, 22%, 136px);
  margin-top:12px;
  background-image: var(--stitch); background-repeat: repeat-x; background-size: 34px 12px;
}
.section-head .hand{ margin-top:10px; display:block; }

/* сетки */
/* сетки. Ширина колонки задана в самой сетке — отдельных правил под большие
   экраны нет намеренно: они перебивали бы модификаторы --wide/--two/--tight */
.grid{
  display:grid; gap: var(--gap);
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));  /* 4 в ряд на 1440 */
}
.grid--wide{ grid-template-columns: repeat(auto-fill, minmax(330px, 1fr)); }
.grid--tight{ grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); }
.grid--two{ grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }

/* бумажная панель — общий контейнер для текстовых блоков */
.panel{
  background: var(--card);
  border: var(--hair);
  border-radius: var(--r-lg);
  box-shadow: var(--sh-1);
  padding: clamp(18px, 3vw, 28px);
}
.panel h3{ margin-bottom: var(--sp-1); }
.panel--tag{
  background: linear-gradient(165deg, var(--tag), var(--tag-2));
  border-color: rgba(140,100,64,.2);
  color: var(--tag-ink);
}

/* бирка на нитке — фирменный мотив, качается */
.tag{
  position:relative;
  display:inline-block;
  background: linear-gradient(165deg, var(--tag), var(--tag-2));
  border-radius: var(--r-sm);
  padding: 11px 16px 13px 26px;
  color: var(--tag-ink);
  /* уровень тени — первый: бирка ЛЕЖИТ. Внутренний блик оставлен:
     он рисует толщину бумаги, а не подъём над столом */
  box-shadow: var(--sh-1), inset 0 1px 0 rgba(255,248,232,.7);
  transform: rotate(-2.6deg);
  transform-origin: 13px 8px;
  animation: tag-sway 5.4s ease-in-out infinite alternate;
  transition: transform var(--t) var(--ease);
}
.tag::before{                      /* дырка под нить */
  content:''; position:absolute; left:9px; top:14px; width:9px; height:9px;
  border-radius:50%; background: var(--paper);
  box-shadow: inset 0 1px 2px rgba(110,70,40,.45);
}
.tag:focus-within{ animation-play-state: paused; }
/* бирка висит на нитке — значит на палец она отзывается качком,
   а не подъёмом плитой. Жест один и тот же на весь сайт */
@media (hover: hover){
  .tag:hover{ animation:none; transform: rotate(-1deg) translateY(-1px); }
}
@keyframes tag-sway{ from{ transform: rotate(-4.4deg); } to{ transform: rotate(-1deg); } }

/* цитата покупателя */
.quote{
  background: var(--card);
  border: var(--hair);
  border-radius: var(--r-lg);
  box-shadow: var(--sh-1);
  padding: clamp(18px, 2.6vw, 26px);
  position:relative;
}
.quote::before{
  content:'“'; position:absolute; left:14px; top:-6px;
  font-family: var(--font-display); font-size:56px; line-height:1;
  color: rgba(190,95,53,.28);
}
.quote p{ color: var(--ink-2); }
.quote figcaption{ margin-top:12px; font-size: var(--fs-small); color: var(--ink-soft); }

/* ───────────────────────── 4. КНОПКИ ───────────────────────────────────── */
.btn{
  display:inline-flex; align-items:center; justify-content:center; gap:10px;
  min-height: var(--tap); padding: 12px 22px;
  border-radius: var(--r-pill);
  font-family: var(--font-text); font-weight:800; font-size: 15.5px;
  text-decoration:none; white-space:nowrap; cursor:pointer;
  transition: transform var(--t) var(--ease), box-shadow var(--t) var(--ease),
              background-color var(--t) var(--ease), color var(--t) var(--ease);
}
.btn:active{ transform: translateY(0) scale(.975); }

/* ЦВЕТ ДЕЙСТВИЯ. Терракотой заливается только то, что ведёт к покупке:
   «в корзину», «оформить», «написать Дарье». Всё остальное — бумага. */
.btn--main{
  background: linear-gradient(180deg, var(--clay), var(--clay-deep));
  color: var(--cream);
  box-shadow: var(--sh-btn);
}

.btn--soft{
  background: var(--card);
  color: var(--clay-ink);
  border: 2px solid rgba(190,95,53,.4);
  box-shadow: var(--sh-1);
}

/* зелёный больше не заливает крупные кнопки — он сжат до точки статуса */
.btn--sage{
  background: var(--card);
  color: var(--sage-ink);
  border: 2px solid rgba(126,150,120,.55);
  box-shadow: var(--sh-1);
}
.btn--sage::before{
  content:''; flex:none; width:10px; height:10px; border-radius:50%;
  background: var(--sage-deep);
  box-shadow: 0 0 0 3px rgba(126,150,120,.22);
}

@media (hover: hover){
  .btn--main:hover{ transform: translateY(-2px); box-shadow: var(--sh-btn-up); }
  .btn--soft:hover{ transform: translateY(-2px); border-color: var(--thread); background: var(--card-2); box-shadow: var(--sh-2); }
  .btn--sage:hover{ transform: translateY(-2px); border-color: var(--sage-deep); background: var(--card-2); box-shadow: var(--sh-2); }
}

/* ссылка-действие: подчёркивание строго по ширине слов, а не рамкой снизу
   (рамка была шире текста и в центрированной колонке висела чёрточкой) */
.btn--ghost{
  min-height: var(--tap); padding: 10px 4px;
  background:none; border:0; border-radius:0; color: var(--ink);
  font-weight:700; font-size:15.5px;
  text-decoration: underline; text-decoration-style: dashed;
  text-decoration-color: var(--thread);
  text-underline-offset: 6px; text-decoration-thickness: 2px;
}
.btn--ghost:hover{ color: var(--clay-ink); }

.btn--wide{ width:100%; }
.btn--sm{ min-height: var(--tap); padding: 10px 16px; font-size:14.5px; }

.btn[disabled], .btn[aria-disabled='true']{
  opacity:.5; cursor:default; transform:none; box-shadow:none;
}

/* круглая иконочная кнопка (закрыть, ±) */
.icon-btn{
  width: var(--tap); height: var(--tap);
  display:inline-flex; align-items:center; justify-content:center;
  border-radius: var(--r-md);
  border: 1px solid var(--line);
  background: var(--card);
  color: var(--ink);
  font-size:18px; font-weight:800; line-height:1;
  transition: background-color var(--t-fast), border-color var(--t-fast), transform var(--t-fast);
}
@media (hover: hover){
  .icon-btn:hover{ background: var(--card-2); border-color: var(--thread); }
}
.icon-btn:active{ transform: scale(.94); }

/* ───────────────────────── 5. ШАПКА ────────────────────────────────────── */
.site-head{
  position: sticky; top:0; z-index: var(--z-head);
  /* у верха страницы шапка прозрачная — полотно под ней не обрывается;
     подложка появляется только когда шапка «прилипла» и стала полкой */
  background: transparent;
  transition: transform var(--t) var(--ease), box-shadow var(--t) var(--ease),
              background-color var(--t) var(--ease);
}
/* натянутая нить, на которой висит вся навигация.
   Одна на все пять страниц (сведено 2026-08-12): 18 px воздуха над нитью и
   провис 8 px в середине — как в утверждённом варианте «Нить». Провис нарисован
   картинкой-кривой внутри самой линии: лишнего слоя нет, filter не нужен,
   дыхание натяжения (scaleY) продолжает работать. */
.site-head::before{
  content:''; position:absolute; left:0; right:0; top:18px; height:20px;
  background-color: transparent;
  background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1000 20" preserveAspectRatio="none"><path d="M0 5.6 Q500 21.6 1000 5.6" fill="none" stroke="%237a4a28" stroke-opacity="0.3" stroke-width="4.4"/><path d="M0 4 Q500 20 1000 4" fill="none" stroke="%23be5f35" stroke-width="3.2"/></svg>');
  background-repeat: no-repeat;
  background-size: 100% 100%;
  pointer-events:none;
}
.site-head.is-stuck{
  background: var(--paper-lit);
  box-shadow: var(--sh-head);
}
.site-head.is-hidden{ transform: translateY(-104%); }

.head-inner{
  position:relative;
  max-width: var(--wrap); margin-inline:auto;
  padding: 38px var(--pad-page) 14px;   /* 38px = воздух над нитью + длина нитки до пунктов */
  display:flex; align-items:flex-start; gap: clamp(10px, 2vw, 26px);
}

/* логотип-бирка с клубком */
.logo{
  display:flex; align-items:center; gap:11px;
  min-height: var(--tap);
  padding: 8px 15px 8px 12px;
  background: linear-gradient(165deg, var(--tag), var(--tag-2));
  border-radius: var(--r-sm);
  box-shadow: var(--sh-1), inset 0 1px 0 rgba(255,248,232,.7);
  text-decoration:none; color: var(--ink);
  transform: rotate(-2.4deg);
  transform-origin: 22px -18px;
  animation: tag-sway 7.5s ease-in-out infinite alternate;
  transition: transform var(--t) var(--ease);
  flex:none;
}
/* тот же жест, что у любой бирки сайта: качнулась, а не поднялась */
@media (hover: hover){
  .logo:hover{ animation:none; transform: rotate(-1deg) translateY(-1px); }
}
.logo-ball{ width:27px; height:27px; flex:none; }
.logo-name{ display:block; font-family: var(--font-display); font-weight:700; font-size:15px; color: var(--ink); }
.logo-sub{ display:block; margin-top:2px; font-size:12px; font-weight:800; letter-spacing:.14em; text-transform:uppercase; color: var(--tag-ink); }
/* нитка от шнура к логотипу и булавка, которой бирка приколота */
.logo::before{
  content:''; position:absolute; left:22px; top:-14px; width:2.5px; height:14px;
  background: var(--thread); border-radius:2px;
}
.logo::after{
  content:''; position:absolute; left:23px; top:-18px;
  width:9px; height:9px; border-radius:50%;
  background: var(--ball);
  box-shadow: 0 1px 2px rgba(122,74,40,.38), inset -1px -1px 0 rgba(122,60,30,.3);
  transform: translateX(-50%);
}

/* навигация — пункты висят на нити, каждый пришпилен булавкой */
.nav{ display:flex; align-items:stretch; gap: clamp(6px, 1.6vw, 26px); margin-inline:auto; }
.nav-link{
  position:relative;
  display:flex; align-items:flex-start;
  min-height: var(--tap); padding: 2px 8px 0;
  font-weight:700; font-size:15px; color: var(--ink-2);
  text-decoration:none; white-space:nowrap;
  transition: color var(--t-fast) var(--ease), transform var(--t-fast) var(--ease);
}
.nav-link::before{           /* нитка вверх до шнура */
  content:''; position:absolute; left:50%; top:-8px; width:2px; height:10px;
  background: var(--thread); transform: translateX(-50%);
}
.nav-link::after{            /* булавка */
  content:''; position:absolute; left:50%; top:-13px; width:8px; height:8px;
  border-radius:50%; background: var(--ball);
  transform: translateX(-50%);
  transition: transform var(--t-fast) var(--ease), background-color var(--t-fast);
}
@media (hover: hover){
  .nav-link:hover{ color: var(--clay-ink); transform: translateY(2px); }
  .nav-link:hover::after{ transform: translateX(-50%) scale(1.25); }
}
.nav-link:active{ transform: translateY(2px) scale(.97); }
.nav-link.is-active{ color: var(--clay-ink); }
.nav-link.is-active::after{ background: var(--clay-deep); transform: translateX(-50%) scale(1.3); }
.nav-link.is-active::before{ width:3px; }

/* кнопка корзины — тоже висит на нити, а не парит сама по себе */
.cart-btn{
  position:relative; flex:none;
  align-self: flex-start; margin-top: -6px;
  display:inline-flex; align-items:center; gap:9px;
  min-height: var(--tap); padding: 0 18px;
  border-radius: var(--r-pill);
  background: linear-gradient(180deg, var(--clay), var(--clay-deep));
  color: var(--cream); font-weight:800; font-size:15px;
  box-shadow: var(--sh-btn);
  transition: transform var(--t) var(--ease), box-shadow var(--t) var(--ease);
}
@media (hover: hover){
  .cart-btn:hover{ transform: translateY(-2px); box-shadow: var(--sh-btn-up); }
}
.cart-btn:active{ transform: translateY(0) scale(.97); }
.cart-btn svg{ flex:none; }
.cart-btn::before{           /* нитка вверх до шнура */
  content:''; position:absolute; left:50%; top:-9px; width:2px; height:11px;
  background: var(--thread); transform: translateX(-50%);
}
.cart-btn::after{            /* булавка */
  content:''; position:absolute; left:50%; top:-14px;
  width:9px; height:9px; border-radius:50%;
  background: var(--ball);
  box-shadow: 0 1px 2px rgba(122,74,40,.38), inset -1px -1px 0 rgba(122,60,30,.3);
  transform: translateX(-50%);
}
.cart-count{
  position:absolute; top:-7px; right:-5px;
  min-width:23px; height:23px; padding:0 6px;
  border-radius: var(--r-pill);
  background: var(--cream-2); color: var(--clay-ink);
  font-size:12.5px; font-weight:800; line-height:23px; text-align:center;
  box-shadow: 0 3px 8px rgba(120,60,25,.3);
}
.cart-count[hidden]{ display:none; }
/* Сама анимация «добавили в корзину» описана в разделе 14.5 вместе со всем
   остальным движением сайта — здесь её не дублируем. Классы такие:
   .bump на кнопке (дёргается клубок) и .pulse на числе (отскакивает). */

/* ───────────────────────── 6. КАРТОЧКА ТОВАРА ──────────────────────────── */
.card{
  position:relative;
  display:flex; flex-direction:column;
  background: var(--card);
  border: var(--hair);
  border-radius: var(--r-lg);
  box-shadow: var(--sh-1);
  transition: transform var(--t) var(--ease), box-shadow var(--t) var(--ease);
}
/* фокус с клавиатуры не режется краем карточки: вместо overflow:hidden
   фото клипует себя само, а рамка фокуса рисуется снаружи */
.card > *{ min-width:0; }
.card:active{ transform: translateY(0) scale(.985); }
.card:focus-within{ box-shadow: var(--sh-2); }

.card-ph{
  position:relative; display:block;
  aspect-ratio: 1 / 1;
  overflow:hidden;
  background: var(--card-2);
  border-bottom: var(--seam);
  border-radius: var(--r-lg) var(--r-lg) 0 0;
}
.card-ph img{
  width:100%; height:100%;
  object-fit: cover; object-position: 50% 42%;
  transition: transform var(--t-slow) var(--ease);
}
/* паспарту: игрушка лежит в рамке, а не упирается в края —
   разнокалиберные снимки перестают спорить друг с другом */
.card-ph::after{
  content:''; position:absolute; inset:0; z-index:1; pointer-events:none;
  border: 6px solid var(--card-2);
  border-radius: var(--r-lg) var(--r-lg) 18px 18px;
}

/* БЕЙДЖИ. Одна форма — бумажный чип; статус несёт только точка слева,
   поэтому подписи не спорят с игрушкой. Формулировки заказаны Дарьей дословно. */
.badges{
  position:absolute; left:10px; top:10px; z-index:2;
  display:flex; flex-direction:column; align-items:flex-start; gap:6px;
  max-width: calc(100% - 20px);
}
.badge{
  display:inline-flex; align-items:center; gap:7px;
  padding: 6px 12px 6px 10px;
  border-radius: var(--r-pill);
  background: rgba(255,250,240,.94);
  border: var(--hair);
  color: var(--ink);
  font-size:12.5px; font-weight:800; letter-spacing:.01em; line-height:1.25;
  box-shadow: var(--sh-1);
}
.badge::before{
  content:''; flex:none; width:7px; height:7px; border-radius:50%;
  background: var(--ink-soft);
  box-shadow: inset 0 0 0 1px rgba(90,60,35,.35);
}
.badge--stock::before{ background: var(--st-ok); }
/* «на заказ» — второе из двух состояний вещи, точка нейтральная */
.badge--order::before{ background: var(--ink-soft); }
.badge--repeat::before{ background: var(--st-may); }
.badge--norepeat::before{ background: var(--st-no); }
.badge--gacha::before{ background: var(--clay); }

.card-body{
  position:relative;
  display:flex; flex-direction:column; gap:6px;
  padding: 14px 16px 16px; flex:1;
}
.card-name{
  order:-1;
  font-family: var(--font-display); font-weight:700; font-size:17.5px;
  line-height:1.24; color: var(--ink);
  min-height: 44px;
  display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical;
  overflow:hidden;
}
/* фирменный жест: под названием прочерчивается нитка */
.card-body::before{
  content:''; order:0; align-self:flex-start;
  width:52px; height:2px; border-radius:2px; margin-block:-2px;
  background: var(--thread);
  transform: scaleX(0); transform-origin: left center;
  transition: transform .28s var(--ease);
}
.card-meta{ font-size:13.5px; color: var(--ink-soft); }
.card-from{ font-size:13.5px; font-weight:700; color: var(--sage-ink); }
/* приписка про повтор — одна на весь сайт (2026-08-12). Раньше её собирали
   отдельно главная (.index-repeat) и каталог (.catalog-card-repeat): один и
   тот же элемент существовал в двух видах и стоял в разных местах карточки.
   Теперь это строка под размером, и рисует её app.js для любой карточки. */
.card-repeat{
  align-self:flex-start; max-width:100%;
  display:inline-flex; align-items:center; gap:6px;
  margin-top:2px; padding: 3px 10px 4px 8px;
  border-radius: var(--r-pill);
  background: var(--paper-shade);
  border: var(--hair);
  font-size:12px; font-weight:700; line-height:1.35; color: var(--ink-2);
  white-space:nowrap;            /* «повтор невозможен» — в одну строку */
}
.card-repeat::before{
  content:''; flex:none; width:6px; height:6px; border-radius:50%;
  background: var(--st-may);
  box-shadow: inset 0 0 0 1px rgba(90,60,35,.35);
}
.card-repeat--no::before{ background: var(--st-no); }
.card-foot{
  display:flex; align-items:center; justify-content:space-between; gap:10px;
  margin-top:auto; padding-top:10px;
}

@media (hover: hover){
  .card:hover{ transform: translateY(-5px); box-shadow: var(--sh-2); }
  .card:hover .card-ph img{ transform: scale(1.05); }
  .card:hover .card-body::before,
  .card:focus-within .card-body::before{ transform: scaleX(1); }
}
.card-price{ font-size:19px; font-weight:800; color: var(--clay-ink); white-space:nowrap; }
.card .btn--sm{ padding: 10px 14px; }
.card.is-added .btn--sm{ background: linear-gradient(180deg,#6a8360,var(--sage-deep)); color: var(--cream); border-color: transparent; }

/* ───────────────────────── 7. КОРЗИНА ──────────────────────────────────── */
.cart-veil{
  position:fixed; inset:0; z-index: var(--z-veil);
  background: rgba(74,59,48,.5);
  opacity:0; visibility:hidden; pointer-events:none;
  transition: opacity var(--t) var(--ease), visibility 0s var(--t);
}
.cart-veil.is-open{ opacity:1; visibility:visible; pointer-events:auto; transition-delay:0s; }

.cart-drawer{
  position:fixed; top:0; right:0; bottom:0; z-index: var(--z-drawer);
  width: min(430px, 100vw);
  display:flex; flex-direction:column;
  background: var(--paper-lit);
  background-image: linear-gradient(180deg, var(--paper-lit), var(--paper));
  border-left: 3px solid var(--thread);
  box-shadow: var(--sh-drawer);
  transform: translateX(102%);
  visibility:hidden;
  transition: transform var(--t-slow) var(--ease), visibility 0s var(--t-slow);
}
.cart-drawer.is-open{ transform:none; visibility:visible; transition-delay:0s; }

.cart-head{
  display:flex; align-items:center; justify-content:space-between; gap:12px;
  padding: 16px 18px; border-bottom: var(--seam);
}
.cart-head h2{ font-size:24px; }
.cart-body{
  flex:1; overflow-y:auto; overscroll-behavior:contain;
  padding: 12px 18px;
  -webkit-overflow-scrolling: touch;
}
.cart-empty{ text-align:center; color: var(--ink-soft); padding: 48px 8px; }
.cart-empty .hand{ display:block; margin-top:10px; color: var(--sage-ink); }

.cart-item{
  display:flex; gap:12px; align-items:flex-start;
  padding: 14px 0; border-bottom: var(--hair);
}
.cart-thumb{
  width:64px; height:64px; flex:none;
  border-radius: var(--r-sm); object-fit: cover; object-position:50% 42%;
  background: var(--card-2);
  border: var(--hair);
  box-shadow: var(--sh-1);
}
.cart-info{ flex:1; min-width:0; }
.cart-nm{ font-family: var(--font-display); font-weight:700; font-size:15.5px; color: var(--ink); line-height:1.24; }
.cart-pp{ font-size:13px; color: var(--ink-soft); margin-top:3px; }
.cart-qty{ display:flex; align-items:center; gap:4px; margin-top:8px; }
/* 44×44 — палец, а не курсор: меньше этого на телефоне промахиваются */
.cart-qty .icon-btn{ width:44px; height:44px; }
.cart-qty output{ min-width:34px; text-align:center; font-weight:800; color: var(--ink); }
.cart-rm{
  flex:none; min-width: var(--tap); min-height: var(--tap);
  display:inline-flex; align-items:center; justify-content:center;
  color: var(--ink-soft); font-size:18px; border-radius: var(--r-sm);
  transition: color var(--t-fast), background-color var(--t-fast);
}
@media (hover: hover){
  .cart-rm:hover{ color: var(--clay-ink); background: rgba(190,95,53,.1); }
}
.cart-rm:active{ transform: scale(.94); }

.cart-foot{
  padding: 16px 18px calc(18px + env(safe-area-inset-bottom, 0px));
  border-top: var(--seam);
  background: var(--paper-lit);
}
.cart-sum{ display:flex; align-items:baseline; justify-content:space-between; gap:12px; margin-bottom:12px; }
.cart-sum span{ font-weight:700; color: var(--ink-2); }
.cart-sum b{ font-family: var(--font-display); font-size:26px; font-weight:700; color: var(--clay-ink); }
.cart-pay{
  margin-top:12px; font-size: var(--fs-tiny); line-height:1.55; color: var(--ink-soft); text-align:center;
}
.cart-pay b{ color: var(--ink-2); font-weight:800; }
.cart-clear{
  display:flex; align-items:center; justify-content:center;
  width:fit-content; margin: 8px auto 0;
  min-height: var(--tap); padding: 8px 14px;
  font-size:13.5px; font-weight:700; color: var(--ink-soft);
  text-decoration: underline; text-decoration-style: dashed; text-underline-offset:4px;
}
.cart-clear:hover{ color: var(--clay-ink); }

/* ───────────────────────── 8. ПОДВАЛ (деревянный стол) ─────────────────── */
.site-foot{
  position:relative;
  margin-top: var(--sec-gap);
  padding: clamp(30px, 5vw, 54px) 0 calc(24px + env(safe-area-inset-bottom, 0px));
  color: var(--ink);
  background: linear-gradient(180deg, var(--wood-lit) 0%, var(--wood) 55%, var(--wood-deep) 100%);
}
.site-foot::before{           /* мягкая тень столешницы, стыка не видно */
  content:''; position:absolute; left:0; right:0; top:-44px; height:44px;
  background: linear-gradient(180deg, rgba(133,92,58,0), rgba(133,92,58,.13));
  pointer-events:none;
}
.site-foot::after{            /* древесные волокна */
  content:''; position:absolute; inset:0;
  background-image: var(--grain); background-size: 280px 148px;
  opacity:.9; pointer-events:none;
}
.foot-inner{
  position:relative; z-index:1;
  max-width: var(--wrap); margin-inline:auto; padding-inline: var(--pad-page);
  display:grid; gap: clamp(20px, 3vw, 34px);
  grid-template-columns: minmax(220px, 1.2fr) repeat(auto-fit, minmax(180px, 1fr));
  align-items:start;
}
.foot-brand .logo-name{ font-size:19px; }
.foot-brand p{ margin-top:8px; font-size: var(--fs-small); color: #5c4630; max-width: 34ch; }
.foot-col h3{ font-size:16px; margin-bottom:10px; }
.foot-links{ display:flex; flex-direction:column; gap:2px; }
.foot-links a, .foot-contact a{
  display:inline-flex; align-items:center; min-height: var(--tap);
  color: var(--clay-ink); font-weight:700; font-size: var(--fs-small);
  text-decoration: underline; text-decoration-style: dashed; text-underline-offset:4px;
  transition: color var(--t-fast);
}
@media (hover: hover){
  .foot-links a:hover, .foot-contact a:hover{ color: var(--clay-deep); }
}
.foot-links a:active, .foot-contact a:active{ transform: scale(.97); }
.cart-clear:active{ transform: scale(.97); }
.foot-links span{ display:block; font-size:13px; color:#5c4630; margin-top:-6px; }
.foot-note{
  position:relative; z-index:1;
  max-width: var(--wrap); margin: clamp(22px,3vw,34px) auto 0;
  padding-inline: var(--pad-page);
  font-size: var(--fs-tiny); color:#5c4630; line-height:1.7;
}
.foot-note b{ color: var(--ink); }

/* ───────────────────────── 9. ЖИВОСТЬ: тост, клубок, появление ─────────── */
.toast{
  position:fixed; left:50%; bottom: calc(22px + env(safe-area-inset-bottom, 0px));
  z-index: var(--z-toast);
  transform: translate(-50%, 22px); opacity:0; visibility:hidden; pointer-events:none;
  /* без width:max-content плашка могла быть шириной максимум в половину
     экрана: у элемента с left:50% доступное место считается от этой точки
     до правого края, и «Добавила в корзину: Помни…» ломалось на четыре
     строки при пустом месте вокруг (2026-08-12) */
  width: max-content; max-width: min(92vw, 460px);
  padding: 13px 22px; border-radius: var(--r-pill);
  background: var(--card); color: var(--ink);
  border: var(--hair);
  box-shadow: var(--sh-3);
  font-size:14.5px; font-weight:700; text-align:center;
  transition: transform var(--t-slow) var(--ease), opacity var(--t) var(--ease), visibility 0s var(--t-slow);
}
.toast.is-on{ transform: translate(-50%, 0); opacity:1; visibility:visible; transition-delay:0s; }

/* ─── плашка при открытой корзине — ПОД ЗАГОЛОВКОМ ШТОРКИ ────────────────
   Обычный ход на телефоне: положила игрушку → сразу открыла корзину.
   Плашка «Добавила в корзину…» держится пару секунд и снизу ложилась ровно
   на кнопку «Оформить в телеграме» — главное действие оказывалось закрыто.
   Сверху она накрывала заголовок «Корзина» и первую строку списка.
   Теперь она встаёт в промежуток под заголовком, а список на это время
   опускается ровно на её высоту (--toast-h ставит скрипт) — не закрыто
   ничего. Правило с :has() не поддержано браузером — плашка просто ляжет
   поверх списка, как раньше (2026-08-12). */
body.is-cart-open .toast{
  top: calc(var(--cart-head-h, 58px) + 10px + env(safe-area-inset-top, 0px));
  bottom: auto;
  z-index: 96;                          /* поверх шторки (--z-drawer: 90) */
  transform: translate(-50%, -14px);
}
body.is-cart-open .toast.is-on{ transform: translate(-50%, 0); }
/* список опускается только там, где плашка и правда попадает на шторку:
   она шириной до 460 px и стоит по центру окна, шторка — 420 px у правого
   края, и пересекаются они на экранах уже ~1300 px */
@media (max-width: 1300px){
  body.is-cart-open:has(.toast.is-on) .cart-body{
    padding-top: calc(var(--toast-h, 52px) + 20px);
  }
}

.fly-dot{
  position:fixed; z-index: var(--z-fly); width:18px; height:18px;
  border-radius:50%; pointer-events:none;
  background: radial-gradient(circle at 35% 30%, var(--ball-lit), var(--ball) 70%);
  box-shadow: 0 4px 8px rgba(120,60,25,.35), inset -2px -3px 0 rgba(122,60,30,.45);
}
.fly-dot--img{
  width:56px; height:56px; border-radius: var(--r-md);
  background-size: cover; background-position: 50% 42%;
  box-shadow: 0 10px 22px rgba(90,58,30,.4);
}

.reveal{ opacity:0; transform: translateY(20px); }
.reveal.is-in{
  opacity:1; transform:none;
  transition: opacity .6s var(--ease), transform .6s var(--ease);
  transition-delay: var(--rd, 0s);
}

/* ───────────────────────── 10. МОБИЛЬНАЯ ПЕРЕСБОРКА (≤740px) ───────────── */
@media (max-width: 740px){
  :root{ --fs-body: 15.5px; }

  html{ scroll-padding-top: 164px; }   /* шапка телефона 151 px + воздух */

  /* шапка: нить сверху, на ней висят бирка и корзина, под ними — вторая нить
     с разделами. Одинаково на всех пяти страницах (сведено 2026-08-12) */
  .site-head::before{ display:block; top:10px; height:16px; }
  .head-inner{
    flex-wrap: wrap; align-items:center;
    padding: 30px var(--pad-page) 0;
    gap: 10px;
  }
  .logo{ transform: rotate(-2deg); transform-origin:50% 50%; padding: 7px 12px 7px 10px; gap:9px; }
  .logo::before{ display:block; left:21px; top:-12px; height:12px; }
  .logo::after{ left:22px; top:-16px; width:8px; height:8px; }
  .logo-name{ font-size:14px; }
  .logo-sub{ font-size:11.5px; letter-spacing:.03em; }
  .cart-btn{ margin-left:auto; margin-top:0; align-self:center; padding: 0 14px; }
  .cart-btn::before{ top:-13px; height:13px; }
  .cart-btn::after{ top:-17px; width:8px; height:8px; }
  .cart-word{ display:none; }

  /* разделы стоят в тех же полях, что и содержимое страницы, а не полосой
     во всю ширину: иначе крайний пункт упирается в край экрана */
  .nav{
    order:5; position:relative;
    width: 100%;
    margin: 12px 0 0;
    padding: 0;
    display:flex; justify-content:space-between; gap:2px;
  }
  .nav::before{                 /* своя натянутая нить под шапкой */
    content:''; position:absolute; left:0; right:0; top:0; height:3px;
    background: var(--thread); box-shadow: 0 2px 3px rgba(122,74,40,.32);
  }
  .nav-link{
    min-height: var(--tap); padding: 16px 6px 8px;
    align-items:flex-end; font-size:13.5px;
  }
  .nav-link::before{ top:2px; height:11px; }
  .nav-link::after{ top:-2px; width:7px; height:7px; }
  .nav-link:hover{ transform:none; }

  /* карточки — две колонки, друг за дружкой */
  .grid{ grid-template-columns: repeat(2, 1fr); gap: 12px; }
  .grid--wide, .grid--two{ grid-template-columns: 1fr; }
  .grid--tight{ grid-template-columns: repeat(2, 1fr); }

  .card-body{ padding: 12px 12px 14px; gap:5px; }
  .card-name{ font-size:15.5px; min-height: 2.5em; }
  .card-meta{ font-size:13.5px; }
  .card-foot{ flex-direction:column; align-items:stretch; gap:8px; }
  .card-price{ font-size:18px; }
  .card .btn--sm{ width:100%; }
  /* на узкой карточке бейдж не должен закрывать игрушку: чип ужимается,
     подпись остаётся в одну строку */
  .badge{ font-size:12.5px; padding: 5px 9px 5px 7px; gap:6px; }
  .badge::before{ width:6px; height:6px; }
  .badges{ left:8px; top:8px; gap:5px; max-width: calc(100% - 16px); }
  .card-ph::after{ border-width:5px; border-radius: var(--r-lg) var(--r-lg) 14px 14px; }

  /* корзина — во всю ширину */
  .cart-drawer{ width:100vw; border-left:0; border-top: 3px solid var(--thread); }
  .cart-head{ padding: 14px 16px; }
  .cart-body{ padding: 10px 16px; }
  .cart-foot{ padding: 14px 16px calc(16px + env(safe-area-inset-bottom, 0px)); }
  .cart-thumb{ width:58px; height:58px; }

  /* подвал */
  .foot-inner{ grid-template-columns: 1fr; gap:18px; }
  .foot-brand p{ max-width:none; }

  /* главные кнопки на телефоне — во всю ширину, палец не промахнётся */
  .btn--hero{ width:100%; }
}

@media (max-width: 359px){
  .grid, .grid--tight{ grid-template-columns: 1fr; }
  .nav-link{ font-size:12.5px; padding-inline:4px; }
}

/* ───────────────────────── 11. БЕЗ ДВИЖЕНИЯ ────────────────────────────── */
@media (prefers-reduced-motion: reduce){
  *, *::before, *::after{
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
  html{ scroll-behavior: auto; }
  .reveal{ opacity:1 !important; transform:none !important; }
  .site-head.is-hidden{ transform:none; }
  body::before{ animation:none; }
}

/* ════════════════════════════════════════════════════════════════════════
   ГЛАВНАЯ СТРАНИЦА (index.html). Только свои классы с префиксом index-.
   Ничего выше не изменяется, :root не трогается.
   ══════════════════════════════════════════════════════════════════════ */

/* ── первый экран: нить, имя из пряжи, фотография на столе ───────────── */
.index-hero{
  position:relative;
  /* --shelf-h — толщина столешницы, --prop-h — рост самого высокого предмета
     на ней (клубок). Нижний отступ = столешница + предметы: так текст
     заканчивается ровно там, где начинается мастерская, и они не налезают. */
  --shelf-h: clamp(78px, 9vw, 126px);
  --prop-h:  clamp(104px, 10.6vw, 152px);
  padding-top: clamp(4px, 1.4vw, 20px);
  padding-bottom: calc(var(--shelf-h) + var(--prop-h) * .58);
}
.index-hero-in{
  position:relative; z-index:1;
  display:grid; gap: clamp(10px, 3vw, 44px);
  grid-template-columns: 1.04fr .96fr;
  align-items:end;
}

/* деревянная полка во всю ширину — продолжение «стола» из подвала */
.index-shelf{
  position:absolute; left:0; right:0; bottom:0;
  height: var(--shelf-h);
  background-image: var(--grain),
    linear-gradient(180deg, var(--wood-lit) 0%, var(--wood) 55%, var(--wood-deep) 100%);
  background-size: 280px 148px, auto;
  background-repeat: repeat, no-repeat;
  pointer-events:none;
}
.index-shelf::before{           /* светлая кромка столешницы */
  content:''; position:absolute; left:0; right:0; top:0; height:3px;
  background: linear-gradient(90deg, rgba(255,244,222,.95), rgba(255,244,222,.35));
}
.index-shelf::after{            /* мягкая тень над столешницей, стыка не видно */
  content:''; position:absolute; left:0; right:0; top:-46px; height:46px;
  background: linear-gradient(180deg, rgba(133,92,58,0), rgba(133,92,58,.13));
}

/* имя бренда, вывязанное пряжей */
.index-h1{
  margin-top: var(--sp-1);
  /* 7.2vw — потолок, при котором слово «comfortable» помещается в свою
     колонку. При 12.4vw на экранах 741–900 px оно раздвигало сетку и
     съедало колонку с фотографией: от игрушки оставалась белая полоска */
  font-size: clamp(42px, 7.2vw, 78px);
  line-height:1.03; letter-spacing:-.015em;
  filter: drop-shadow(0 1px 0 rgba(255,247,232,.7)) drop-shadow(0 5px 9px rgba(120,80,50,.22));
}
.index-h1 span{ display:block; -webkit-background-clip:text; background-clip:text; color:transparent; }
.index-w1{ background-image: repeating-linear-gradient(112deg,#5d4433 0 3px,#71543e 3px 6px,#54402f 6px 9px); }
.index-w2{ margin-left:.1em; background-image: repeating-linear-gradient(112deg,#a9542b 0 3px,#c66f40 3px 6px,#9c4b24 6px 9px); }
@supports not ((-webkit-background-clip: text) or (background-clip: text)){
  .index-h1 .index-w1{ color: var(--ink); }
  .index-h1 .index-w2{ color: var(--clay-ink); }
}

/* нить, которая дорисовывается сама и завязывается сердечком */
/* блок нити держим низким: раньше между именем бренда и абзацем зияла
   дыра под 200 px, и пауза читалась как забытое место */
.index-thread{ display:block; width:min(100%, 466px); height:auto; margin: var(--sp-1) 0 var(--sp-3); }
.index-draw{
  stroke-dasharray:101; stroke-dashoffset:101;
  animation: index-draw 1.7s cubic-bezier(.6,.15,.35,.9) .25s forwards;
}
@keyframes index-draw{ to{ stroke-dashoffset:0; } }
.index-glow{
  stroke-dasharray:20 80; opacity:0;
  animation: index-glowrun 7s linear 2.4s 3,
             index-glowin .8s ease 2.4s forwards,
             index-glowout .9s ease 22.6s forwards;
}
@keyframes index-glowrun{ from{ stroke-dashoffset:0; } to{ stroke-dashoffset:-100; } }
@keyframes index-glowin{ to{ opacity:.9; } }
@keyframes index-glowout{ to{ opacity:0; } }

/* абзац не доходит до нити: у неё свой коридор справа от текста */
.index-lede{ max-width: 40ch; }
.index-narrow{ display:none; }   /* короткая версия вступления — только для телефона */
.index-z{ font-family: var(--font-hand); font-weight:600; font-size:1.28em; color: var(--sage-ink); }

.index-cta{ display:flex; flex-wrap:wrap; gap: var(--sp-2); margin-top: clamp(16px, 2.4vw, 24px); }
/* строка условий не заезжает под клубок: справа от неё стоит мастерская */
.index-terms{ margin-top: var(--sp-2); max-width: 40ch; color: var(--ink-soft); }
.index-terms b{ color: var(--ink-2); font-weight:800; }

/* фотография-карточка, лежащая на столе, и бирка с ценой на нитке */
.index-photo{
  position:relative;
  width:min(100%, 460px);
  margin-inline:auto;
  margin-bottom: calc(-1 * clamp(34px, 5vw, 74px));
}
.index-photo-move{ position:relative; will-change: transform; }
.index-photo-move::after{        /* контактная тень на столешнице */
  content:''; position:absolute; left:7%; right:7%; bottom:-16px; height:30px;
  border-radius:50%; pointer-events:none;
  background: radial-gradient(ellipse at 50% 50%, rgba(110,70,40,.34), rgba(110,70,40,0) 70%);
}
.index-photo-card{
  position:relative; overflow:hidden;
  border-radius: var(--r-xl);
  background: var(--card-2);
  border: var(--hair);
  box-shadow: var(--sh-2);
  padding: 8px;                       /* паспарту, как в карточках каталога */
  transform: rotate(-1.8deg);
  transition: transform var(--t-slow) var(--ease);
}
.index-photo-card img{
  width:100%; height:auto; aspect-ratio: 1 / 1; object-fit: cover;
  border-radius: var(--r-lg);
}
@media (hover: hover){
  .index-photo:hover .index-photo-card{ transform: rotate(0deg) translateY(-5px); }
}

.index-tag{
  position:absolute; left:-14px; bottom:-28px;
  width: clamp(172px, 46%, 210px);
  padding: 12px 14px 14px 26px;
  background: linear-gradient(165deg, var(--tag), var(--tag-2));
  border-radius: var(--r-sm);
  box-shadow: var(--sh-1), inset 0 1px 0 rgba(255,248,232,.7);
  text-align:center;
  transform: rotate(-4deg);
  transform-origin: 14px -34px;
  animation: tag-sway 5.4s ease-in-out .8s infinite alternate;
  transition: transform var(--t) var(--ease);
}
.index-tag:focus-within{ animation-play-state: paused; }
@media (hover: hover){
  .index-tag:hover{ animation:none; transform: rotate(-1deg) translateY(-1px); }
}
.index-tag::before{              /* дырка под нить */
  content:''; position:absolute; left:11px; top:14px; width:9px; height:9px;
  border-radius:50%; background: var(--paper);
  box-shadow: inset 0 1px 2px rgba(110,70,40,.45);
}
.index-tag::after{               /* сама нить уходит вверх */
  content:''; position:absolute; left:13px; top:-46px; width:2.5px; height:62px;
  border-radius:2px; background: var(--thread);
}
.index-tag-nm{ font-family: var(--font-hand); font-weight:700; font-size:21px; line-height:1.06; color:#6b4a35; }
.index-tag-price{ margin-top:2px; font-weight:800; font-size:20px; color: var(--clay-ink); }
.index-tag-sub{
  margin-top:4px; font-size: var(--fs-tiny); font-weight:700;
  letter-spacing:.06em; text-transform:uppercase; line-height:1.3; color: var(--tag-ink);
}
.index-tag-btn{ margin-top: var(--sp-1); width:100%; }

.index-pull{ margin-top: var(--sp-4); text-align:center; }

/* ── полоска доверия: четыре бумажные бирки на одной нити ────────────── */
.index-trust{
  position:relative;
  display:grid; grid-template-columns: repeat(4, 1fr);
  gap: clamp(12px, 1.8vw, 22px); text-align:center;
  padding-top: 26px;      /* место под нить, на которой они висят */
}
/* сама нить: слегка провисает, толщина не пляшет — картинка тянется
   только по ширине, высота у неё постоянная */
.index-trust::before{
  content:''; position:absolute; left:-1%; right:-1%; top:2px; height:14px;
  background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 10' preserveAspectRatio='none'><path d='M0,2.4 Q50,8.6 100,2.4' fill='none' stroke='%23be5f35' stroke-width='2.2' stroke-linecap='round'/></svg>") no-repeat center / 100% 100%;
}
.index-trust-i{
  position:relative;
  padding: 16px clamp(8px, 1.4vw, 16px) 18px;
  background: linear-gradient(165deg, var(--tag), var(--tag-2));
  border-radius: var(--r-sm);
  box-shadow: var(--sh-1), inset 0 1px 0 rgba(255,248,232,.7);
  transform: rotate(var(--tw, 0deg));
  transform-origin: 50% -22px;
  animation: index-sway var(--td, 6s) ease-in-out infinite alternate;
}
.index-trust-i::before{            /* дырка под нить */
  content:''; position:absolute; left:calc(50% - 4.5px); top:7px;
  width:9px; height:9px; border-radius:50%; background: var(--paper);
  box-shadow: inset 0 1px 2px rgba(110,70,40,.45);
}
.index-trust-i::after{             /* нить от бирки вверх, к общей нити */
  content:''; position:absolute; left:calc(50% - 1.25px); top:-22px;
  width:2.5px; height:30px; border-radius:2px; background: var(--thread);
}
@keyframes index-sway{
  from{ transform: rotate(calc(var(--tw, 0deg) - 1.1deg)); }
  to  { transform: rotate(calc(var(--tw, 0deg) + 1.1deg)); }
}
.index-trust-n{
  font-family: var(--font-display); font-weight:700;
  font-size: clamp(24px, 3.1vw, 33px); line-height:1.1; color: var(--clay-ink);
}
.index-trust-l{ margin-top: 6px; font-size: var(--fs-small); line-height:1.35; color: var(--tag-ink); }

/* ── строка заголовка секции со ссылкой справа ───────────────────────── */
.index-head-row{
  display:flex; align-items:flex-end; justify-content:space-between;
  gap:16px; flex-wrap:wrap;
  margin-bottom: clamp(18px, 2.6vw, 30px);
}
.index-head-row .section-head{ margin-bottom:0; }
.index-more{ flex:none; }
.index-loading{ grid-column: 1 / -1; padding: var(--sp-3) 0; }

/* ── гача слаймиков ──────────────────────────────────────────────────── */
.index-gacha{
  display:grid; grid-template-columns: minmax(0,.88fr) minmax(0,1.12fr);
  gap: clamp(18px, 3vw, 38px); align-items:center;
  padding: clamp(18px, 3vw, 34px);
  background: linear-gradient(160deg, var(--card), var(--card-2));
  border: var(--seam);
  border-radius: var(--r-xl);
  box-shadow: var(--sh-1);
}
.index-gacha-ph{ position:relative; }
.index-gacha-ph img{
  width:100%; height:auto; aspect-ratio: 1 / 1; object-fit: cover;
  border-radius: var(--r-lg); background: var(--card-2);
  border: var(--hair); box-shadow: var(--sh-1);
}
.index-gacha-badge{ position:absolute; left:12px; top:12px; }
.index-gacha-txt .section-title{ margin-top:6px; }
.index-gacha-txt .lead{ margin-top: var(--sp-2); }
.index-gacha-buys{ display:grid; gap: var(--sp-2); margin-top: var(--sp-3); }
.index-buy{
  display:flex; align-items:center; justify-content:space-between; gap:12px; flex-wrap:wrap;
  padding: 12px 14px; border-radius: var(--r-md);
  background: var(--paper-lit); border: var(--hair);
}
.index-buy-nm{ font-family: var(--font-display); font-weight:700; font-size:16px; color: var(--ink); }
.index-buy-sub{ font-size: var(--fs-small); color: var(--ink-soft); }
.index-buy-act{ display:flex; align-items:center; gap:12px; }
.index-gacha-sets{ margin-top: var(--sp-2); color: var(--ink-2); }
.index-gacha-sets b{ color: var(--clay-ink); font-weight:800; }
.index-gacha-sets s{ color: var(--ink-soft); }
.index-gacha-txt .btn--ghost{ margin-top: var(--sp-1); }

/* шов-разделитель между секциями */
.index-seam{
  height:12px; max-width: calc(var(--wrap) - 2 * var(--pad-page));
  margin-inline:auto; opacity:.3;
  background-image: var(--stitch); background-repeat: repeat-x; background-size: 34px 12px;
}

/* ── как заказать ────────────────────────────────────────────────────── */
.index-steps{
  display:grid; gap: var(--gap);
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  list-style:none;
}
.index-step{ position:relative; padding-top: var(--sp-4); }
.index-step-n{
  position:absolute; top:-22px; left: clamp(18px, 3vw, 28px);
  width:46px; height:46px; border-radius:50%;
  display:flex; align-items:center; justify-content:center;
  background: radial-gradient(circle at 35% 30%, var(--ball-lit), var(--ball) 70%);
  box-shadow: var(--sh-1), inset -3px -4px 0 rgba(122,60,30,.32);
  color: var(--cream); font-family: var(--font-display); font-weight:700; font-size:20px;
}
.index-step p{ color: var(--ink-2); }
.index-pay{
  margin-top: clamp(18px, 2.6vw, 26px);
  display:flex; align-items:center; justify-content:space-between;
  gap: clamp(14px, 2.4vw, 26px); flex-wrap:wrap;
}
.index-pay p{ flex:1 1 400px; color: var(--tag-ink); }
.index-pay .btn{ flex:none; }

/* ── отзывы ──────────────────────────────────────────────────────────── */
.index-reviews{
  display:grid; gap: var(--gap); align-items:start;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
}
.index-quote{ display:flex; flex-direction:column; gap: var(--sp-2); padding-top: var(--sp-4); }
.index-quote-ph{
  width:100%; height:auto; aspect-ratio: 1 / 1;
  object-fit: cover; object-position: 50% 45%;
  border-radius: var(--r-md); background: var(--card-2);
  border: var(--hair);
}
.index-quote p{ font-size:15.5px; }
.index-quote figcaption{ margin-top:auto; }

/* ── тизер бинго ─────────────────────────────────────────────────────── */
.index-bingo{
  display:grid; grid-template-columns: minmax(0,1.05fr) minmax(0,.95fr);
  gap: clamp(20px, 3vw, 40px); align-items:center;
}
.index-bingo-txt .lead{ margin-top: var(--sp-2); }
.index-bingo-txt .btn{ margin-top: var(--sp-3); }
.index-bingo-tiles{ display:grid; grid-template-columns: repeat(3, 1fr); gap: var(--sp-1); }
.index-tile{
  display:block; overflow:hidden;
  border-radius: var(--r-md); background: var(--card-2);
  border: var(--hair); box-shadow: var(--sh-1);
  padding: 4px;
  transform: rotate(var(--tr, 0deg));
  transition: transform var(--t) var(--ease);
}
.index-tile img{
  width:100%; height:auto; aspect-ratio: 1 / 1; object-fit: cover;
  border-radius: 9px;
}
@media (hover: hover){
  .index-bingo:hover .index-tile{ transform: rotate(0deg); }
}

/* ── широкие экраны: витрина наличия в три больших карточки ──────────── */
@media (min-width: 741px){
  .index-stock{ grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); }
}

/* ── телефон ─────────────────────────────────────────────────────────── */
@media (max-width: 740px){
  .index-hero{
    --shelf-h: clamp(64px, 16vw, 84px);
    --prop-h:  clamp(76px, 24vw, 104px);
    padding-bottom: calc(var(--shelf-h) + var(--prop-h));
  }
  /* ПОРЯДОК НА ТЕЛЕФОНЕ: имя — нить — игрушка — текст — кнопки.
     Раньше фотография начиналась на 694-м пикселе: человек открывал сайт
     про игрушки и ни одной игрушки не видел. display:contents убирает
     обёртку текста, и все части встают одной колонкой в нужном порядке. */
  .index-hero-text{ display:contents; }
  .index-hero-in{ grid-template-columns: 1fr; gap:0; align-items:stretch; }
  .index-hero .overline{ order:1; }
  .index-h1{ order:2; font-size: clamp(40px, 12.8vw, 56px); }
  /* 366 px ширины дают ровно 90 px высоты — потолок, заданный макетом */
  .index-thread{ order:3; width:min(100%, 366px); margin: 0 0 var(--sp-1); }
  .index-photo{ order:4; }
  .index-lede{ order:5; max-width:none; }
  .index-cta{ order:6; gap:10px; }
  .index-terms{ order:7; max-width:none; line-height:1.7; }
  .index-wide{ display:none; }
  .index-narrow{ display:inline; }

  .index-photo{
    width:min(100%, 380px); margin-top: var(--sp-2);
    margin-bottom: var(--sp-5);          /* место бирке с ценой, она свисает вниз */
  }
  .index-tag{ left:-6px; bottom:-22px; width: clamp(156px, 50%, 190px); padding-right:12px; }
  .index-tag-nm{ font-size:19px; }
  /* рукописная приписка живёт только на широком экране: на телефоне
     она попадала под бирку и обрезалась столешницей */
  .index-pull{ display:none; }

  /* бирки доверия — 2×2, без перегородок и без общей нити:
     вешать четыре штуки на две строки одной нити нечестно */
  .index-trust{ grid-template-columns: repeat(2, 1fr); gap: var(--sp-2); padding-top:0; }
  .index-trust::before{ display:none; }
  .index-trust-i::before, .index-trust-i::after{ display:none; }
  .index-trust-i{ padding: 14px 10px 16px; transform-origin: 50% 50%; }

  .index-head-row{ align-items:flex-start; gap: var(--sp-1); }
  .index-gacha, .index-bingo{ grid-template-columns: 1fr; }
  .index-gacha-buys{ gap: var(--sp-2); }
  .index-buy{ align-items:flex-start; }
  .index-buy-act{ width:100%; justify-content:space-between; }
  .index-steps{ gap: var(--sp-4); }
  .index-pay{ text-align:left; }
  .index-bingo-tiles{ order:-1; }
}

/* ════════════════════════════════════════════════════════════════════════
   ГЛАВНАЯ · МАСТЕРСКАЯ НА СТОЛЕ, ИГРУШКА НЕДЕЛИ, ПОЛКИ, ЗАМЫКАНИЕ НИТИ
   Дополнение к блоку выше. Всё с префиксом index-, :root не трогается,
   в анимациях только transform и opacity.
   ══════════════════════════════════════════════════════════════════════ */

/* ── сцена: предметы стоят на столешнице, кликов не ловят ────────────── */
.index-scene{
  position:absolute; inset:0; z-index:0;
  pointer-events:none;
}
.index-scene-in{
  position:absolute; inset:0;
  width: min(var(--wrap), calc(100% - 2 * var(--pad-page)));
  margin-inline:auto;
}
/* соединительная нить от сердечка к клубку: путь считает скрипт,
   толщина линии не пляшет при растяжении (non-scaling-stroke) */
.index-link{ position:absolute; inset:0; width:100%; height:100%; }
.index-link-p{
  stroke-dasharray:101; stroke-dashoffset:101;
  animation: index-draw 1.1s cubic-bezier(.6,.15,.35,.9) 1.55s forwards;
}
/* петля, вытянутая из буквы «e»: рисуется первой — сначала нить выходит из
   слова, и только потом разбегается по экрану */
.index-seam-p{
  stroke-dasharray:101; stroke-dashoffset:101;
  animation: index-draw 1.05s cubic-bezier(.6,.15,.35,.9) .2s forwards;
}

.index-prop{
  position:absolute;
  height: var(--h);
  bottom: calc(var(--shelf-h) - var(--h) * var(--sink, .08) - 5px);
}
.index-prop > svg, .index-prop > img{ display:block; height:100%; width:auto; }

/* клубок с крючком — правее текста, перед фотографией */
.index-prop--ball{
  --h: var(--prop-h); --sink: .088;
  right: 49%;
}
/* кружка с чаем и слаймик — слева, у самого края стола */
.index-prop--mug{
  --h: clamp(52px, 5.4vw, 78px); --sink: .072;
  left: 0;
}
.index-prop--slime{
  --h: clamp(56px, 6vw, 84px); --sink: .12;
  left: clamp(58px, 7.4vw, 100px);
}
.index-prop--slime::before{        /* контактная тень слаймика на столе */
  content:''; position:absolute; left:0; right:0; bottom:6%; height:22%;
  border-radius:50%;
  background: radial-gradient(ellipse at 50% 50%, rgba(110,70,40,.34), rgba(110,70,40,0) 70%);
}

/* пар над кружкой: только transform и opacity */
.index-steam path{ transform-box: fill-box; transform-origin: 50% 100%; }
.index-steam-1{ animation: index-steam 4.6s ease-in-out infinite; }
.index-steam-2{ animation: index-steam 5.4s ease-in-out .7s infinite; }
.index-steam-3{ animation: index-steam 6.1s ease-in-out 1.4s infinite; }
@keyframes index-steam{
  0%   { opacity:0;   transform: translateY(6px)  scale(.9); }
  35%  { opacity:.85; }
  100% { opacity:0;   transform: translateY(-12px) scale(1.06); }
}

/* ── игрушка недели ──────────────────────────────────────────────────── */
.index-week{
  display:grid; grid-template-columns: minmax(0,.78fr) minmax(0,1.22fr);
  gap: clamp(20px, 3.4vw, 44px); align-items:center;
  padding: clamp(18px, 3vw, 32px);
  background: linear-gradient(160deg, var(--card), var(--card-2));
  border: var(--hair); border-radius: var(--r-xl);
  box-shadow: var(--sh-1);
}
.index-week-ph{
  position:relative;
  padding:6px; border-radius: var(--r-lg);
  background: var(--card-2); border: var(--hair);
  box-shadow: var(--sh-1);
  transform: rotate(-1.2deg);
}
.index-week-ph img{
  display:block; width:100%; height:auto;
  aspect-ratio: 1 / 1; object-fit: cover; object-position: 50% 42%;
  border-radius: 14px; background: var(--card-2);
}
.index-week-mark{                  /* рукописная бирка поверх фотографии */
  position:absolute; right:-10px; top:-16px; z-index:2;
  padding: 7px 15px 9px; border-radius: var(--r-sm);
  background: linear-gradient(165deg, var(--tag), var(--tag-2));
  box-shadow: var(--sh-1), inset 0 1px 0 rgba(255,248,232,.7);
  color:#6b4a35; font-size:20px; line-height:1;
  transform: rotate(4deg);
}
.index-week-nm{
  margin-top: var(--sp-2);
  font-family: var(--font-display); font-weight:700;
  font-size: var(--fs-h3); line-height:1.2; color: var(--ink);
}
.index-week-from{ margin-top:4px; font-size:13.5px; font-weight:700; color: var(--sage-ink); }
.index-week-note{ margin-top: var(--sp-2); }
.index-week-buy{
  display:flex; align-items:center; flex-wrap:wrap;
  gap: var(--sp-2) var(--sp-3); margin-top: var(--sp-3);
}
.index-week-buy .card-price{ font-size:26px; }
.index-week-more{ margin-top: var(--sp-3); }

/* ── деревянные полки под рядами витрины ─────────────────────────────── */
/* карточка не висит в воздухе, а стоит на полке: полоса шире карточки на
   половину зазора, поэтому у соседей она сливается в одну линию ряда */
.index-stock .card::after{
  content:''; position:absolute; pointer-events:none;
  left: calc(-1 * var(--gap) / 2 - 1px);
  right: calc(-1 * var(--gap) / 2 - 1px);
  bottom:-13px; height:3px; border-radius:2px;
  background: linear-gradient(90deg, var(--wood-lit), var(--wood-deep));
  box-shadow: 0 4px 9px rgba(120,80,45,.18);
  transition: transform var(--t) var(--ease);
}
@media (hover: hover){
  /* карточку подняли — полка остаётся на месте, иначе поднимется стол */
  .index-stock .card:hover::after{ transform: translateY(5px); }
}

/* ── конец страницы: нить сматывается обратно в клубок ───────────────── */
.index-end{
  position:relative;
  padding: clamp(6px, 1.6vw, 18px) 0 clamp(34px, 4.6vw, 60px);
}
.index-end-in{ display:flex; flex-direction:column; align-items:center; text-align:center; }
.index-end-yarn{ display:block; width: clamp(116px, 12vw, 158px); height:auto; }
.index-draw--late{ animation-delay: 2.2s; }
.index-end-hand{
  margin-top: var(--sp-2);
  font-size: clamp(27px, 3.6vw, 40px); color: var(--clay-ink);
}
.index-end-sub{ max-width: 46ch; margin-top: var(--sp-2); color: var(--ink-2); }
.index-end .btn{ margin-top: var(--sp-3); }

/* ── узкий десктоп: текст короче, чтобы не залезал под клубок ────────── */
@media (min-width: 741px) and (max-width: 1000px){
  .index-terms{ max-width: 30ch; }
  .index-prop--slime{ left: clamp(52px, 6.6vw, 84px); }
}

/* ── телефон ─────────────────────────────────────────────────────────── */
@media (max-width: 740px){
  /* через полстраницы нить на телефоне не тянем — длинную линию к клубку
     скрипт и так не рисует. Но петля из буквы «e» нужна и здесь: это тот
     самый жест, ради которого стиль называется «Нить» */
  .index-link-p{ display:none; }
  .index-prop--ball{ right: 4%; }
  .index-prop--mug{ --h: clamp(46px, 12vw, 62px); left: 2%; }
  .index-prop--slime{ --h: clamp(50px, 13vw, 68px); left: clamp(52px, 15vw, 78px); }

  .index-week{ grid-template-columns: 1fr; gap: var(--sp-3); }
  .index-week-ph{ transform: rotate(-1deg); }
  .index-week-mark{ right:-4px; top:-14px; font-size:19px; }
  .index-week-buy{ gap: var(--sp-2); }
  .index-week-buy .btn{ flex:1 1 160px; }
  .index-week-more{ margin-top: var(--sp-2); }

  .index-stock .card::after{ bottom:-10px; }
}

/* печать — вдруг Дарья захочет распечатать прайс */
@media print{
  .site-head, .cart-drawer, .cart-veil, .toast, .btn{ display:none !important; }
  body::before, body::after{ display:none; }
  html{ background:#fff; }
  .card{ break-inside: avoid; box-shadow:none; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   12. БИНГО ПО ФАНДОМАМ — только страница bingo.html (префикс .bingo-)
   Чужие правила не трогаются, :root не меняется. Анимации — transform/opacity.
   ══════════════════════════════════════════════════════════════════════════ */

.bingo-top{ padding-bottom: var(--sp-3); }
.bingo-lead{ max-width: 64ch; margin-top: var(--sp-3); }

/* три бирки-подсказки «как играть» */
.bingo-steps{
  list-style:none;
  display:flex; flex-wrap:wrap; gap: var(--sp-2) var(--sp-3);
  margin-top: var(--sp-3);
}
.bingo-step{
  font-weight:700; font-size: var(--fs-small);
  padding: 10px 16px 12px 26px;
}
.bingo-steps .bingo-step:nth-child(2){ animation-duration: 6.6s; transform: rotate(1.8deg); }
.bingo-steps .bingo-step:nth-child(3){ animation-duration: 4.8s; }

/* ── раскладка: поле слева, бирка с выбранной игрушкой справа ─────────── */
.bingo-play{ display:grid; gap: var(--gap); align-items:start; }
.bingo-main{ min-width:0; }

/* ── счёт и звание ───────────────────────────────────────────────────── */
.bingo-score{ display:grid; gap: var(--sp-1); }
.bingo-score-top{
  display:flex; align-items:baseline; justify-content:space-between; gap: 10px 18px;
  flex-wrap:wrap;
}
.bingo-rank{
  font-family: var(--font-display); font-weight:700; line-height:1.15;
  font-size: clamp(19px, 2.6vw, 26px); color: var(--ink);
}
.bingo-count{ font-size:15px; font-weight:700; color: var(--ink-2); white-space:nowrap; }
.bingo-count b{ font-size:21px; font-weight:800; color: var(--clay-ink); }

.bingo-bar{
  position:relative; height:13px; overflow:hidden;
  border-radius: var(--r-pill);
  background: var(--paper-shade);
  border: var(--hair);
}
.bingo-bar-fill{
  position:absolute; inset:0; border-radius: inherit;
  background: linear-gradient(90deg, var(--ball-lit), var(--clay));
  transform: scaleX(var(--p, 0)); transform-origin: 0 50%;
  transition: transform var(--t-slow) var(--ease);
}
.bingo-rank-note{ font-size: var(--fs-small); color: var(--ink-2); }
.bingo-lines-note{ font-size: var(--fs-small); font-weight:700; color: var(--sage-ink); }

/* ── поле 5 × 5 ──────────────────────────────────────────────────────── */
.bingo-board-outer{ position:relative; margin-top: var(--sp-2); }
.bingo-board{
  display:grid; grid-template-columns: repeat(5, 1fr);
  gap: clamp(8px, 1.3vw, 14px);
}
.bingo-fallback{
  grid-column: 1 / -1;
  padding: clamp(18px, 3vw, 28px);
  background: var(--card); border: var(--hair);
  border-radius: var(--r-lg); box-shadow: var(--sh-1);
  color: var(--ink-2); font-size: var(--fs-small);
}

.bingo-cell{
  position:relative; display:block; padding:0;
  touch-action: manipulation; -webkit-tap-highlight-color: transparent;
  background: var(--card-2);
  border: 2px solid rgba(140,100,64,.16);
  border-radius: var(--r-md);
  box-shadow: var(--sh-1);
  transition: transform var(--t) var(--ease), box-shadow var(--t) var(--ease),
              border-color var(--t) var(--ease);
}
/* рамка фокуса раньше срезалась краем клетки — клипует теперь только фото */
.bingo-cell:focus-visible{ outline: 3px dashed var(--thread); outline-offset: 3px; }
.bingo-cell:active{ transform: translateY(0) scale(.97); }
@media (hover: hover){
  .bingo-cell:hover{ transform: translateY(-3px); box-shadow: var(--sh-2); border-color: rgba(190,95,53,.45); }
}

.bingo-ph{
  position:relative; display:block; aspect-ratio: 1 / 1; overflow:hidden;
  background: var(--card-2);
  border-radius: 12px 12px 0 0;      /* внутренний радиус клетки: 14 − 2 */
}
.bingo-ph img{
  width:100%; height:100%;
  object-fit: cover; object-position: 50% 42%;
  transition: transform var(--t-slow) var(--ease);
}
@media (hover: hover){
  .bingo-cell:hover .bingo-ph img{ transform: scale(1.06); }
}
/* тёплая вуаль отмеченной клетки — цветом, без filter */
.bingo-ph::after{
  content:''; position:absolute; inset:0;
  background: rgba(190,95,53,.26);
  opacity:0; transition: opacity var(--t) var(--ease);
  pointer-events:none;
}

/* сердечко-отметка в углу: игрушку не закрывает и не спорит с ниткой линии */
.bingo-mark{
  position:absolute; right:5%; top:5%;
  width:40%; max-width:48px; aspect-ratio: 32 / 30;
  transform-origin: 85% 15%;
  transform: scale(.3) rotate(-16deg);
  opacity:0;
  transition: transform var(--t) var(--ease), opacity var(--t-fast) var(--ease);
  pointer-events:none;
}
.bingo-mark svg{ width:100%; height:100%; }

.bingo-nm{
  display:block; padding: 8px 8px 10px;
  font-family: var(--font-display); font-weight:700; font-size:13.5px; line-height:1.22;
  color: var(--ink);
  min-height: calc(2 * 1.22em + 18px);
  overflow:hidden;
  display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical;
}

/* отмечено */
.bingo-cell.is-on{ border-color: var(--thread); border-style: dashed; }
.bingo-cell.is-on .bingo-ph::after{ opacity:1; }
.bingo-cell.is-on .bingo-mark{ transform: scale(1) rotate(-7deg); opacity:1; }
.bingo-cell.is-on .bingo-nm{ color: var(--clay-ink); }

/* клетка внутри собранной линии */
.bingo-cell.is-line{
  border-color: var(--sage-deep); border-style: solid;
  box-shadow: 0 0 0 3px rgba(91,112,82,.34), var(--sh-2);
}
.bingo-cell.is-line .bingo-ph::after{ background: rgba(91,112,82,.22); }

/* нитка, перечёркивающая собранную линию */
.bingo-lines{ position:absolute; inset:0; pointer-events:none; z-index:3; }
.bingo-thread{
  position:absolute; height:12px; margin-top:-6px;
  border-radius: var(--r-pill);
  background-color: rgba(255,248,240,.55);
  background-image: var(--stitch);
  background-repeat: repeat-x; background-size: 34px 12px;
  box-shadow: var(--sh-1);
  transform-origin: 0 50%;
  transform: rotate(var(--ang, 0deg)) scaleX(1);
}
.bingo-thread.is-new{ animation: bingo-draw .55s var(--ease) both; }
@keyframes bingo-draw{
  from{ transform: rotate(var(--ang, 0deg)) scaleX(0); }
  to  { transform: rotate(var(--ang, 0deg)) scaleX(1); }
}

/* ── строка-подпись под полем ────────────────────────────────────────── */
.bingo-live{
  display:flex; align-items:center; min-height:52px;
  margin-top: var(--sp-2);
  padding: 10px 16px;
  background: linear-gradient(165deg, var(--tag), var(--tag-2));
  border-radius: var(--r-md);
  box-shadow: var(--sh-1), inset 0 1px 0 rgba(255,248,232,.7);
  color: var(--tag-ink); font-size: var(--fs-small); font-weight:700; line-height:1.4;
}

/* ── кнопки под полем ────────────────────────────────────────────────── */
.bingo-controls{
  display:flex; flex-wrap:wrap; gap: var(--sp-2);
  margin-top: var(--sp-3);
}
.bingo-save-note{ margin-top: var(--sp-1); }

/* ── боковая колонка ─────────────────────────────────────────────────── */
.bingo-side{ display:grid; gap: var(--gap); align-content:start; min-width:0; }
.bingo-pick{
  background: linear-gradient(168deg, var(--paper-lit), var(--paper-shade));
  display:grid; gap:12px;
}
.bingo-pick-h{ font-size:19px; }
.bingo-pick-from{ font-size:13.5px; font-weight:800; color: var(--sage-ink); margin-top:-6px; }
.bingo-pick-hint{ font-size: var(--fs-small); color: var(--ink-2); }
.bingo-pick-ph{
  display:block; overflow:hidden; border-radius: var(--r-md);
  border: var(--seam);
  background: var(--card-2);
}
.bingo-pick-ph img{ width:100%; aspect-ratio: 1 / 1; object-fit: cover; object-position: 50% 42%; }
.bingo-pick-price{
  font-family: var(--font-display); font-weight:700; font-size:17px; color: var(--clay-ink);
}
.bingo-pick-link{ justify-self:start; }
.bingo-pick .card{ margin-top:2px; }

.bingo-quote{ display:grid; gap:8px; justify-items:start; }
.bingo-quote .hand{ color: var(--clay-ink); }
.bingo-quote a{ font-weight:800; }
/* ссылка на канал — отдельной строкой и с полем под палец: внутри абзаца
   у неё было 17 px высоты, мимо такой промахиваются */
.bingo-quote-src{
  display:inline-flex; align-items:center; min-height: var(--tap);
  margin-top:-4px; padding: 4px 2px;
  font-size: var(--fs-small); font-weight:800; color: var(--clay-ink);
  text-decoration: underline; text-underline-offset: 3px;
  text-decoration-thickness: 1.5px; text-decoration-color: rgba(190,95,53,.45);
  transition: color var(--t) var(--ease), text-decoration-color var(--t) var(--ease);
}
.bingo-quote-src:hover{ color: var(--ink); text-decoration-color: currentColor; }
.bingo-quote-src:active{ transform: scale(.98); }

.bingo-rank-list{ list-style:none; display:grid; gap:2px; }
.bingo-rank-row{
  display:flex; align-items:baseline; gap:10px;
  padding: 7px 8px; border-radius: var(--r-xs);
  font-size:13.5px; line-height:1.35; color: var(--tag-ink);
}
.bingo-rank-num{
  flex:none; min-width:46px;
  font-weight:800; font-size:12.5px; color: var(--clay-ink);
}
.bingo-rank-row.is-now{
  background: rgba(255,248,240,.72);
  font-weight:800; color: var(--ink);
  box-shadow: inset 0 0 0 1px rgba(140,100,64,.2);
}

/* ── концовка ────────────────────────────────────────────────────────── */
.bingo-finale{
  margin-top: clamp(20px, 3vw, 32px);
  opacity:0; transform: translateY(16px);
  transition: opacity var(--t-slow) var(--ease), transform var(--t-slow) var(--ease);
}
.bingo-finale.is-on{ opacity:1; transform:none; }
.bingo-finale .overline{ color: var(--sage-ink); }
.bingo-finale-h{ font-family: var(--font-display); font-weight:700; font-size: var(--fs-h2); color: var(--ink); margin-top:6px; }
.bingo-finale .hand{ display:block; margin-top:6px; }
.bingo-finale-txt{ margin-top: var(--sp-1); font-size: var(--fs-small); color: var(--tag-ink); max-width: 62ch; }
.bingo-finale-btns{ display:flex; flex-wrap:wrap; gap: var(--sp-2); margin-top: var(--sp-3); }

/* ── «не нашли своё» ─────────────────────────────────────────────────── */
/* абзац не растягивается на всю ширину полосы: строка длиннее ~62 знаков
   читается тяжело, а сама коробка теперь во всю ширину страницы */
.bingo-more-txt{ max-width: 62ch; font-size: var(--fs-lead); color: var(--ink-2); }
.bingo-terms{
  list-style:none; display:grid; gap: var(--sp-1);
  margin-top: var(--sp-3); padding-top: var(--sp-2);
  border-top: var(--seam);
  font-size: var(--fs-small); color: var(--ink-2);
}
.bingo-terms li{ padding-left:22px; position:relative; }
.bingo-terms li::before{
  content:''; position:absolute; left:2px; top:8px;
  width:9px; height:9px; border-radius:50%;
  background: var(--ball);
}
.bingo-more-btns{ display:flex; flex-wrap:wrap; gap: var(--sp-2); margin-top: var(--sp-3); }

/* ── салют из клубочков (только по transform/opacity) ────────────────── */
.bingo-conf{ animation: bingo-conf .95s var(--ease-soft) forwards; }
@keyframes bingo-conf{
  from{ transform: translate(0,0) scale(.65); opacity:1; }
  to  { transform: translate(var(--cx, 0), var(--cy, 0)) scale(1.05) rotate(var(--cr, 0deg)); opacity:0; }
}

/* ── широкий экран: поле и бирка рядом ───────────────────────────────── */
@media (min-width: 981px){
  .bingo-play{ grid-template-columns: minmax(0, 1fr) 344px; }
  .bingo-side{ position:sticky; top:118px; }
}

/* ── телефон: поле остаётся 5 × 5 и нажимаемым ───────────────────────── */
@media (max-width: 740px){
  .bingo-board{ gap:8px; }
  .bingo-cell{ border-radius: var(--r-sm); }
  .bingo-ph{ border-radius: 8px; }    /* подписи нет — фото занимает клетку целиком */
  .bingo-nm{ display:none; }          /* подпись читается по тапу — в строке под полем */
  .bingo-mark{ width:46%; right:6%; top:6%; }
  .bingo-thread{ height:10px; margin-top:-5px; background-size: 28px 10px; }
  .bingo-live{ min-height:56px; }
  .bingo-controls{ gap:10px; }
  .bingo-side{ margin-top: 6px; }
  .bingo-step{ font-size:13.5px; }
  .bingo-rank-num{ min-width:44px; }
}

@media (max-width: 359px){
  .bingo-board{ gap:6px; }
  .bingo-steps{ gap:10px 14px; }
}

/* ── без движения ────────────────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce){
  .bingo-finale{ opacity:1; transform:none; }
  .bingo-thread.is-new{ animation:none; }
  .bingo-cell:hover{ transform:none; }
}

/* ═════════════════════════════════════════════════════════════════════════
   СТРАНИЦА «ОТЗЫВЫ» — reviews.html
   Дописано в конец файла. :root и чужие правила не тронуты, все свои классы
   с префиксом reviews-. Движение только transform/opacity.
   ═══════════════════════════════════════════════════════════════════════ */

/* ─── шапка раздела ─────────────────────────────────────────────────────── */
.reviews-hero{
  display:grid;
  grid-template-columns: minmax(0, 1.35fr) minmax(266px, .82fr);
  gap: clamp(24px, 3.6vw, 46px);
  align-items:center;
}
.reviews-hero h1{ margin: var(--sp-1) 0 var(--sp-2); }
.reviews-hero .lead{ max-width: 48ch; }
.reviews-hero .hand{ display:block; margin-top: var(--sp-2); }
.reviews-actions{ display:flex; flex-wrap:wrap; align-items:center; gap: var(--sp-2); margin-top: var(--sp-2); }

/* ─── лента доказательств: три снимка покупателей на первом экране ──────── */
/* Высота задана самой ленте (aspect-ratio), а не снимкам: фотографии
   приходят из reviews.json уже после отрисовки, и без зарезервированного
   места панель под лентой прыгала бы вниз. */
.reviews-strip{
  display:grid; grid-template-columns: repeat(3, minmax(0,1fr));
  gap: var(--sp-2);
  aspect-ratio: 2.42;
  max-width: 560px;
  margin-top: var(--sp-3);
}
.reviews-strip[hidden]{ display:none; }

.reviews-snap{
  position:relative; display:block; height:100%;
  padding: 6px;                       /* кремовое паспарту вокруг снимка */
  background: var(--card);
  border: var(--hair);
  border-radius: var(--r-md);
  box-shadow: var(--sh-1);
  transform: rotate(-1.4deg);
  transition: transform var(--t) var(--ease), box-shadow var(--t) var(--ease);
}
.reviews-snap:nth-child(2){ transform: rotate(.9deg) translateY(-5px); }
.reviews-snap:nth-child(3){ transform: rotate(-.5deg) translateY(3px); }
.reviews-snap img{
  display:block; width:100%; height:100%;
  object-fit: cover; object-position: center;
  border-radius: 9px; background: var(--card-2);
}
.reviews-snap:focus-visible{ outline: 3px dashed var(--thread); outline-offset: 3px; }
.reviews-snap:active{ transform: scale(.98); }
@media (hover: hover){
  .reviews-snap:hover{
    z-index:1; transform: rotate(0deg) translateY(-5px) scale(1.03);
    box-shadow: var(--sh-2);
  }
}

.reviews-strip-note{
  margin-top: var(--sp-2);
  font-size: var(--fs-small); color: var(--ink-2); line-height:1.5;
  max-width: 560px;
}
.reviews-strip-note[hidden]{ display:none; }
.reviews-strip-note b{ color: var(--clay-ink); font-weight:800; }
.reviews-strip-hint{ display:block; color: var(--ink-soft); }

.reviews-facts{ display:grid; gap: var(--sp-2); }
.reviews-nums{ display:grid; grid-template-columns: 1fr 1fr; gap: var(--sp-2); }
.reviews-num b{
  display:block; font-family: var(--font-display); font-weight:700;
  font-size: clamp(30px, 4.6vw, 44px); line-height:1.04; color: var(--clay-ink);
}
.reviews-num span{
  display:block; margin-top:5px;
  font-size: var(--fs-small); font-weight:700; line-height:1.35;
}
.reviews-rule{ border:0; border-top: var(--seam); }
.reviews-facts .btn{ width:100%; }

/* ─── полоса управления кладкой ─────────────────────────────────────────── */
.reviews-bar{
  display:flex; align-items:center; justify-content:space-between;
  flex-wrap:wrap; gap: 12px 18px;
  margin-bottom: clamp(18px, 2.4vw, 26px);
}
.reviews-chips{ display:flex; flex-wrap:wrap; gap: var(--sp-1); }
.reviews-chip{
  display:inline-flex; align-items:center; justify-content:center;
  min-height: var(--tap); padding: 10px 20px;
  border-radius: var(--r-pill);
  background: var(--card);
  border: 2px solid rgba(190,95,53,.4);   /* как у .btn--soft: одна семья */
  color: var(--clay-ink);
  box-shadow: var(--sh-1);
  font-family: var(--font-text); font-weight:800; font-size:14.5px;
  transition: transform var(--t) var(--ease), background-color var(--t) var(--ease),
              color var(--t) var(--ease), border-color var(--t) var(--ease),
              box-shadow var(--t) var(--ease);
}
.reviews-chip:active{ transform: scale(.97); }
@media (hover: hover){
  .reviews-chip:hover{ transform: translateY(-2px); border-color: var(--thread); background: var(--card-2); box-shadow: var(--sh-2); }
}
.reviews-chip[aria-pressed="true"]{
  background: linear-gradient(180deg, var(--clay), var(--clay-deep));
  border-color: transparent;
  color: var(--cream); box-shadow: var(--sh-btn);
}
.reviews-shown{ font-size: var(--fs-small); font-weight:700; color: var(--ink-soft); }

/* ─── кладка отзывов ────────────────────────────────────────────────────── */
.reviews-wall{
  display:grid; grid-template-columns: repeat(3, minmax(0,1fr));
  gap: var(--gap); align-items:start;
}
.reviews-col{ display:flex; flex-direction:column; gap: var(--gap); min-width:0; }
.reviews-item{ position:relative; min-width:0; }

/* КРЕПЁЖ ЗАПИСКИ — деревянная прищепка, ровно такая же, как на ленте
   снимков в шапке страницы (2026-08-12). Было два разных предмета для
   одного жеста: на ленте прищепка, на стене крафтовая бирка с дырочкой,
   да ещё и на каждой третьей карточке — при кладке в три колонки левый
   столбец оставался вообще без креплений, и это читалось как сбой.
   Теперь прищепка у каждой записки. Живёт на обёртке, а не на карточке:
   у карточки без фото ::before уже занят кавычкой. */
.reviews-item--pin{ padding-top: 18px; }
.reviews-item--pin::before{                /* деревянная планка */
  content:''; position:absolute; z-index:2; top:0; left:34%;
  width:12px; height:26px; margin-left:-6px;
  border-radius:3px;
  background: linear-gradient(180deg, var(--tag), var(--tag-2));
  border: var(--hair);
  box-shadow: 0 1px 2px rgba(120,80,45,.18), inset 0 1px 0 rgba(255,248,232,.75);
  transform: rotate(-2.4deg);
  pointer-events:none;
}
.reviews-item--pin::after{                 /* металлическая пружинка */
  content:''; position:absolute; z-index:3; top:10px; left:34%;
  width:16px; height:2px; margin-left:-8px;
  border-radius:2px; background: rgba(140,100,64,.5);
  transform: rotate(-2.4deg);
  pointer-events:none;
}

.reviews-card{
  position:relative;
  display:flex; flex-direction:column;
  background: var(--card);
  border: var(--hair);
  border-radius: var(--r-lg);
  box-shadow: var(--sh-1);
  /* обрезки нет: клип срезал бы рамку фокуса и бирку-прищепку.
     Фото обрезает себя само — у .reviews-ph свой overflow */
  transform: rotate(var(--rv-tilt, -.6deg));
  transition: transform var(--t) var(--ease), box-shadow var(--t) var(--ease);
}
.reviews-card:focus-within{
  transform: rotate(0deg) translateY(-4px);
  box-shadow: var(--sh-2);
}
@media (hover: hover){
  .reviews-card:hover{
    transform: rotate(0deg) translateY(-4px);
    box-shadow: var(--sh-2);
  }
}

/* фото покупателя — целиком, без обрезки, в кремовом паспарту 8 px:
   разнокалиберные любительские снимки перестают спорить друг с другом */
.reviews-ph{
  --rv-ph-max: 420px;              /* потолок высоты: кладка не разъезжается */
  position:relative; display:block;
  margin: 8px 8px 0;
  aspect-ratio: 4 / 3;
  background: var(--card-2);
  border: var(--hair);
  border-radius: var(--r-md);
  overflow:hidden;
}
.reviews-ph.is-ready{ aspect-ratio: auto; }
.reviews-ph:focus-visible{ outline: 3px dashed var(--thread); outline-offset: 3px; }
.reviews-ph img{
  width:100%; height:100%; object-fit: contain;
  transition: transform var(--t-slow) var(--ease);
}
/* фото показывается целиком: contain не режет и не тянет,
   высокие кадры просто ложатся на бумажную подложку */
.reviews-ph.is-ready img{ height:auto; max-height: var(--rv-ph-max); }
@media (hover: hover){
  .reviews-card:hover .reviews-ph img{ transform: scale(1.025); }
}

.reviews-zoom{
  position:absolute; right:10px; bottom:10px;
  display:inline-flex; align-items:center; gap:6px;
  padding: 7px 13px; border-radius: var(--r-pill);
  background: rgba(255,250,240,.94);
  border: var(--hair);
  color: var(--clay-ink); font-size:12.5px; font-weight:800;
  box-shadow: var(--sh-1);
  opacity:0; transform: translateY(6px);
  transition: opacity var(--t) var(--ease), transform var(--t) var(--ease);
}
.reviews-ph:focus-visible .reviews-zoom{ opacity:1; transform:none; }
@media (hover: hover){
  .reviews-card:hover .reviews-zoom{ opacity:1; transform:none; }
}
@media (hover: none){ .reviews-zoom{ opacity:1; transform:none; } }

.reviews-body{ padding: clamp(14px,2vw,20px) clamp(14px,2vw,20px) 0; }
/* pre-line — чтобы абзацы внутри одного письма не слипались в кашу:
   покупатель иногда пишет двумя сообщениями подряд, и на сайте они
   лежат одной карточкой с пустой строкой между ними */
.reviews-body p{ font-size: 15.5px; line-height:1.62; color: var(--ink-2); white-space: pre-line; }
/* шов: фото и слова — две части одной записки */
.reviews-ph + .reviews-body{
  margin-top: 10px;
  padding-top: clamp(12px, 1.6vw, 16px);
  border-top: var(--seam);
}

/* отзыв без фото — с большой кавычкой, как у .quote */
.reviews-card--noph .reviews-body{ padding-top: clamp(28px,3.4vw,36px); }
.reviews-card--noph::before{
  content:'“'; position:absolute; left:14px; top:2px;
  font-family: var(--font-display); font-size:52px; line-height:1;
  color: rgba(190,95,53,.26); pointer-events:none;
}

/* в подписи остались клубочек и дата: слово «покупатель» повторялось
   24 раза и читалось как шум */
.reviews-meta{
  display:flex; align-items:center; justify-content:flex-start;
  flex-wrap:wrap; gap: 4px 9px; margin-top:auto;
  padding: 13px clamp(14px,2vw,20px) clamp(14px,2vw,18px);
  font-size: var(--fs-small); color: var(--ink-soft);
}
.reviews-who{ display:inline-flex; align-items:center; }
.reviews-who::before{
  content:''; width:13px; height:13px; border-radius:50%; flex:none;
  background: radial-gradient(circle at 35% 30%, var(--ball-lit), var(--ball) 72%);
  box-shadow: inset -2px -2px 0 rgba(122,60,30,.32);
}
.reviews-when{ white-space:nowrap; }

.reviews-more{ display:flex; justify-content:center; margin-top: clamp(22px,3vw,34px); }
.reviews-more[hidden]{ display:none; }
.reviews-tail{ margin-top: 16px; text-align:center; }
.reviews-fail{ text-align:center; }
.reviews-fail .btn{ margin-top: var(--sp-2); }

/* ─── прочитал — поверил — выбирай ──────────────────────────────────────── */
.reviews-finale{
  display:flex; align-items:center; justify-content:space-between;
  flex-wrap:wrap; gap: var(--sp-3) var(--sp-4);
  padding: clamp(20px, 2.8vw, 30px) clamp(20px, 3vw, 34px);
  background: linear-gradient(165deg, var(--tag), var(--tag-2));
  border: var(--hair);
  border-radius: var(--r-xl);
  box-shadow: var(--sh-1), inset 0 1px 0 rgba(255,248,232,.7);
}
.reviews-finale-text{ min-width:0; }
.reviews-finale-num{
  font-family: var(--font-display); font-weight:700; line-height:1.15;
  font-size: clamp(21px, 2.6vw, 30px); color: var(--tag-ink);
  text-wrap: balance;
}
.reviews-finale-num b{ color: var(--clay-ink); font-weight:700; }
.reviews-finale-sub{
  margin-top: var(--sp-1);
  max-width: 46ch;
  font-size: var(--fs-small); line-height:1.55; color: var(--tag-ink);
}
.reviews-finale .btn{ flex:none; }

/* ─── «как заказать» ────────────────────────────────────────────────────── */

/* ─── лупа: увеличенное фото ────────────────────────────────────────────── */
.reviews-lb{
  position:fixed; inset:0; z-index:92;
  display:flex; align-items:center; justify-content:center;
  padding: clamp(12px, 3vw, 34px);
  opacity:0; visibility:hidden; pointer-events:none;
  transition: opacity var(--t) var(--ease), visibility 0s var(--t);
}
.reviews-lb.is-on{ opacity:1; visibility:visible; pointer-events:auto; transition-delay:0s; }
.reviews-lb-veil{ position:absolute; inset:0; background: rgba(74,59,48,.74); }
.reviews-lb-box{
  position:relative; z-index:1;
  display:grid; grid-template-columns: minmax(0,1fr) minmax(264px, 336px);
  gap: clamp(14px,2vw,22px);
  width: min(1060px, 100%); max-height: min(88vh, 900px);
  padding: clamp(14px,2vw,20px);
  background: var(--paper-lit);
  border: 3px solid var(--thread);
  border-radius: var(--r-xl);
  box-shadow: var(--sh-3);
  transform: translateY(16px) scale(.985);
  transition: transform var(--t-slow) var(--ease);
}
.reviews-lb.is-on .reviews-lb-box{ transform:none; }
.reviews-lb-figure{
  display:flex; align-items:center; justify-content:center; min-height:0;
  background: var(--card-2);
  border: var(--hair);
  border-radius: var(--r-lg);
  overflow:hidden;
}
.reviews-lb-figure img{ width:100%; height:100%; max-height: calc(88vh - 62px); object-fit: contain; }
.reviews-lb-side{ display:flex; flex-direction:column; min-height:0; }
.reviews-lb-top{ display:flex; align-items:center; justify-content:space-between; gap:12px; margin-bottom:12px; }
.reviews-lb-text{
  overflow-y:auto; overscroll-behavior:contain; padding-right:6px;
  color: var(--ink-2); font-size:15.5px; line-height:1.62;
  white-space: pre-line;          /* абзацы письма — как их писали */
}
.reviews-lb-meta{ margin-top:12px; }
.reviews-lb-nav{
  display:flex; align-items:center; gap:10px;
  margin-top:auto; padding-top: var(--sp-2);
  border-top: var(--seam);
}
.reviews-lb-count{ margin-inline:auto; font-size: var(--fs-small); font-weight:800; color: var(--ink-soft); }
.reviews-lb-nav .icon-btn{ font-size:22px; }

/* ─── телефон и планшет ─────────────────────────────────────────────────── */
@media (max-width: 1080px){
  .reviews-wall{ grid-template-columns: repeat(2, minmax(0,1fr)); }
}
@media (max-width: 980px){
  .reviews-hero{ grid-template-columns: 1fr; }
  .reviews-hero .lead{ max-width:none; }
}
@media (max-width: 900px){
  .reviews-lb-box{
    grid-template-columns: 1fr;
    grid-template-rows: auto minmax(0,1fr);
    max-height: 92vh;
  }
  .reviews-lb-figure img{ max-height: 44vh; }
}
@media (max-width: 740px){
  .reviews-wall{ grid-template-columns: 1fr; }
  .reviews-ph{ --rv-ph-max: 74vh; }   /* колонка одна — фото можно крупнее */
  /* карточка во всю ширину: тот же наклон, но мягче — иначе высокая записка
     вылезала бы углами за поля */
  .reviews-card{ transform: rotate(calc(var(--rv-tilt, -.6deg) * .55)); }
  .reviews-body p{ font-size:15px; }
  .reviews-strip{ gap: var(--sp-1); aspect-ratio: 2.5; }
  .reviews-snap{ padding:5px; border-radius: var(--r-sm); }
  .reviews-snap img{ border-radius:7px; }
  .reviews-finale{ flex-direction:column; align-items:stretch; }
  .reviews-chip{ flex:1 1 auto; padding: 10px 14px; font-size:14px; }
  .reviews-shown{ width:100%; }
  .reviews-actions .btn:not(.btn--ghost),  .reviews-actions .btn--ghost{ margin-inline:auto; }
  .reviews-num b{ font-size: 34px; }
    .reviews-lb-box{ border-radius: var(--r-lg); padding:14px; }
}
@media (max-width: 359px){
  .reviews-nums{ grid-template-columns: 1fr; }
}

@media (prefers-reduced-motion: reduce){
  .reviews-card,
  .reviews-snap,
  .reviews-snap:nth-child(2),
  .reviews-snap:nth-child(3){ transform:none !important; }
  .reviews-item--pin::before,
  .reviews-item--pin::after{ transform:none; }
  .reviews-zoom{ opacity:1; transform:none; }
  .reviews-lb-box{ transform:none !important; }
}

@media print{
  .reviews-bar, .reviews-more, .reviews-lb, .reviews-zoom{ display:none !important; }
  .reviews-wall{ grid-template-columns: 1fr 1fr; }
  .reviews-card{ transform:none; box-shadow:none; break-inside: avoid; }
  .reviews-finale .btn{ display:none; }
}

/* ═════════════════════════════════════════════════════════════════════════
   СТРАНИЦА «КАТАЛОГ» — catalog.html
   Дописано в конец файла. :root и чужие правила не тронуты, все свои классы
   с префиксом catalog-. Движение только transform/opacity.
   ═══════════════════════════════════════════════════════════════════════ */

/* скрытие фильтром: .card и .catalog-fandom задают display, поэтому [hidden]
   сам по себе их не прячет — гасим явно */
.card[hidden], .catalog-fandom[hidden], .catalog-none[hidden], .catalog-fail[hidden]{
  display:none !important;
}

/* пришли по ссылке с главной или с бинго (catalog.html#i-<id>) — карточка
   на пару секунд подсвечивается, чтобы было видно, куда вас привели.
   Движение только по transform, тень статична. */
.card.is-target{
  outline: 3px dashed var(--thread);
  outline-offset: 4px;
  animation: catalog-found 2.4s var(--ease);
}
@keyframes catalog-found{
  0%   { transform: translateY(0)     scale(1); }
  14%  { transform: translateY(-6px)  scale(1.02); }
  30%  { transform: translateY(0)     scale(1); }
  42%  { transform: translateY(-3px)  scale(1.01); }
  56%, 100% { transform: translateY(0) scale(1); }
}
@media (prefers-reduced-motion: reduce){
  .card.is-target{ animation: none; }
}

/* ─── шапка раздела ─────────────────────────────────────────────────────── */
.catalog-top{ padding-top: var(--sp-3); padding-bottom: var(--sp-3); }
.catalog-lead{ margin-top: var(--sp-2); max-width: 56ch; }
.catalog-top .hand{ margin-top: var(--sp-2); display:block; }

.catalog-hero{
  display:grid; grid-template-columns: minmax(0,1.5fr) minmax(252px,.78fr);
  gap: clamp(20px, 3.4vw, 46px); align-items:center;
}
.catalog-hero .section-head{ margin-bottom: 0; }
.catalog-facts .overline{ display:block; margin-bottom: var(--sp-2); }
.catalog-nums{ list-style:none; display:grid; gap: var(--sp-2); margin-bottom: var(--sp-3); }
.catalog-nums li{ display:flex; align-items:baseline; gap: var(--sp-2); }
.catalog-nums b{
  font-family: var(--font-display); font-weight:700;
  font-size: clamp(23px, 2.8vw, 31px); line-height:1; color: var(--clay-ink);
  white-space:nowrap;
}
.catalog-nums span{ font-size: var(--fs-small); font-weight:700; line-height:1.3; }

/* ─── полка с бирками-фильтрами ─────────────────────────────────────────── */
.catalog-filters{
  position: relative; z-index: 30;
  margin-bottom: clamp(6px, 1.4vw, 14px);
  background: var(--paper-lit);
  border-top: var(--hair);
  border-bottom: var(--seam);
  transition: box-shadow var(--t) var(--ease);
}
.catalog-filters.is-pinned{ box-shadow: var(--sh-3); }
.catalog-filters-in{ display:flex; flex-direction:column; gap: var(--sp-2); padding-block: var(--sp-2); }

.catalog-chips{ display:flex; flex-wrap:wrap; gap: var(--sp-1); }
.catalog-chip{
  display:inline-flex; align-items:center; gap: var(--sp-1);
  min-height: var(--tap); padding: 8px 16px;
  border-radius: var(--r-sm);
  background: linear-gradient(165deg, var(--tag), var(--tag-2));
  border: var(--hair);
  box-shadow: var(--sh-1);
  color: var(--tag-ink);
  font-family: var(--font-text); font-weight:800; font-size: 14.5px; line-height:1.2;
  text-align:left;
  transition: transform var(--t-fast) var(--ease), box-shadow var(--t-fast) var(--ease),
              background-color var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
}
.catalog-chip:active{ transform: scale(.97); }
/* бирка висит на нитке: качается, а не поднимается плитой */
@media (hover: hover){
  .catalog-chip:hover{ transform: rotate(-1deg) translateY(-1px); box-shadow: var(--sh-2); }
}
.catalog-chip.is-on{
  background: linear-gradient(180deg, var(--clay), var(--clay-deep));
  border-color: transparent; color: var(--cream);
  box-shadow: var(--sh-btn);
}
/* двух подписей у бирки больше нет: имя мира одно на весь сайт */
.catalog-chip-n{
  display:inline-block; min-width: 22px; padding: 2px 7px;
  border-radius: var(--r-pill);
  background: rgba(255,248,232,.72); color: var(--tag-ink);
  font-size: 12.5px; font-weight:800; text-align:center; line-height:1.5;
}
.catalog-chip.is-on .catalog-chip-n{ background: rgba(70,30,10,.32); color: var(--cream); }

.catalog-tools{ display:flex; align-items:center; flex-wrap:wrap; gap: var(--sp-2) var(--sp-3); }
.catalog-switch{
  display:inline-flex; align-items:center; gap: var(--sp-1);
  min-height: var(--tap); padding: 8px 18px 8px 13px;
  border-radius: var(--r-pill);
  background: var(--card);
  border: 2px solid rgba(126,150,120,.55);
  color: var(--ink-2);
  box-shadow: var(--sh-1);
  font-family: var(--font-text); font-weight:700; font-size: 14.5px;
  transition: transform var(--t-fast) var(--ease), background-color var(--t) var(--ease),
              color var(--t) var(--ease), border-color var(--t) var(--ease),
              box-shadow var(--t) var(--ease);
}
.catalog-switch b{ color: var(--sage-ink); font-weight:800; }
.catalog-switch:active{ transform: scale(.97); }
@media (hover: hover){
  .catalog-switch:hover{ transform: translateY(-2px); border-color: var(--sage-deep); box-shadow: var(--sh-2); }
}
.catalog-switch-box{
  position:relative; flex:none;
  width: 22px; height: 22px; border-radius: 6px;
  background: var(--cream); border: 2px solid var(--sage);
  transition: background-color var(--t-fast), border-color var(--t-fast);
}
.catalog-switch-box::after{
  content:''; position:absolute; left: 6px; top: 1px;
  width: 5px; height: 11px;
  border: solid var(--sage-deep); border-width: 0 3px 3px 0;
  transform: rotate(45deg) scale(0); transform-origin: 50% 50%;
  transition: transform var(--t-fast) var(--ease);
}
/* включённый фильтр: зелёный сжат до галки в квадратике,
   заливать им кнопку во всю ширину — значит спорить с фотографиями */
.catalog-switch.is-on{
  background: var(--card-2);
  border-color: var(--sage-deep); color: var(--sage-ink);
  box-shadow: var(--sh-1);
}
.catalog-switch.is-on b{ color: var(--sage-ink); }
.catalog-switch.is-on .catalog-chip-n{ background: rgba(91,112,82,.16); color: var(--sage-ink); }
.catalog-switch.is-on .catalog-switch-box{ background: var(--sage-deep); border-color: var(--sage-deep); }
.catalog-switch.is-on .catalog-switch-box::after{ border-color: var(--cream); transform: rotate(45deg) scale(1); }

.catalog-count{ margin-left:auto; font-weight:700; color: var(--ink-soft); }

/* ─── секция одной игры: бирка на нитке ─────────────────────────────────── */
.catalog-body{ padding-top: clamp(10px, 2vw, 20px); }
.catalog-fandom{ position:relative; padding-top: clamp(26px, 4vw, 46px); }
.catalog-fandom::before{           /* стежок-разделитель между мирами */
  content:''; position:absolute; left:0; right:0; top: clamp(8px, 1.6vw, 18px); height: 12px;
  background-image: var(--stitch); background-repeat: repeat-x; background-size: 34px 12px;
  opacity: .3; pointer-events:none;
}
.catalog-fandom:first-child::before{ display:none; }
.catalog-fandom:first-child{ padding-top: clamp(8px, 1.6vw, 18px); }

.catalog-fandom-head{
  position:relative;
  display:flex; align-items:center; justify-content:space-between;
  flex-wrap:wrap; gap: var(--sp-1) var(--sp-3);
  margin: 0 0 var(--sp-3);
}
.catalog-fandom-head::before{      /* нитка от стежка к бирке */
  content:''; position:absolute; left: 22px; top: -22px; width: 2.5px; height: 24px;
  background: var(--thread); border-radius: 2px;
}
.catalog-fandom:first-child .catalog-fandom-head::before{ display:none; }
.catalog-fandom-tag{ padding: 10px 18px 12px 27px; }
.catalog-fandom-name{
  font-family: var(--font-display); font-weight:700;
  font-size: clamp(17px, 2.2vw, 21px); line-height:1.2; color: var(--ink);
}
.catalog-fandom-ru{
  display:block; margin-top: 3px;
  font-size: 12.5px; font-weight:800; letter-spacing:.12em; text-transform:uppercase;
  color: var(--tag-ink);
}
.catalog-fandom-n{ color: var(--sage-ink); white-space:nowrap; }

/* ─── карточка: несколько фото ──────────────────────────────────────────── */
.catalog-multi img{
  position:absolute; inset:0; width:100%; height:100%;
  opacity:0;
  transition: opacity var(--t) var(--ease), transform var(--t-slow) var(--ease);
}
.catalog-multi img.is-on{ opacity:1; }
.catalog-flip{                     /* тапабельно всё фото целиком, а не точка */
  position:absolute; inset:0; z-index:3;
  background:none; border:0; cursor:pointer;
}
/* рамку фокуса снаружи срезало бы фото — рисуем её внутрь, по краю паспарту */
.catalog-flip:focus-visible{
  outline: 3px dashed var(--thread); outline-offset: -10px; border-radius: var(--r-md);
}
.catalog-dots{
  position:absolute; right:9px; bottom:9px; z-index:4;
  display:flex; align-items:center; gap:6px;
  padding: 7px 10px; border-radius: var(--r-pill);
  background: rgba(255,250,240,.94);
  border: var(--hair);
  box-shadow: var(--sh-1);
  pointer-events:none;
}
.catalog-dot{
  width: 8px; height: 8px; border-radius:50%;
  background: rgba(122,101,83,.45);
  transition: transform var(--t-fast) var(--ease), background-color var(--t-fast);
}
.catalog-dot.is-on{ background: var(--clay); transform: scale(1.3); }

/* цена по запросу — не влезает в строку прайса, поэтому в две */
.catalog-price-ask{
  font-size: 14px; font-weight:800; line-height:1.25;
  color: var(--ink-2); white-space: normal;
}

/* ─── пусто / не загрузилось / наверх ───────────────────────────────────── */
.catalog-none, .catalog-fail{ text-align:center; margin: var(--sp-4) 0; }
.catalog-none p, .catalog-fail p{ margin-top: var(--sp-1); }
.catalog-none-btns{ display:flex; flex-wrap:wrap; justify-content:center; align-items:center; gap: var(--sp-2); margin-top: var(--sp-3); }
.catalog-up-line{ text-align:center; margin-top: var(--sp-4); }

/* ─── гача слаймиков: одна рамка ────────────────────────────────────────── */
.catalog-gacha{
  border: var(--seam);
  border-radius: var(--r-xl);
  background: linear-gradient(170deg, var(--card), var(--card-2));
  padding: clamp(18px, 3vw, 34px);
}
.catalog-gacha-top{
  display:grid; grid-template-columns: minmax(0,1fr) minmax(0,1.1fr);
  gap: clamp(16px, 3vw, 34px); align-items:center;
}
.catalog-gacha-ph{ margin:0; }
.catalog-gacha-ph img{
  width:100%; border-radius: var(--r-lg);
  border: 6px solid var(--card-2);          /* паспарту, как в карточках */
  background: var(--card-2);
  box-shadow: var(--sh-1);
}
.catalog-gacha-ph figcaption{ margin-top: var(--sp-1); text-align:center; color: var(--ink-soft); }
.catalog-gacha-intro .overline{ display:block; margin-bottom: var(--sp-1); }
.catalog-gacha-intro .lead{ margin-top: var(--sp-2); }
.catalog-gacha-intro .hand{ display:block; margin-top: var(--sp-1); }
.catalog-gacha-note{
  margin-top: var(--sp-3); padding: 12px 16px;
  border-radius: var(--r-md);
  background: linear-gradient(165deg, var(--tag), var(--tag-2));
  border: var(--hair);
  color: var(--tag-ink); font-size: 14.5px; line-height:1.5;
}
.catalog-sub{ margin: var(--sp-4) 0 var(--sp-2); font-size: var(--fs-h3); }

.catalog-kinds{ display:flex; flex-wrap:wrap; gap: var(--sp-1); list-style:none; }
.catalog-kind{
  padding: 7px 14px; border-radius: var(--r-pill);
  background: var(--card); border: var(--hair);
  box-shadow: var(--sh-1);
  color: var(--ink-2); font-size: 14px; font-weight:700;
}
.catalog-kind.is-secret{
  background: var(--cream-2); border: 1px dashed rgba(190,95,53,.5);
  color: var(--clay-ink);
}

.catalog-prices{ display:flex; flex-direction:column; gap: var(--sp-2); }
.catalog-price-row{
  display:grid; grid-template-columns: minmax(0,1fr) auto auto;
  align-items:center; gap: var(--sp-1) var(--sp-3);
  padding: 13px 16px; border-radius: var(--r-md);
  background: var(--paper-lit); border: var(--hair);
  transition: transform var(--t-fast) var(--ease), box-shadow var(--t-fast) var(--ease);
}
@media (hover: hover){
  .catalog-price-row:hover{ transform: translateY(-2px); box-shadow: var(--sh-1); }
}
.catalog-price-txt b{
  display:block; font-family: var(--font-display); font-weight:700;
  font-size: 16.5px; color: var(--ink); line-height:1.25;
}
.catalog-price-txt span{ display:block; margin-top: 2px; }
.catalog-price-num{ display:flex; flex-direction:column; align-items:flex-end; line-height:1.2; }
.catalog-price-now{ font-size: 19px; font-weight:800; color: var(--clay-ink); white-space:nowrap; }
.catalog-price-old{ font-size: 13px; color: var(--ink-soft); }
/* выгода — бумажный чип с зелёной точкой, а не зелёная плашка */
.catalog-save{
  display:inline-flex; align-items:center; gap:7px;
  margin-left: var(--sp-1); padding: 4px 11px 4px 9px;
  border-radius: var(--r-pill);
  background: rgba(255,250,240,.94); border: var(--hair);
  color: var(--sage-ink);
  font-family: var(--font-text); font-size: 13px; font-weight:800;
  vertical-align: middle;
}
.catalog-save::before{
  content:''; flex:none; width:7px; height:7px; border-radius:50%;
  background: var(--sage-deep);
}

.catalog-sets{ display:grid; grid-template-columns: repeat(auto-fit, minmax(196px,1fr)); gap: var(--gap); }
.catalog-set{
  display:flex; flex-direction:column; gap: var(--sp-1); text-align:center;
  padding: 18px 15px; border-radius: var(--r-lg);
  background: var(--card); border: var(--hair);
  box-shadow: var(--sh-1);
  transition: transform var(--t) var(--ease), box-shadow var(--t) var(--ease);
}
@media (hover: hover){
  .catalog-set:hover{ transform: translateY(-4px); box-shadow: var(--sh-2); }
}
.catalog-set-icon{
  font-size: 30px; line-height:1; min-height: 32px;
  display:flex; align-items:center; justify-content:center;
  font-family: 'Apple Color Emoji','Segoe UI Emoji','Noto Color Emoji', var(--font-text);
}
.catalog-set-ball{ width: 30px; height: 30px; }
.catalog-set-name{ font-family: var(--font-display); font-weight:700; font-size: 17px; color: var(--ink); }
.catalog-set-kinds{ flex:1; font-size: 13.5px; color: var(--ink-soft); line-height:1.5; }
.catalog-gacha-foot{ margin-top: var(--sp-3); }

/* ─── условия заказа ────────────────────────────────────────────────────── */
.catalog-terms{ grid-template-columns: repeat(2, minmax(0,1fr)); }
.catalog-term{ display:flex; flex-direction:column; gap: 6px; }
.catalog-term-icon{ font-size: 26px; line-height:1; }
.catalog-term h3{ font-size: 17.5px; }
.catalog-terms-foot{ margin-top: var(--sp-3); text-align:center; color: var(--ink-2); }
.catalog-terms-foot a{
  display:inline-flex; align-items:center; min-height: var(--tap);
  padding-inline: 3px; font-weight:800;
}
.catalog-terms-btns{ display:flex; flex-wrap:wrap; justify-content:center; align-items:center; gap: var(--sp-2); margin-top: var(--sp-3); }

/* ─── широкий экран: полка липнет под шапкой ────────────────────────────── */
@media (min-width: 741px){
  .catalog-filters{ position: sticky; }
}

/* ─── от 981px: бирка мира уходит в левую колонку, как ярлык в картотеке.
       Так секция из одной работы не занимает пустую строку во всю ширину ── */
@media (min-width: 981px){
  .catalog-fandom{
    display:grid; align-items:start;
    grid-template-columns: minmax(176px, 218px) minmax(0, 1fr);
    column-gap: clamp(18px, 2.4vw, 34px);
  }
  .catalog-fandom-head{
    flex-direction: column; align-items: flex-start; gap: 10px;
    margin-bottom: 0; padding-top: 2px;
  }
  .catalog-fandom-tag{ max-width: 100%; }
  .catalog-fandom-n{ padding-left: 4px; }
}

/* ─── телефон ───────────────────────────────────────────────────────────── */
@media (max-width: 740px){
  /* шапка раздела: цифры в строку, кнопка «в наличии» остаётся */
  .catalog-top{ padding-top: 10px; padding-bottom: 18px; }
  .catalog-lead{ margin-top: 12px; }
  .catalog-hero{ grid-template-columns: 1fr; gap: 16px; }
  .catalog-facts{ padding: 14px 16px 16px; }
  .catalog-facts .overline{ margin-bottom: 10px; }
  .catalog-nums{ grid-template-columns: repeat(3, 1fr); gap: 8px; margin-bottom: 13px; }
  .catalog-nums li{ flex-direction: column; align-items:flex-start; gap: 1px; }
  .catalog-nums b{ font-size: 21px; }
  .catalog-nums span{ font-size: 13px; }

  /* бирки-фильтры едут вбок одной лентой — иначе занимают пол-экрана */
  .catalog-filters{ margin-inline: 0; }
  .catalog-filters-in{ gap: 10px; padding-block: 11px; }
  .catalog-chips{
    flex-wrap: nowrap; overflow-x: auto; overscroll-behavior-x: contain;
    scroll-snap-type: x proximity; scrollbar-width: none;
    gap: 8px; padding-block: 2px;
    margin-inline: calc(var(--pad-page) * -1); padding-inline: var(--pad-page);
    -webkit-overflow-scrolling: touch;
  }
  .catalog-chips::-webkit-scrollbar{ display:none; }
  .catalog-chip{ flex: none; scroll-snap-align: start; padding: 8px 13px; font-size: 13.5px; gap: 6px; }
  .catalog-chip:hover{ transform:none; }
  .catalog-chip-n{ min-width: 20px; padding: 1px 6px; font-size: 12px; }
  .catalog-tools{ flex-direction: column; align-items: stretch; gap: 8px; }
  .catalog-switch{ justify-content:center; }
  .catalog-count{ margin-left: 0; text-align:center; }

  .catalog-fandom-head{ gap: 8px 12px; }
  .catalog-fandom-head::before{ left: 20px; top: -20px; height: 22px; }
  .catalog-fandom-tag{ padding: 9px 15px 11px 25px; }
  .catalog-dots{ right: 7px; bottom: 7px; padding: 6px 9px; }

  .catalog-gacha{ padding: 16px 14px 20px; border-radius: var(--r-lg); }
  .catalog-gacha-top{ grid-template-columns: 1fr; gap: 16px; }
  .catalog-gacha-intro .lead{ margin-top: 10px; }

  .catalog-price-row{ grid-template-columns: minmax(0,1fr) auto; padding: 13px 14px; }
  .catalog-price-row .btn{ grid-column: 1 / -1; width: 100%; }
  .catalog-price-txt b{ font-size: 15.5px; }

  .catalog-sets{ grid-template-columns: 1fr 1fr; gap: var(--sp-1); }
  .catalog-set{ padding: 15px 11px; gap: 6px; }
  .catalog-set-icon{ font-size: 26px; }
  .catalog-set-name{ font-size: 15.5px; }
  .catalog-set-kinds{ font-size: 13.5px; }
  /* длинная подпись кнопки распирала колонку и выносила сет за край экрана */
  .catalog-set .btn{ font-size: 13px; padding: 10px 8px; white-space: normal; }

  .catalog-none-btns .btn, .catalog-terms-btns .btn{ width: 100%; }
  .catalog-terms{ grid-template-columns: 1fr; }
}

@media (max-width: 420px){
  .catalog-sets{ grid-template-columns: 1fr; }
}
@media (max-width: 359px){
  .catalog-chip{ font-size: 13px; padding: 8px 11px; }
}

@media (prefers-reduced-motion: reduce){
  .catalog-multi img{ transition: none; }
}

@media print{
  .catalog-filters, .catalog-flip, .catalog-dots,
  .catalog-up-line, .catalog-terms-btns, .catalog-none-btns{ display:none !important; }
  .catalog-gacha{ break-inside: avoid; }
}

/* ═════════════════════════════════════════════════════════════════════════
   КАТАЛОГ — доводка: сводка, складная полка, быстрый просмотр, итог корзины
   Дописано в конец. :root и чужие правила не тронуты, движение — только
   transform и opacity.
   ═══════════════════════════════════════════════════════════════════════ */

/* ─── сводка «сейчас на столе»: три равные колонки ───────────────────────
   Числа стоят на одной базовой линии, подписи одной длины и одинаковой
   высоты — ряд перестал быть рваным, кнопка под ними не пляшет. */
@media (min-width: 981px){
  /* панель со сводкой чуть шире: в трёх колонках должно помещаться «640 ₽» */
  .catalog-hero{ grid-template-columns: minmax(0,1.4fr) minmax(292px,.86fr); }
}
@media (min-width: 741px) and (max-width: 980px){
  /* на планшете колонка со сводкой становится такой узкой, что подписи рвутся
     на три строки — там панель ложится под заголовок во всю ширину */
  .catalog-hero{ grid-template-columns: 1fr; }
  .catalog-facts{ display: grid; grid-template-columns: 1fr auto; align-items: center; gap: 0 var(--sp-3); }
  .catalog-facts .overline{ grid-column: 1 / -1; }
  .catalog-nums{ margin-bottom: 0; }
  .catalog-facts-btn{ margin-top: 0; }
}
.catalog-nums{
  grid-template-columns: repeat(3, minmax(0,1fr));
  gap: var(--sp-2) 0; align-items: start;
}
.catalog-nums li{
  flex-direction: column; align-items: flex-start; gap: 2px;
  padding-inline: var(--sp-2);
}
.catalog-nums li:first-child{ padding-left: 0; }
.catalog-nums li + li{ border-left: var(--seam); }
.catalog-nums b{ font-size: clamp(22px, 2.1vw, 27px); }
.catalog-nums span{ min-height: 2.6em; font-size: 13.5px; }

.catalog-facts-btn{
  margin-top: var(--sp-1);
  font-size: 14px; padding: 10px 16px 10px 14px;
  text-align: left;
}
.catalog-facts-btn::before{ width: 8px; height: 8px; }

/* ─── лупа на фотографии: тап открывает быстрый просмотр ──────────────── */
.catalog-zoom{
  position: absolute; inset: 0; z-index: 3;
  display: flex; align-items: flex-end; justify-content: flex-end;
  padding: 9px;
  background: none; border: 0; cursor: zoom-in;
}
/* рамку фокуса снаружи срезало бы фото — рисуем её внутрь, по краю паспарту */
.catalog-zoom:focus-visible{
  outline: 3px dashed var(--thread); outline-offset: -10px;
  border-radius: var(--r-lg);
}
.catalog-zoom-chip{
  display: inline-flex; align-items: center; gap: 6px;
  min-height: 28px; padding: 5px 10px;
  border-radius: var(--r-pill);
  background: rgba(255,250,240,.94);
  border: var(--hair);
  box-shadow: var(--sh-1);
  color: var(--ink-2);
  font-size: 12.5px; font-weight: 800; line-height: 1;
  transition: transform var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
}
.catalog-zoom:active .catalog-zoom-chip{ transform: scale(.94); }
@media (hover: hover){
  .catalog-zoom:hover .catalog-zoom-chip{ color: var(--clay-ink); transform: scale(1.06); }
}

/* ─── работы выкладываются на стол после отбора ──────────────────────────
   Кадры и тайминги — в разделе 14.7: там собрано всё движение сайта. */
@media (prefers-reduced-motion: reduce){
  .card.catalog-pop{ animation: none !important; }
}

/* ─── общий раздел «гости из разных миров» ───────────────────────────── */
/* в нём под именем работы стоит мир, а не тёплая деталька: иначе непонятно,
   откуда приехала игрушка */
.catalog-card-world{
  display: flex; align-items: center; gap: 6px;
  color: var(--tag-ink);
}
.catalog-card-world::before{
  content:''; flex: none; width: 6px; height: 6px; border-radius: 50%;
  background: var(--thread);
}

/* ─── подсказка «лента бирок листается вбок» ──────────────────────────────
   Растворения края мало: обрезанное на полуслове слово читается как баг
   вёрстки. Стрелка у правого края говорит, что там есть продолжение, и
   гаснет, когда ленту домотали. Не кнопка — знак: pointer-events выключены,
   чтобы палец попадал по бирке под ней. */
.catalog-chips-hint{ display: none; }

@media (max-width: 740px){
  .catalog-filters-in{ position: relative; }
  .catalog-chips-hint{
    position: absolute; top: 10px; right: 0; z-index: 3;
    display: flex; align-items: center; justify-content: flex-end;
    width: 30px; height: 36px; padding-right: 2px;
    pointer-events: none; color: var(--clay-ink);
    opacity: 1; transition: opacity var(--t) var(--ease);
    animation: ct-chips-nudge 2.6s var(--ease) .9s 3 both;
  }
  .catalog-filters.is-chips-end .catalog-chips-hint{ opacity: 0; animation: none; }
}
@keyframes ct-chips-nudge{
  0%, 62%, 100% { transform: translateX(0); }
  78%           { transform: translateX(4px); }
}
@media (prefers-reduced-motion: reduce){
  .catalog-chips-hint{ animation: none !important; }
}

/* ─── прилипшая полка складывается в одну строку 60 px ────────────────── */
.catalog-filters-gap{ height: 0; }     /* добирает высоту, потерянную полкой */

@media (min-width: 741px){
  .catalog-filters-in{ transition: padding var(--t-fast) var(--ease); }

  .catalog-filters.is-pinned .catalog-filters-in{
    flex-direction: row; align-items: center;
    gap: var(--sp-3); padding-block: var(--sp-1);
  }
  /* бирки уезжают вбок и мягко тают у правого края — маской, не тенью */
  .catalog-filters.is-pinned .catalog-chips{
    flex: 1 1 auto; min-width: 0;
    flex-wrap: nowrap; overflow-x: auto; overscroll-behavior-x: contain;
    scroll-snap-type: x proximity; scrollbar-width: none;
    -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 52px), transparent);
            mask-image: linear-gradient(90deg, #000 calc(100% - 52px), transparent);
  }
  .catalog-filters.is-pinned .catalog-chips::-webkit-scrollbar{ display: none; }
  .catalog-filters.is-pinned .catalog-chip{
    flex: none; scroll-snap-align: start;
    padding: 8px 13px; font-size: 14px;
  }
  .catalog-filters.is-pinned .catalog-tools{ flex: none; margin-left: 0; }
  /* счётчик убран с глаз, но остаётся для голосового чтения (aria-live) */
  .catalog-filters.is-pinned .catalog-count{
    position: absolute !important; width: 1px; height: 1px;
    overflow: hidden; clip-path: inset(50%); white-space: nowrap;
  }
}

/* ─── быстрый просмотр работы ─────────────────────────────────────────── */
.catalog-qv{
  position: fixed; inset: 0; z-index: var(--z-drawer);
  display: flex; align-items: center; justify-content: center;
  padding: clamp(12px, 3vw, 32px);
  opacity: 0; visibility: hidden; pointer-events: none;
  transition: opacity var(--t) var(--ease), visibility 0s var(--t);
}
.catalog-qv.is-on{ opacity: 1; visibility: visible; pointer-events: auto; transition-delay: 0s; }
.catalog-qv-veil{ position: absolute; inset: 0; background: rgba(74,59,48,.74); }

.catalog-qv-box{
  position: relative;
  display: grid; grid-template-columns: minmax(0,1.08fr) minmax(0,.92fr);
  gap: clamp(14px, 2vw, 24px);
  width: min(980px, 100%); max-height: min(88vh, 760px);
  padding: clamp(14px, 2vw, 20px);
  background: var(--card);
  border: var(--hair);
  border-radius: var(--r-xl);
  box-shadow: var(--sh-3);
  transform: translateY(14px) scale(.985);
  transition: transform var(--t-slow) var(--ease);
}
.catalog-qv.is-on .catalog-qv-box{ transform: none; }

.catalog-qv-figure{
  position: relative; margin: 0; min-height: 0;
  display: flex; align-items: center; justify-content: center;
  background: var(--card-2);
  border: 6px solid var(--card-2);      /* паспарту, как в карточках */
  border-radius: var(--r-lg);
}
.catalog-qv-figure img{
  width: 100%; height: 100%;
  max-height: calc(88vh - 80px);
  object-fit: contain;
  border-radius: var(--r-md);
}
.catalog-qv-nav{
  position: absolute; left: 50%; bottom: 10px;
  transform: translateX(-50%);
  display: flex; align-items: center; gap: var(--sp-1);
  padding: 5px 8px; border-radius: var(--r-pill);
  background: rgba(255,250,240,.94);
  border: var(--hair);
  box-shadow: var(--sh-1);
}
.catalog-qv-nav[hidden]{ display: none; }   /* одно фото — листать нечего */
.catalog-qv-count{ font-size: var(--fs-tiny); font-weight: 800; color: var(--ink-soft); }

.catalog-qv-side{ display: flex; flex-direction: column; min-height: 0; }
.catalog-qv-top{
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: var(--sp-2); margin-bottom: var(--sp-1);
}
.catalog-qv-name{ font-size: var(--fs-h3); margin-bottom: var(--sp-2); }
.catalog-qv-badges{
  display: flex; flex-wrap: wrap; gap: var(--sp-1);
  margin-bottom: var(--sp-2);
}
.catalog-qv-size{ margin-bottom: var(--sp-2); }
.catalog-qv-details{
  list-style: none; margin: 0 0 var(--sp-2);
  overflow-y: auto; min-height: 0;
  display: flex; flex-direction: column; gap: 6px;
  padding-top: var(--sp-2);
  border-top: var(--seam);
}
.catalog-qv-details li{
  display: flex; align-items: baseline; gap: var(--sp-1);
  font-size: 14.5px; color: var(--ink-2);
}
.catalog-qv-details li::before{
  content:''; flex: none; width: 7px; height: 7px; border-radius: 50%;
  background: var(--tag-2); box-shadow: inset 0 0 0 1px rgba(140,100,64,.3);
}
/* ссылка «все работы этого мира» — из просмотра можно уйти к соседям,
   не возвращаясь к полке фильтров */
.catalog-qv-more{ align-self: flex-start; margin: var(--sp-1) 0 var(--sp-2); }
.catalog-qv-more[hidden]{ display: none; }   /* .btn задаёт display — гасим явно */
.catalog-qv-pay{ margin-top: auto; padding-top: var(--sp-2); line-height: 1.45; }
.catalog-qv-foot{
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-2); padding-top: var(--sp-2);
  border-top: var(--seam);
}
/* строку про оплату может не прислать catalog.json — тогда вниз колонки
   прижимается сама строка с ценой */
.catalog-qv-side:has(.catalog-qv-pay[hidden]) .catalog-qv-foot{ margin-top: auto; }
.catalog-qv-act .btn{ white-space: nowrap; }

/* ─── итог корзины под рукой: узкая полоса внизу телефона ─────────────── */
.catalog-cartbar{ display: none; }

@media (max-width: 740px){
  .catalog-cartbar{
    position: fixed; left: 0; right: 0; bottom: 0; z-index: var(--z-veil);
    display: flex; align-items: center; gap: var(--sp-2);
    min-height: 56px;
    padding: 8px 14px calc(8px + env(safe-area-inset-bottom, 0px));
    background: var(--card);
    border-top: 2px solid var(--thread);
    box-shadow: 0 -8px 22px rgba(90,58,30,.16);
    transform: translateY(120%);
    visibility: hidden;
    transition: transform var(--t-slow) var(--ease), visibility 0s var(--t-slow);
  }
  body.catalog-has-bar .catalog-cartbar{
    transform: none; visibility: visible; transition-delay: 0s;
  }
  .catalog-cartbar-tx{
    flex: 1; min-width: 0;
    font-size: 14.5px; font-weight: 800; color: var(--ink);
    line-height: 1.25;
  }
  .catalog-cartbar .btn{ flex: none; }

  /* полоса не должна накрывать подвал и всплывающую плашку */
  body.catalog-has-bar .site-foot{ padding-bottom: calc(74px + env(safe-area-inset-bottom, 0px)); }
  body.catalog-has-bar .toast{ bottom: calc(86px + env(safe-area-inset-bottom, 0px)); }
}
.catalog-cartbar[hidden]{ display: none; }

/* ─── быстрый просмотр на телефоне: бумажная шторка снизу ─────────────── */
@media (max-width: 740px){
  .catalog-qv{ align-items: flex-end; padding: 0; }
  .catalog-qv-box{
    grid-template-columns: 1fr;
    width: 100%; max-height: 92vh;
    padding: 12px 14px calc(12px + env(safe-area-inset-bottom, 0px));
    border-radius: var(--r-xl) var(--r-xl) 0 0;
    border-bottom: 0;
    overflow-y: auto;
    transform: translateY(24px);
  }
  .catalog-qv-figure img{ max-height: 42vh; }
  /* строка с крестиком липнет к верху шторки: закрыть можно с любого места,
     не отматывая обратно к фотографии */
  .catalog-qv-top{
    position: sticky; top: 0; z-index: 4;
    align-items: center;
    padding-block: 8px; margin-bottom: var(--sp-1);
    background: var(--card);
  }
  .catalog-qv-name{ font-size: 20px; }
  .catalog-qv-foot{
    position: sticky; bottom: 0;
    background: var(--card);
    flex-wrap: wrap;
  }
  .catalog-qv-act{ flex: 1; }
  .catalog-qv-act .btn{ width: 100%; }
  .catalog-qv-details{ overflow: visible; }
}

@media (max-width: 740px){
  /* на узком экране колонки сводки уже — поля между ними меньше */
  .catalog-nums li{ padding-inline: var(--sp-1); }
  .catalog-nums b{ font-size: 21px; }
  .catalog-nums span{ font-size: 13px; }
}

@media (max-width: 359px){
  .catalog-nums li{ padding-inline: 5px; }
  .catalog-nums span{ font-size: 13px; }
  .catalog-zoom-chip span{ display: none; }
}

@media (prefers-reduced-motion: reduce){
  .catalog-qv-box{ transform: none !important; }
  .catalog-cartbar{ transition: none; }
}

@media print{
  .catalog-qv, .catalog-cartbar, .catalog-zoom{ display: none !important; }
}

/* ═════════════════════════════════════════════════════════════════════════
   БИНГО — доводка страницы bingo.html. Дописано в конец файла, :root и чужие
   правила не тронуты. Что делает этот блок:
     1) поднимает игровое поле в первый экран (шапка сжата, подсказки — вниз);
     2) собирает 25 отдельных карточек в ОДНО бумажное полотно со швами;
     3) вешает звание бумажной биркой на нитке над полотном;
     4) добавляет подборку «пять в ряд» и кнопку «поделиться результатом».
   Движение — только transform/opacity, бесконечных анимаций не добавлено.
   ═══════════════════════════════════════════════════════════════════════ */

/* ─── 1. шапка страницы: коротко, чтобы поле начиналось сразу ──────────── */
.bingo-top{ padding-top: var(--sp-2); padding-bottom: 0; }
.bingo-top .section-head{ margin-bottom: var(--sp-2); }
.bingo-top .section-title::after{ margin-top: 7px; }
.bingo-lead{ margin-top: 0; max-width: 70ch; }   /* правило умещается в строку */
/* рукописная строка стоит под вводной, как на остальных страницах.
   Снизу зазор больше, чем сверху: у Caveat длинные хвосты букв, и без
   него строка почти касалась дорожки прогресса */
.bingo-hand{ display: block; margin: 6px 0 8px; }

.bingo-section{ padding-top: var(--sp-2); padding-bottom: var(--sec-gap-tight); }
/* шов между правилом и полем не нужен — это одна мысль, а не две секции */
.section--tight.bingo-section::before{ display:none; }

/* ─── 2. нить прогресса: узнано столько-то, на конце клубок ────────────── */
.bingo-progress{ display:flex; align-items:center; gap: var(--sp-2); }
.bingo-count{
  flex:none; font-size:13.5px; font-weight:700; color: var(--ink-2);
  white-space:nowrap;
}
.bingo-count b{ font-size:19px; font-weight:800; color: var(--clay-ink); }
.bingo-bar{ flex:1 1 auto; height:10px; min-width:56px; }
.bingo-clew{
  flex:none; width:18px; height:18px; border-radius:50%;
  background: radial-gradient(circle at 35% 30%, var(--ball-lit), var(--ball) 72%);
  box-shadow: inset -2px -3px 0 rgba(122,60,30,.32), var(--sh-1);
  transition: transform var(--t) var(--ease);
}
.bingo-clew.is-full{ transform: scale(1.3); }

/* ─── 3. полотно: лист бумаги, на котором лежит всё поле ───────────────── */
.bingo-stage{ position:relative; margin-top: var(--sp-2); padding-top: 44px; }

.bingo-mat{
  position:relative;
  padding: clamp(7px, 1vw, 12px);
  background-color: var(--card);
  background-image: var(--grain);
  background-size: 280px 148px;
  border: var(--hair);
  border-radius: var(--r-lg);
  box-shadow: var(--sh-1);
  transform: rotate(-.4deg);      /* лист лежит на столе, а не приклеен */
}

/* звание — бумажная бирка на нитке над правым верхним углом полотна */
.bingo-rank-tag{
  position:absolute; top:4px; right:10px; z-index:4;
  display:block; max-width: min(58%, 300px);
  padding: 8px 14px 10px 26px;
  transform-origin: 13px 8px;
}
.bingo-rank-tag::after{
  content:''; position:absolute; left:12px; bottom: calc(100% - 8px);
  width:2px; height:26px; border-radius:1px;
  background: linear-gradient(180deg, rgba(190,95,53,0), rgba(190,95,53,.6));
}
.bingo-rank-cap{
  /* прозрачности тут нет намеренно: на бумаге бирки .75 давало 3,5:1 */
  display:block; font-size:12px; font-weight:800; letter-spacing:.11em;
  text-transform:uppercase; color: var(--tag-ink);
}
.bingo-rank-nm{
  display:block; margin-top:1px;
  font-family: var(--font-display); font-weight:700;
  font-size: clamp(13px, 1.15vw, 15.5px); line-height:1.2; color: var(--tag-ink);
}
/* сменилось звание — бирка качнулась. Один раз, только transform */
.bingo-rank-tag.is-turn{ animation: bingo-tag-turn .75s var(--ease) 1 both; }
@keyframes bingo-tag-turn{
  0%  { transform: rotate(-2.6deg); }
  22% { transform: rotate(-8deg); }
  52% { transform: rotate(1.6deg); }
  78% { transform: rotate(-3.8deg); }
  100%{ transform: rotate(-2.6deg); }
}

/* ─── 4. клетки: без собственных теней, разделены стежком ──────────────── */
.bingo-board{ --bgap: clamp(6px, .9vw, 9px); gap: var(--bgap); }

.bingo-cell{
  --cell-lift: 0px; --cell-rot: 0deg; --cell-sq: 1;
  padding:3px;
  background: transparent;
  border: 2px dashed transparent;
  border-radius: 12px;
  box-shadow: none;
  transform: translateY(var(--cell-lift)) rotate(var(--cell-rot)) scale(var(--cell-sq));
}
.bingo-cell:focus-visible{ outline: 3px dashed var(--thread); outline-offset: 1px; }
.bingo-cell:active{ --cell-sq: .94; }

/* швы полотна: линия идёт ровно посередине зазора. Прозрачность чуть ниже
   рамки отметки — иначе шов и «отмечено» читаются одинаково */
.bingo-cell::before, .bingo-cell::after{ content:''; position:absolute; pointer-events:none; opacity:.7; }
.bingo-cell::after{
  top:10%; bottom:10%; right: calc(var(--bgap) / -2 - 1px);
  border-right: var(--seam);
}
.bingo-cell::before{
  left:10%; right:10%; bottom: calc(var(--bgap) / -2 - 1px);
  border-bottom: var(--seam);
}
.bingo-cell:nth-child(5n)::after,
.bingo-cell:nth-child(n+21)::before{ display:none; }

.bingo-ph{ border-radius: 10px; background: var(--card-2); }
.bingo-ph::after{ background: rgba(190,95,53,.32); }   /* вуаль отмеченной */

/* сердечко: на телефоне крупное (клетка мелкая — иначе не видно отметку),
   на большом экране скромнее, чтобы не закрывать игрушку собой */
.bingo-mark{ width:44%; max-width:72px; right:4%; top:4%; }

.bingo-nm{
  padding: 7px 4px 3px; text-align:center;
  font-size:12.5px; color: var(--ink-2);
  min-height: calc(2 * 1.22em + 10px);
}

/* отмечено: клетка чуть повернулась, как наклейка */
.bingo-cell.is-on{
  --cell-rot: -1deg;
  border-color: rgba(190,95,53,.5);
  background: rgba(190,95,53,.05);
}
.bingo-cell.is-on .bingo-nm{ color: var(--clay-ink); font-weight:700; }

/* клетка внутри собранной линии */
.bingo-cell.is-line{
  border-color: rgba(91,112,82,.55);
  background: rgba(91,112,82,.09);
  box-shadow:none;
}

@media (hover: hover){
  /* наведение НЕ красит рамку терракотой: терракотовая рамка означает
     «отмечено», и путать эти два состояния нельзя */
  .bingo-cell:hover{
    --cell-lift: -2px;
    border-color: rgba(140,100,64,.3);
    background: rgba(140,100,64,.05);
    box-shadow: none;
  }
  .bingo-cell.is-on:hover{ border-color: var(--thread); background: rgba(190,95,53,.09); }
  .bingo-cell.is-line:hover{ border-color: var(--sage-deep); background: rgba(91,112,82,.14); }
}

/* нитка через собранную линию — на 2 px толще, её видно на фотографиях */
.bingo-thread{ height:14px; margin-top:-7px; background-size: 40px 14px; }

/* ─── 5. под полем: звание словами, звания списком, кнопки ─────────────── */
.bingo-under{ display:grid; gap: var(--sp-3); align-content:start; }
.bingo-notes{ display:grid; gap:4px; }
.bingo-rank-note{ font-size: var(--fs-small); color: var(--ink-2); }
.bingo-lines-note{ font-size: var(--fs-small); font-weight:700; color: var(--sage-ink); }

.bingo-ranks{ border-top: var(--seam); padding-top: 2px; }
.bingo-ranks-sum{
  display:inline-flex; align-items:center; gap:8px;
  min-height: var(--tap); padding-right:4px;
  list-style:none; cursor:pointer;
  font-weight:800; font-size:15px; color: var(--clay-ink);
  text-decoration: underline; text-decoration-style: dashed;
  text-decoration-color: var(--thread);
  text-underline-offset:6px; text-decoration-thickness:2px;
}
.bingo-ranks-sum::-webkit-details-marker{ display:none; }
.bingo-ranks-sum::after{        /* галочка нарисована рамками, а не глифом */
  content:''; width:8px; height:8px; margin-bottom:3px;
  border-right:2px solid var(--thread); border-bottom:2px solid var(--thread);
  transform: rotate(45deg);
  transition: transform var(--t) var(--ease);
}
.bingo-ranks[open] .bingo-ranks-sum::after{ transform: rotate(225deg); margin-bottom:-3px; }
.bingo-ranks-sum:focus-visible{ outline: 3px dashed var(--thread); outline-offset: 3px; border-radius: var(--r-xs); }
.bingo-ranks .bingo-rank-list{
  margin-top: var(--sp-1); padding: var(--sp-2);
  grid-template-columns: repeat(auto-fit, minmax(228px, 1fr));
  gap: 2px 18px;
  background: var(--card); border: var(--hair); border-radius: var(--r-md);
}
.bingo-rank-txt{ font-size:13.5px; color: var(--tag-ink); }

.bingo-controls{ margin-top:0; align-items:center; }
.bingo-steps{ margin-top:0; }
.bingo-save-note{ margin-top:0; }
/* кнопка .btn задаёт display:inline-flex и этим перебивает [hidden] —
   поэтому спрятанную кнопку «поделиться» гасим явно */
.bingo-controls .btn[hidden]{ display:none; }

/* ─── 6. собранная линия превращается в подборку с настоящими ценами ───── */
.bingo-lineup{
  display:grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: var(--sp-2); margin-top: var(--sp-3);
}
.bingo-lot{
  display:flex; flex-direction:column; min-width:0;
  background: var(--card); border: var(--hair); border-radius: var(--r-md);
  box-shadow: var(--sh-1); overflow:hidden;
  transition: transform var(--t) var(--ease), box-shadow var(--t) var(--ease);
}
.bingo-lot-ph{ display:block; aspect-ratio: 1 / 1; overflow:hidden; background: var(--card-2); border-bottom: var(--seam); }
.bingo-lot-ph img{
  width:100%; height:100%; object-fit:cover; object-position:50% 42%;
  transition: transform var(--t-slow) var(--ease);
}
.bingo-lot-ph:focus-visible{ outline: 3px dashed var(--thread); outline-offset: -6px; }
@media (hover: hover){
  .bingo-lot:hover{ transform: translateY(-3px); box-shadow: var(--sh-2); }
  .bingo-lot:hover .bingo-lot-ph img{ transform: scale(1.05); }
}
.bingo-lot-body{ display:flex; flex-direction:column; gap:3px; flex:1; padding: 10px 12px 12px; }
.bingo-lot-nm{ font-family: var(--font-display); font-weight:700; font-size:14.5px; line-height:1.2; color: var(--ink); }
.bingo-lot-from{ font-size:13px; font-weight:700; line-height:1.25; color: var(--sage-ink); }
.bingo-lot-price{ margin: 6px 0 8px; font-size:17px; font-weight:800; color: var(--clay-ink); }
.bingo-lot-price--ask{ font-size:13.5px; font-weight:700; color: var(--ink-soft); }
/* кнопка прижата к низу — низы карточек в полоске выравниваются */
.bingo-lot .btn{ width:100%; margin-top:auto; padding-inline:10px; white-space:normal; line-height:1.2; }
.bingo-lot.is-added .btn{
  background: linear-gradient(180deg, #6a8360, var(--sage-deep));
  color: var(--cream); border-color: transparent;
}

.bingo-finale{ margin-top: var(--sp-4); }

/* ─── 7. широкий экран: поле слева, бирка выбранной игрушки справа ─────── */
@media (min-width: 981px){
  .bingo-play{
    grid-template-columns: minmax(0, 1fr) 336px;
    grid-template-areas: 'stage side' 'under side';
    column-gap: var(--gap); row-gap: var(--sp-4);
  }
  .bingo-stage-block{ grid-area: stage; }
  .bingo-side{ grid-area: side; }
  .bingo-under{ grid-area: under; }
}

/* ─── 8. телефон ──────────────────────────────────────────────────────── */
@media (max-width: 980px){
  .bingo-under{ margin-top: var(--sp-1); }
}
@media (max-width: 740px){
  .bingo-progress{ gap: var(--sp-1); }
  .bingo-count{ font-size:13.5px; }
  .bingo-stage{ padding-top: 38px; margin-top: var(--sp-1); }
  .bingo-rank-tag{ right:6px; max-width:66%; padding: 7px 12px 9px 24px; }
  .bingo-rank-tag::after{ height:22px; }
  .bingo-mat{ padding:6px; border-radius: var(--r-md); }
  .bingo-board{ --bgap: 5px; }
  .bingo-cell{ padding:2px; border-radius:9px; }
  .bingo-cell::after{ top:6%; bottom:6%; }
  .bingo-cell::before{ left:6%; right:6%; }
  .bingo-ph{ border-radius:7px; }
  .bingo-mark{ width:54%; max-width:44px; right:3%; top:3%; }
  .bingo-thread{ height:12px; margin-top:-6px; background-size: 34px 12px; }
  .bingo-live{ min-height:52px; }
  .bingo-ranks .bingo-rank-list{ grid-template-columns: 1fr; }

  /* подборка «пять в ряд» на телефоне — не пять больших карточек в столбик,
     а пять коротких строк: фото слева, цена и кнопка справа */
  .bingo-lineup{ grid-template-columns: 1fr; gap: var(--sp-1); }
  .bingo-lot{ flex-direction: row; }
  .bingo-lot-ph{ flex:none; width:92px; aspect-ratio:auto; min-height:92px; border-bottom:0; border-right: var(--seam); }
  .bingo-lot-body{
    display:grid; gap:1px 10px; padding: 8px 10px 8px 12px; min-width:0;
    grid-template-columns: 1fr auto;
    grid-template-areas: 'nm nm' 'from from' 'price btn';
    align-items:center;
  }
  .bingo-lot-nm{ grid-area:nm; }
  .bingo-lot-from{ grid-area:from; }
  .bingo-lot-price{ grid-area:price; margin: 4px 0 0; }
  .bingo-lot .btn{ grid-area:btn; width:auto; margin:4px 0 0; font-size:13.5px; padding:8px 14px; }
}
@media (max-width: 359px){
  .bingo-board{ --bgap: 4px; }
  .bingo-rank-tag{ max-width:72%; }
  .bingo-lineup{ grid-template-columns: repeat(auto-fit, minmax(132px, 1fr)); }
}

/* ─── 9. без движения ─────────────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce){
  .bingo-rank-tag, .bingo-rank-tag.is-turn{ animation:none; transform: rotate(-2.6deg); }
  .bingo-mat{ transform:none; }
  .bingo-cell, .bingo-lot, .bingo-lot-ph img, .bingo-clew{ transition:none; }
}

/* ═════════════════════════════════════════════════════════════════════════
   14. ДВИЖЕНИЕ — режиссура всего сайта одним куском
   Дописано в конец файла намеренно: этот блок доводит уже существующее
   движение до одной физики и добавляет недостающее. :root тронут только
   в одном месте — там, где заведены кривые и длительности (раздел 1).

   ПРАВИЛА, КОТОРЫЕ ЗДЕСЬ НЕЛЬЗЯ НАРУШАТЬ:
   1. В кадровом цикле только transform и opacity. Никакого filter/blur,
      никаких box-shadow и width/height в бесконечных анимациях.
   2. Всё, что стартует невидимым, висит на классе .reveal — у него есть
      и запасной вариант без скрипта (<noscript> на каждой странице),
      и глушилка в prefers-reduced-motion. Своих «opacity:0 до класса»
      не заводить: если скрипт не отработает, страница останется пустой.
   3. Появление ничего не двигает в вёрстке: только transform/opacity,
      место элемента занято сразу, блоки под ним не прыгают.
   4. На телефоне фоновой жизни меньше — см. подраздел 14.8.
   ═══════════════════════════════════════════════════════════════════════ */

/* ─── 14.1 ПОЯВЛЕНИЕ: блок поднимается со стола ───────────────────────────
   База одна на весь сайт. --rd — задержка догона, её ставит app.js
   (соседи по сетке или по строке догоняют друг друга через --step). */
.reveal{ opacity:0; transform: translateY(18px); }
.reveal.is-in{
  opacity:1; transform:none;
  transition: opacity var(--t-in) var(--ease-out),
              transform var(--t-in-lg) var(--ease-out);
  transition-delay: var(--rd, 0s);
}

/* карточка не «выезжает снизу», а КЛАДЁТСЯ на стол: поднимается и
   доворачивается в ноль. Соседи по ряду доворачиваются в разные стороны —
   ряд получается живым, а не строем.
   :not(.is-in) обязателен: без него правило .card.reveal весит столько же,
   сколько .reveal.is-in, стоит в файле ниже — и карточка так и осталась бы
   лежать повёрнутой на 0,8°, просто проявившись. */
.card.reveal:not(.is-in),
.bingo-lot.reveal:not(.is-in){ transform: translateY(24px) rotate(var(--rv-r, .8deg)); }
.card.reveal:nth-child(2n),
.bingo-lot.reveal:nth-child(2n){ --rv-r: -.8deg; }

/* фотография ложится на стол — чуть подрастает до своего размера */
.reveal--photo{ transform: translateY(20px) scale(.986); }

/* «только проявиться» — для того, у чего уже есть свой transform
   (наклонённая записка отзыва, повёрнутое полотно бинго) */
.reveal--fade,
.reveal--fade.is-in{ transform: none; }

/* БИРКА появляется не подъёмом, а качком: пока она не в кадре, её
   собственное качание стоит на первом кадре (самый отведённый угол) —
   как только бирка появилась, качание пошло, и она «успокаивается».
   Отдельной анимации не нужно: работает та, что уже есть у .tag. */
.reveal--tag:not(.is-in){ animation-play-state: paused; }

/* ─── 14.2 ЗАГОЛОВОК СЕКЦИИ СОБИРАЕТСЯ ПО ЧАСТЯМ ──────────────────────────
   Надзаголовок и заголовок приходят вместе, стежок под заголовком
   прошивается следом, рукописная строка догоняет последней.
   Значения по умолчанию — «видно»: заголовок вне .reveal ничего не ждёт. */
.section-title::after{
  transform-origin: left center;
  transition: transform .5s var(--ease-out) calc(var(--rd, 0s) + .14s);
}
.reveal:not(.is-in) .section-title::after{ transform: scaleX(0); }

.section-head .hand{
  transition: opacity .42s var(--ease-out) calc(var(--rd, 0s) + .16s),
              transform .42s var(--ease-out) calc(var(--rd, 0s) + .16s);
}
/* два написания: .reveal может быть и обёрткой заголовка, и самим .section-head */
.reveal:not(.is-in) .section-head .hand,
.section-head.reveal:not(.is-in) .hand{ opacity:0; transform: translateY(7px); }

/* ─── 14.3 ЖИВЫЕ ДЕТАЛИ: мастерская дышит ─────────────────────────────────
   Всё в диапазоне 5–9 с, все со сдвигом по фазе — хором ничего не ходит. */

/* нить на первом экране: дорисовалась (1.95 с) — и дальше еле заметно
   покачивается, как настоящий шнур, на котором что-то висит */
.index-thread{
  transform-origin: 1% 50%;
  animation: ct-thread-breath 7.4s ease-in-out 2.2s infinite alternate;
}
@keyframes ct-thread-breath{
  from{ transform: rotate(-.16deg) translateY(0); }
  to  { transform: rotate(.3deg)  translateY(-2px); }
}

/* натянутая нить в шапке дышит натяжением: 3 px → 3,7 px и обратно.
   Меняется только scaleY — слой композитный, перерисовки нет */
.site-head::before{
  transform-origin: 50% 50%;
  animation: ct-cord-breath 6.6s ease-in-out infinite alternate;
}
@keyframes ct-cord-breath{ from{ transform: scaleY(1); } to{ transform: scaleY(1.24); } }

/* клубок с крючком лежит на столе и чуть перекатывается */
.index-prop--ball > svg{
  transform-origin: 50% 92%;
  animation: ct-prop-tilt 8.6s ease-in-out infinite alternate;
}
@keyframes ct-prop-tilt{ from{ transform: rotate(-.7deg); } to{ transform: rotate(.7deg); } }

/* слаймик дышит, тень под ним остаётся на столе */
.index-prop--slime img{ animation: ct-prop-bob 5.8s ease-in-out .9s infinite alternate; }
@keyframes ct-prop-bob{ from{ transform: translateY(0); } to{ transform: translateY(-3px); } }

/* клубок в подвале главной: нить наматывается, клубок ведёт */
.index-end-yarn{
  transform-origin: 50% 76%;
  animation: ct-yarn-turn 9s ease-in-out 2.6s infinite alternate;
}
@keyframes ct-yarn-turn{ from{ transform: rotate(-1.1deg); } to{ transform: rotate(1.1deg); } }

/* рукописная бирка на игрушке недели — тот же жест, что у всех бирок */
.index-week-mark{
  transform-origin: 82% 0;
  animation: ct-mark-sway 6.2s ease-in-out .5s infinite alternate;
}
@keyframes ct-mark-sway{ from{ transform: rotate(2.8deg); } to{ transform: rotate(5.4deg); } }

/* бирка мира в каталоге висит на нитке от стежка — значит качается.
   Фазы разведены, чтобы восемь разделов не кивали синхронно */
.catalog-fandom-tag{ transform-origin: 22px -20px; }
.catalog-fandom:nth-child(2n) .catalog-fandom-tag{ animation-duration: 6.4s; }
.catalog-fandom:nth-child(3n) .catalog-fandom-tag{ animation-duration: 7.3s; animation-delay: .5s; }
.catalog-fandom:nth-child(5n) .catalog-fandom-tag{ animation-duration: 5.9s; animation-delay: 1.1s; }

/* три снимка на первом экране отзывов ложатся на стол один за другим.
   backwards, а не forwards: после заезда каждый снимок возвращается к
   своему наклону из вёрстки, и :hover продолжает работать */
.reviews-snap{ animation: ct-snap-in .48s var(--ease-out) backwards; }
.reviews-snap:nth-child(2){ animation-delay: .09s; }
.reviews-snap:nth-child(3){ animation-delay: .18s; }
@keyframes ct-snap-in{ from{ opacity:0; transform: translateY(16px) rotate(-4.5deg); } }

/* прищепка на записке отзыва — бумага чуть ведёт от сквозняка */
.reviews-item--pin::before,
.reviews-item--pin::after{
  transform-origin: 50% 2px;
  animation: ct-pin-sway 7.8s ease-in-out infinite alternate;
}
.reviews-col:nth-child(2) .reviews-item--pin::before,
.reviews-col:nth-child(2) .reviews-item--pin::after{ animation-duration: 6.9s; animation-delay: .8s; }
@keyframes ct-pin-sway{ from{ transform: rotate(-3.2deg); } to{ transform: rotate(-1.4deg); } }

/* ─── 14.4 ОТКЛИК НА ПАЛЕЦ: короче, чем появление ─────────────────────────
   Нажатие — 140 мс, возврат — 280 мс: «прижал быстро, отпустил мягко». */
.btn:active, .card:active, .bingo-cell:active,
.catalog-chip:active, .reviews-chip:active, .icon-btn:active,
.cart-btn:active, .nav-link:active{ transition-duration: .14s; }

/* фирменный жест карточки — нитка прочерчивается под названием.
   На телефоне hover нет, поэтому её же чертит касание */
.card:active .card-body::before{ transform: scaleX(1); }
.bingo-lot:active{ transform: translateY(0) scale(.985); }

/* ─── 14.5 ШАПКА И КОРЗИНА ────────────────────────────────────────────────
   Шапка уезжает быстро (уходит с глаз), возвращается мягче (её ждут). */
.site-head{ transition: transform .34s var(--ease-out), box-shadow var(--t) var(--ease),
                        background-color var(--t) var(--ease); }
.site-head.is-hidden{ transition-duration: .24s; }

/* добавили в корзину: клубок дёрнулся, число отскочило и встало */
.cart-btn.bump{ animation: bump .46s var(--ease-back); }
@keyframes bump{
  0%{ transform: scale(1); }  30%{ transform: scale(1.1) rotate(2.5deg); }
  64%{ transform: scale(.975); }  100%{ transform: scale(1); }
}
@keyframes pop{ 0%{ transform: scale(1); } 38%{ transform: scale(1.42); } 100%{ transform: scale(1); } }
/* .pulse ставится на любое изменение числа, а не только на «добавили»:
   плюс и минус в шторке тоже должны отзываться в шапке */
.cart-count.pulse{ animation: pop .42s var(--ease-back); }

/* шторка выезжает мягко, затемнение приходит чуть раньше неё */
.cart-veil{ transition: opacity .3s var(--ease-out), visibility 0s .3s; }
.cart-drawer{ transition: transform .46s var(--ease-out), visibility 0s .46s; }
.cart-drawer.is-open{ transition-delay: 0s; }

/* содержимое догоняет шторку: позиции выезжают одна за другой, итог —
   последним. Класс is-fresh живёт меньше секунды и ставится ТОЛЬКО при
   открытии: пересчёт количества внутри открытой шторки ничего не двигает */
.cart-drawer.is-fresh .cart-item{
  animation: ct-cart-row .36s var(--ease-out) both;
  animation-delay: calc(.12s + var(--i, 0) * 46ms);
}
@keyframes ct-cart-row{
  from{ opacity:0; transform: translateX(18px); }
  to  { opacity:1; transform: none; }
}
.cart-drawer.is-fresh .cart-foot{ animation: ct-cart-foot .4s var(--ease-out) .18s both; }
@keyframes ct-cart-foot{
  from{ opacity:0; transform: translateY(16px); }
  to  { opacity:1; transform: none; }
}

/* всплывающая плашка приходит снизу и уходит вниз же */
.toast{ transition: transform .42s var(--ease-out), opacity var(--t) var(--ease-out), visibility 0s .42s; }

/* ─── 14.6 БИНГО: отметка как печать, линия как поздравление ──────────────
   Клетка собирает свой transform из трёх переменных, поэтому кадры
   анимации повторяют их — иначе нажатие сбрасывало бы наклон отметки. */
.bingo-cell.is-tap{ animation: ct-bingo-press .26s var(--ease-out); }
@keyframes ct-bingo-press{
  0%  { transform: translateY(var(--cell-lift)) rotate(var(--cell-rot)) scale(.93); }
  55% { transform: translateY(var(--cell-lift)) rotate(var(--cell-rot)) scale(1.045); }
  100%{ transform: translateY(var(--cell-lift)) rotate(var(--cell-rot)) scale(1); }
}
/* сердечко ставится штампом: с доводкой, а не просто вырастает */
.bingo-mark{ transition: transform .34s var(--ease-back), opacity var(--t-fast) var(--ease-out); }

/* линия собралась: пять клеток загораются одна за другой слева направо,
   и только потом сквозь них протягивается нитка */
.bingo-cell.is-lit{
  animation: ct-bingo-lit .44s var(--ease-back) backwards;
  animation-delay: calc(var(--i, 0) * 72ms);
}
@keyframes ct-bingo-lit{
  0%  { transform: translateY(var(--cell-lift)) rotate(var(--cell-rot)) scale(1); }
  42% { transform: translateY(-6px) rotate(var(--cell-rot)) scale(1.055); }
  100%{ transform: translateY(var(--cell-lift)) rotate(var(--cell-rot)) scale(1); }
}
.bingo-thread.is-new{ animation: bingo-draw .5s var(--ease-out) .3s both; }

/* нить прогресса и клубок на её конце: клубок подрастает вместе с полосой */
.bingo-bar-fill{ transition: transform .5s var(--ease-out); }
.bingo-clew{ transition: transform .44s var(--ease-back); }

/* подборка «пять в ряд» выкладывается карточка за карточкой.
   backwards, а не both: иначе застывший последний кадр перебил бы :hover */
.bingo-lot{ animation: ct-lot-in .42s var(--ease-out) backwards; animation-delay: var(--rd, 0s); }
@keyframes ct-lot-in{
  from{ opacity:0; transform: translateY(14px) scale(.985); }
  to  { opacity:1; transform: none; }
}

/* ─── 14.7 КАТАЛОГ: работы выкладываются на стол после отбора ─────────────
   Один язык с появлением: та же кривая, тот же шаг догона.
   animation-delay пишется ОТДЕЛЬНОЙ строкой: короткая запись animation
   обнуляет задержку, и весь догон карточек пропал бы молча. */
.card.catalog-pop{
  animation: catalog-pop .42s var(--ease-out) backwards;
  animation-delay: var(--rd, 0s);
}
@keyframes catalog-pop{
  from{ opacity:0; transform: translateY(14px) scale(.985); }
  to  { opacity:1; transform: none; }
}
/* включили фильтр — бирка коротко качнулась, как будто её тронули пальцем */
.catalog-chip.is-just{ animation: ct-chip-settle .36s var(--ease-out); }
@keyframes ct-chip-settle{
  0%  { transform: rotate(-2.6deg) scale(.97); }
  52% { transform: rotate(1.1deg)  scale(1.025); }
  100%{ transform: none; }
}
/* «только в наличии» — не бумажная бирка, а переключатель: он не качается,
   а коротко приседает и встаёт. Галочка внутри уже отрисовывается сама */
.catalog-switch.is-just{ animation: ct-switch-tick .32s var(--ease-back); }
@keyframes ct-switch-tick{
  0%{ transform: scale(.96); } 54%{ transform: scale(1.03); } 100%{ transform: none; }
}

/* ─── 14.8 ТЕЛЕФОН: движения меньше и оно легче ───────────────────────────
   Фон не ползёт (это экономит батарею при долгой прокрутке каталога),
   предметы мастерской стоят, появления короче — на мелком экране длинный
   заход читается как тормоз. */
@media (max-width: 740px){
  body::before{ animation: none; }
  .index-thread,
  .index-prop--ball > svg,
  .index-prop--slime img,
  .index-end-yarn,
  .catalog-fandom-tag,
  .reviews-item--pin::before,
  .reviews-item--pin::after{ animation: none; }
  .catalog-fandom-tag{ transform: rotate(-2.6deg); }
  .reviews-item--pin::before,
  .reviews-item--pin::after{ transform: rotate(-2.4deg); }

  .reveal{ transform: translateY(13px); }
  /* на мелком экране карточку не доворачиваем: поворот там читается
     как дрожь, а не как «положили на стол» */
  .card.reveal:not(.is-in),
  .bingo-lot.reveal:not(.is-in){ --rv-r: 0deg; transform: translateY(15px); }
  .reveal--photo{ transform: translateY(14px) scale(.99); }
  .reveal.is-in{
    transition: opacity .42s var(--ease-out), transform .46s var(--ease-out);
    transition-delay: var(--rd, 0s);
  }
  .cart-drawer.is-fresh .cart-item{ animation-delay: calc(.1s + var(--i, 0) * 34ms); }
}

/* ─── 14.9 БЕЗ ДВИЖЕНИЯ ───────────────────────────────────────────────────
   Раздел 11 уже гасит длительности всему сайту через !important. Здесь
   добивается то, что живёт не длительностью, а начальным кадром:
   фоновая жизнь снимается совсем, появления показываются сразу. */
@media (prefers-reduced-motion: reduce){
  .index-thread, .site-head::before, .index-prop--ball > svg,
  .index-prop--slime img, .index-end-yarn, .index-week-mark,
  .reviews-item--pin::before, .reviews-item--pin::after,
  .cart-btn.bump, .cart-count.pulse,
  .bingo-cell.is-tap, .bingo-cell.is-lit, .bingo-lot,
  .catalog-chip.is-just, .catalog-switch.is-just, .reviews-snap,
  .cart-drawer.is-fresh .cart-item,
  .cart-drawer.is-fresh .cart-foot{ animation: none !important; }

  .index-thread, .site-head::before, .index-prop--ball > svg,
  .index-prop--slime img, .index-end-yarn{ transform: none !important; }

  .bingo-lot,
  .cart-drawer.is-fresh .cart-item,
  .cart-drawer.is-fresh .cart-foot{ opacity: 1 !important; transform: none !important; }

  .reveal:not(.is-in) .section-title::after{ transform: none !important; }
  .reveal:not(.is-in) .section-head .hand{ opacity: 1 !important; transform: none !important; }
  .reveal--tag:not(.is-in){ animation-play-state: running; }
}

/* печать: бумага не двигается */
@media print{
  *, *::before, *::after{ animation: none !important; transform: none !important; }
}

/* ═════════════════════════════════════════════════════════════════════════
   15. ГЛАВНАЯ — правки после разбора страницы (только классы .index-*)
   Дописано в конец файла намеренно: чужие правила и :root не тронуты,
   всё ниже действует лишь внутри блоков главной страницы.
   ═══════════════════════════════════════════════════════════════════════ */

/* ─── 15.1 приписка про повтор ушла с фотографии в тело карточки ─────────
   Правила переехали в базовый блок карточки (.card-repeat, раздел 6):
   элемент теперь один на весь сайт и стоит в одном и том же месте. */

/* ─── 15.2 «в корзине ✓» одинаково на всей странице ──────────────────────
   У карточек зелёное состояние даёт .is-added на самой карточке; кнопки,
   написанные руками (бирка героя, игрушка недели, гача), получают тот же
   класс на себя — скрипт главной вешает его на 1,6 с. */
.index-tag-btn.is-added,
.index-buy .btn.is-added,
.index-week-buy .btn.is-added{
  background: linear-gradient(180deg, #6a8360, var(--sage-deep));
  color: var(--cream);
  border-color: transparent;
}

/* ─── 15.3 телефон: имя товара показываем целиком ───────────────────────
   На 360–390 px «Помни из Цифрового цирка» не влезал в две строки и
   обрывался многоточием. Три строки закрывают все шесть названий витрины
   вплоть до 320 px, высота карточек при этом остаётся одинаковой. */
@media (max-width: 740px){
  .index-stock .card-name{
    font-size:15px; line-height:1.24;
    -webkit-line-clamp:3; min-height:3.72em;
  }
}

/* ═════════════════════════════════════════════════════════════════════════
   16. БИНГО — правки по разбору арт-критика (дописано в конец файла)
   Ничего выше не переписано: все правила ниже перебивают прежние только
   тем, что стоят позже при равной силе селектора. :root не тронут,
   движение — по-прежнему только transform/opacity.
   ═══════════════════════════════════════════════════════════════════════ */

/* ─── 16.1 клетка в собранной линии: фотография проясняется ────────────────
   Было наоборот: поверх фото ложился зелёный светофильтр. Он врал про цвет
   пряжи (человек выбирает игрушку глазами) и делал награду ТУСКЛЕЕ обычной
   отметки. Теперь клетка в линии почти без вуали — собранная линия видно
   светлее соседей, а что это линия, говорят зелёная рамка и нитка. */
.bingo-cell.is-line .bingo-ph::after{ background: rgba(190,95,53,.05); }

/* строка-подпись живёт только для скринридера: у неё min-height 52 px,
   и без сброса она оставляла на экране полоску в пиксель шириной */
.bingo-live.visually-hidden{ min-height:0; padding:0; margin:0; }

/* ─── 16.2 нитка через линию: тоньше и с разной громкостью ─────────────────
   Было 14 px при клетке 57 px — четверть клетки. К девяти линиям поле
   превращалось в клубок зигзагов. Теперь стежок тоньше, а в полную силу
   светятся только две-три последние нитки (класс вешает bingo.html). */
.bingo-thread{
  height:8px; margin-top:-4px;
  background-size: 24px 8px;
  opacity:.7;
}
.bingo-thread.is-faint{ opacity:.28; }

/* ─── 16.3 подборка «пять в ряд»: размер под именем ────────────────────── */
.bingo-lot-size{
  font-size:12px; line-height:1.25; color: var(--ink-2);
}

/* ─── 16.4 кнопка сброса, которая переспрашивает ──────────────────────── */
.bingo-reset-armed{
  border-color: var(--thread);
  background: rgba(190,95,53,.1);
  color: var(--clay-ink);
  font-weight:800;
}

/* ─── 16.5 пустая корзина: выход не только через крестик ──────────────── */
.cart-empty .btn{ margin-top: 22px; }

/* ─── 16.6 телефон ────────────────────────────────────────────────────── */
@media (max-width: 740px){
  /* нитка ещё тоньше: клетка здесь 57 px, стежок в 6 px её не закрывает */
  .bingo-thread{ height:6px; margin-top:-3px; background-size: 18px 6px; }

  /* Бирка звания встаёт НАД полотном, а не поверх него. «Почётный житель
     уютного стола» вставал в три строки и непрозрачно закрывал верхний ряд
     клеток — ровно в тот момент, когда человек увлёкся игрой. */
  .bingo-stage{ display:flex; flex-direction:column; padding-top:0; }
  .bingo-rank-tag{
    position:relative; top:auto; right:auto;
    align-self:flex-end;
    max-width:100%; margin: 0 0 8px;
    padding: 7px 14px 9px 24px;
  }
  .bingo-rank-tag::after{ display:none; }   /* шнурок в потоке висел бы из пустоты */

  /* Колонка цены больше не рвётся на «цена по / запросу»: имя, размер,
     мир, цена и кнопка идут пятью отдельными строками. */
  .bingo-lot-body{
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas: 'nm' 'size' 'from' 'price' 'btn';
    align-items:start;
    gap: 1px 0;
  }
  .bingo-lot-size{ grid-area:size; }
  .bingo-lot-price{ margin: 5px 0 0; }
  .bingo-lot-price--ask{ white-space:nowrap; font-size:13px; }
  .bingo-lot .btn{ grid-area:btn; width:100%; margin: 7px 0 0; }

  /* подпись под логотипом была 9 px — мельче нижней границы читаемости */
  .logo-sub{ font-size:12px; letter-spacing:.07em; }
}

@media (max-width: 359px){
  /* на самых узких телефонах подборка остаётся лентой строк, а не
     двумя колонками по 132 px, где пять строк текста не помещаются */
  .bingo-lineup{ grid-template-columns: 1fr; }
}

/* ═════════════════════════════════════════════════════════════════════════
   17. ОТЗЫВЫ — правки после разбора (reviews.html)
   Дописано в конец файла, ничего выше не переписано: :root не тронут,
   свои классы с префиксом reviews-. Движение — transform, opacity и
   однократная отрисовка нити через stroke-dashoffset.
   ═══════════════════════════════════════════════════════════════════════ */

/* ─── 17.1 НИТЬ ЧЕРЕЗ ПЕРВЫЙ ЭКРАН ────────────────────────────────────────
   Экран без неё подходил любой мастерской ручной работы. Теперь через него
   проходит та же нить, что на главной: приходит сверху справа (от пункта
   «Отзывы» в навигации), провисает над снимками, которые висят на ней на
   прищепках, и завязывается узелком у строки «спасибо каждому...». */
.reviews-cord{
  display:block; width:100%; max-width:560px; height:40px;
  margin: var(--sp-3) 0 -12px;      /* нижние 12 px заходят на ленту снимков */
  overflow:visible;
}
.reviews-cord[hidden]{ display:none; }
.reviews-cord + .reviews-strip{ margin-top:0; }

.reviews-tail-wrap{ position:relative; max-width:560px; padding-left:30px; }
.reviews-cord-end{
  position:absolute; left:0; top:0;
  width:26px; height:100%;
  overflow:visible; pointer-events:none;
}
.reviews-cord-end[hidden]{ display:none; }
/* отзывы не загрузились, нити нет — отступ под неё тоже не нужен */
.reviews-tail-wrap:has(.reviews-cord-end[hidden]){ padding-left:0; }
.reviews-tail-wrap .reviews-strip-note{ margin-top: var(--sp-2); max-width:none; }
.reviews-thanks{ margin-top: var(--sp-2); }

/* отрисовка при загрузке: нить «вяжется» слева направо и сверху вниз */
.reviews-draw{
  stroke-dasharray:100; stroke-dashoffset:100;
  animation: reviews-draw 1.5s cubic-bezier(.6,.15,.35,.9) .3s forwards;
}
.reviews-draw--late{ animation-duration:.9s; animation-delay:1.45s; }
@keyframes reviews-draw{ to{ stroke-dashoffset:0; } }
.reviews-knot{ opacity:0; animation: reviews-knot .4s var(--ease-back) 2.2s forwards; }
@keyframes reviews-knot{ to{ opacity:1; } }

/* прищепка на каждом снимке: деревянная планка и металлическая пружинка.
   Средний снимок висит ниже — под ним нить провисает сильнее всего */
.reviews-snap::before{
  content:''; position:absolute; z-index:2;
  left:50%; top:-13px; width:11px; height:23px; margin-left:-5.5px;
  border-radius:3px;
  background: linear-gradient(180deg, var(--tag), var(--tag-2));
  border: var(--hair);
  box-shadow: 0 1px 2px rgba(120,80,45,.18), inset 0 1px 0 rgba(255,248,232,.75);
}
.reviews-snap::after{
  content:''; position:absolute; z-index:3;
  left:50%; top:-4px; width:15px; height:2px; margin-left:-7.5px;
  border-radius:2px; background: rgba(140,100,64,.45);
}
.reviews-snap:nth-child(2){ transform: rotate(.9deg) translateY(7px); }
.reviews-snap:nth-child(3){ transform: rotate(-.5deg) translateY(2px); }
/* повторено после них: у :nth-child и :hover вес одинаковый, и без этого
   правила ниже по файлу подъём под пальцем и под курсором перестал бы работать */
@media (hover: hover){
  .reviews-snap:hover{
    z-index:1; transform: rotate(0deg) translateY(-5px) scale(1.03);
    box-shadow: var(--sh-2);
  }
}
.reviews-snap:active{ transform: scale(.98); }

/* ─── 17.2 КРЕПЁЖ ЗАПИСКИ ─────────────────────────────────────────────────
   Прежняя бумажная бирка с нитью и узелком заменена деревянной прищепкой —
   тем же предметом, что держит снимки в шапке страницы. Правила стоят в
   разделе «отзывы» выше по файлу, здесь ничего не переопределяется. */

/* ─── 17.3 ЧТО КРУПНЕЕ НА ПЕРВОМ ЭКРАНЕ ───────────────────────────────────
   Было: на телефоне заголовок 28 px, а статистика «24» — 34 px, и самым
   крупным на экране оказывалось число, а не «Уже дома, уже обнимают». */
.reviews-hero h1{ font-size: clamp(34px, 8.5vw, 44px); }

/* ─── 17.4 «КАК ЗАКАЗАТЬ»: телеграм-ссылка стала кнопкой ──────────────────
   Была тап-цель 121×19 px при норме 44 — пальцем не попасть. */
.reviews-tg{ margin-top:10px; }
/* ссылка внутри строки шага: тап-цель 44 px по высоте, при этом строка
   не раздвигается — отрицательное поле возвращает высоту обратно */

/* подпись на фото: «увеличить» — только там, где лупа правда увеличивает */
.reviews-zoom-narrow{ display:none; }

/* ─── 17.5 ПУСТАЯ КОРЗИНА ─────────────────────────────────────────────────
   На телефоне это была шторка во весь экран с двумя строками наверху и
   800 px пустоты под ними. Теперь содержимое стоит по центру. */
.cart-body:has(.cart-empty){ display:grid; place-content:center; }

/* ─── 17.6 ТЕЛЕФОН ───────────────────────────────────────────────────────── */
@media (max-width: 740px){
  /* ЛУПА. Была меньше карточки: фото в кладке 340 px по ширине, а в лупе
     330 и обрезано по высоте правилом max-height:44vh — кнопка обещала
     «увеличить», а картинка уменьшалась. Теперь фото — гибкая строка сетки
     и занимает больше 60 % высоты экрана, текст отзыва скроллится сам. */
  .reviews-lb{ padding:8px; }
  .reviews-lb-box{
    grid-template-columns: 1fr;
    grid-template-rows: minmax(0,1fr) auto;
    gap:10px;
    height: 92vh;
    height: 92svh;
    max-height:none;
    padding:10px;
    border-radius: var(--r-lg);
  }
  .reviews-lb-figure img{ max-height:none; height:100%; }
  .reviews-lb-side{ max-height:28vh; max-height:28svh; }
  .reviews-lb-text{ flex:1 1 auto; min-height:0; }
  /* крестик уезжает на само фото — освободившиеся 56 px отданы фотографии */
  .reviews-lb-top{
    position:absolute; z-index:4; top:16px; right:16px;
    margin:0; gap:0;
  }
  .reviews-lb-top .overline{ display:none; }
  .reviews-lb-top .icon-btn{ background: var(--card); box-shadow: var(--sh-2); }

  /* заголовок снова крупнее статистики */
  .reviews-num b{ font-size:28px; }

  /* карточка тут уже во всю ширину экрана — лупа даёт не размер, а фото
     без страницы вокруг, весь текст отзыва и переход по всем снимкам */
  .reviews-zoom-wide{ display:none; }
  .reviews-zoom-narrow{ display:inline; }

  /* нить и прищепки на узком экране: снимки мельче — крепёж тоже */
  .reviews-cord{ height:34px; margin-bottom:-10px; }
  .reviews-snap::before{ top:-11px; height:20px; width:10px; margin-left:-5px; }
  .reviews-snap::after{ top:-3px; width:13px; margin-left:-6.5px; }
  .reviews-tail-wrap{ padding-left:26px; }

  .reviews-tg{ width:100%; }
}

@media (max-width: 359px){
  .reviews-tail-wrap{ padding-left:22px; }
}

@media (prefers-reduced-motion: reduce){
  /* нить показана сразу целиком, узелок на месте — движения нет */
  .reviews-draw{ animation:none !important; stroke-dashoffset:0; }
  .reviews-knot{ animation:none !important; opacity:1; }
  .reviews-snap:nth-child(2),
  .reviews-snap:nth-child(3){ transform:none !important; }
  .reviews-item--pin::after{ transform:none; }
}

@media print{
  .reviews-cord, .reviews-cord-end{ display:none !important; }
  .reviews-tail-wrap{ padding-left:0; }
}

/* ═════════════════════════════════════════════════════════════════════════
   17. КАТАЛОГ — правки по разбору арт-критика (2026-08-12)
   Дописано в конец файла. :root и чужие правила не тронуты, свои селекторы
   с приставкой catalog-. Движение — только transform и opacity.

   Что чинится:
     17.1 системные эмодзи в условиях и сэтах → свои рисунки цвета нити;
     17.2 второй бейдж ложился игрушке на голову (телефон);
     17.3 названия работ обрывались многоточием в двух колонках;
     17.4 полка бирок была приклеена к левому краю экрана;
     17.5 обрезанная бирка из-под чекбокса на широком экране;
     17.6 бирка раздела уезжала, оставляя слева метр пустоты;
     17.7 БЛОКЕР: в шторке просмотра текст печатался поверх кнопки;
     17.8 висячий пробел перед точкой в строке контакта;
     17.9 первый ряд фотографий не попадал в первый экран телефона;
     17.10 при открытии файлом сводка показывала три прочерка.
   ═══════════════════════════════════════════════════════════════════════ */

/* ─── 17.1 свои значки вместо системных эмодзи ────────────────────────────
   Эмодзи ломали палитру: на айфоне глянцевый кислотно-зелёный клубок и
   жёлтая банковская карта, на Windows часть символов не находилась вовсе.
   Теперь рисунки свои — одно семейство линий цвета нити (4,2:1 к бумаге,
   для рисунка требуется 3:1). */
.catalog-ic{
  display: block; width: 28px; height: 28px;
  color: var(--thread);
}
.catalog-term-icon{
  display: block; font-size: 0; line-height: 0;   /* внутри рисунок, не буква */
  margin-bottom: 2px;
}
.catalog-set-icon{ font-family: var(--font-text); font-size: 0; }
.catalog-set-icon .catalog-ic{ width: 30px; height: 30px; }

/* ─── 17.2 приписка про повтор уходит с фотографии в тело карточки ────────
   Правила переехали в базовый блок карточки (.card-repeat, раздел 6):
   элемент один на весь сайт, собирает его app.js. */

/* ─── 17.3 название работы целиком, ряды одной высоты ─────────────────────
   В двух колонках «Помни из Цифрового…» и «Королёр из Цифрового…»
   обрывались многоточием. Даём третью строку и держим под неё место, чтобы
   ряды карточек остались одного размера — так просила Дарья. */
@media (max-width: 740px){
  .catalog-card .card-name{
    -webkit-line-clamp: 3;
    min-height: 60px;
  }
}

/* ─── 17.4 полка бирок: левое поле и «есть ещё» справа ────────────────────
   Лента с прилипанием съедала боковое поле: первая бирка стояла в x=0, хотя
   весь остальной текст начинается с 16 px, и был виден срезанный угол.
   scroll-padding возвращает поле. Правый край растворяется — обрезанное на
   полуслове читается как «есть ещё», а не как сломанная вёрстка. */
@media (max-width: 740px){
  .catalog-chips{
    scroll-padding-inline: var(--pad-page);
    -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 34px), transparent calc(100% - 2px));
            mask-image: linear-gradient(90deg, #000 calc(100% - 34px), transparent calc(100% - 2px));
  }
}

/* ─── 17.5 широкий экран: обрезанная бирка за чекбоксом ───────────────────
   В сложенной полке из-под чекбокса «только то, что в наличии» торчала
   половина буквы — читалось как баг вёрстки. Растворение сделано длиннее и
   глубже, плюс зазор до чекбокса. */
@media (min-width: 741px){
  .catalog-filters.is-pinned .catalog-chips{
    padding-right: 12px;
    -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 96px),
                        rgba(0,0,0,.28) calc(100% - 44px), transparent calc(100% - 8px));
            mask-image: linear-gradient(90deg, #000 calc(100% - 96px),
                        rgba(0,0,0,.28) calc(100% - 44px), transparent calc(100% - 8px));
  }
}

/* ─── 17.6 бирка раздела едет вместе со своей секцией ─────────────────────
   В длинных разделах ярлык показывался один раз в начале и уезжал: дальше
   слева оставалось до тысячи пикселей голого фона на 40% ширины. Теперь
   бирка вместе с ниткой и счётчиком липнет под шапкой и идёт рядом со
   своими работами — как ярлык в картотеке. Высоту остановки считает скрипт
   (--catalog-stick): шапка плюс сложенная полка фильтров плюс зазор. */
.catalog-fandom-stick{ display: contents; }   /* на телефоне обёртки будто нет */

@media (min-width: 981px){
  .catalog-fandom-head{
    display: block;            /* колонку теперь строит сама обёртка */
    align-self: stretch;       /* без этого бирке некуда ехать */
  }
  .catalog-fandom-stick{
    display: flex; flex-direction: column; align-items: flex-start; gap: 10px;
    position: sticky; top: var(--catalog-stick, 168px);
  }
  /* нитка от стежка к бирке переезжает на обёртку: иначе бирка уедет вниз,
     а нитка останется висеть в пустоте */
  .catalog-fandom-head::before{ display: none; }
  .catalog-fandom-stick::before{
    content:''; position: absolute; left: 22px; top: -22px;
    width: 2.5px; height: 24px;
    background: var(--thread); border-radius: 2px;
  }
  .catalog-fandom:first-child .catalog-fandom-stick::before{ display: none; }
}

/* ─── 17.7 шторка быстрого просмотра на телефоне ──────────────────────────
   БЛОКЕР: список деталей получал высоту 15 px при содержимом 94 px и
   выливался наружу — строки печатались поверх кнопки «все работы из этого
   мира». Виновата прокрутка внутри списка: на телефоне прокручиваться
   должна вся шторка целиком, а не отдельный её кусок. */
@media (max-width: 740px){
  .catalog-qv-details{
    overflow: visible;
    flex: none;
    min-height: auto;
  }
  /* фотография чуть ниже прежних 42vh: иначе описание вместе с кнопкой
     «все работы из этого мира» не помещается в шторку и кнопка уезжает
     под липкую строку с ценой — тот же вид наложения, только другой */
  .catalog-qv-figure img{ max-height: 34vh; }
  /* и ещё 22 px по мелочи: теперь самая длинная карточка (Помни) целиком
     помещается в экран 390×844 — прокручивать нечего */
  .catalog-qv-name{ margin-bottom: 8px; }
  .catalog-qv-badges{ margin-bottom: 8px; }
  .catalog-qv-size{ margin-bottom: 8px; }
  .catalog-qv-more{ margin: 6px 0 8px; }
  .catalog-qv-pay{ padding-top: 8px; }
}

/* ─── 17.8 строка контакта в конце ────────────────────────────────────────
   Ссылка была inline-flex с боковыми полями: перед точкой висел пробел, а
   строка на телефоне разъезжалась по высоте. Зона нажатия остаётся 44 px —
   её даёт вертикальное поле, вынесенное отрицательным внешним отступом. */
.catalog-terms-foot a{
  display: inline;
  min-height: 0;
  padding-inline: 0;
  padding-block: 12px;    /* 21 px строки + 24 = 45 px под палец */
  margin-block: -12px;
}

/* ─── 17.9 первый экран телефона: игрушки видно сразу ─────────────────────
   Первая карточка начиналась на 872 px при высоте экрана 844 — до правки на
   первом экране не было ни одной работы, только заголовок, абзац и сводка.
   Сжат вводный блок; кегль текста не тронут, читаемость та же. */
@media (max-width: 740px){
  .catalog-top{ padding-top: 4px; padding-bottom: 10px; }
  .catalog-hero{ gap: 12px; }
  .catalog-lead{ margin-top: 9px; }
  .catalog-top .hand{ margin-top: 8px; }

  .catalog-facts{ padding: 12px 14px 13px; }
  .catalog-facts .overline{ margin-bottom: 7px; }
  .catalog-nums{ gap: 6px; margin-bottom: 10px; }
  .catalog-nums span{ min-height: 2.4em; }
  .catalog-facts-btn{ margin-top: 0; }

  .catalog-filters-in{ gap: 8px; padding-block: 9px; }
  .catalog-body{ padding-top: 4px; }
  .catalog-fandom:first-child{ padding-top: 6px; }
  .catalog-fandom-head{ margin-bottom: 10px; }

  /* чекбокс и счётчик встают в одну строку: раздельными строками полка
     съедала 27 px первого экрана. Зона нажатия чекбокса прежняя — 44 px
     держит min-height, поля только боковые. */
  .catalog-tools{
    flex-direction: row; flex-wrap: nowrap;
    align-items: center; justify-content: space-between;
    gap: 8px;
  }
  .catalog-switch{ flex: 0 0 auto; justify-content: flex-start; padding: 8px 12px 8px 10px; font-size: 13.5px; }
  .catalog-count{ flex: 1 1 auto; min-width: 0; text-align: right; font-size: 13px; line-height: 1.3; }
}

@media (max-width: 359px){
  /* на самых узких в строку они уже не помещаются — возвращаем столбик */
  .catalog-tools{ flex-direction: column; align-items: stretch; }
  .catalog-switch{ justify-content: center; }
  .catalog-count{ text-align: center; }
}

/* ─── 17.10 страницу открыли файлом: данных нет ───────────────────────────
   Дарья может скачать папку и открыть catalog.html двойным щелчком — тогда
   браузер запрещает читать catalog.json. Всё, что без данных показывает
   прочерки и пустые рамки (сводка, полка фильтров, рамка гачи), убирается:
   остаётся объяснение и кнопка в прайс-канал. */
body.catalog-nodata .catalog-facts,
body.catalog-nodata .catalog-filters,
body.catalog-nodata .catalog-filters-gap,
body.catalog-nodata .catalog-up-line,
body.catalog-nodata .catalog-gacha-sec{ display: none; }

/* ═════════════════════════════════════════════════════════════════════════
   20. КАТАЛОГ — правки по второму разбору арт-критика.
   Дописано в конец файла: :root и чужие правила не тронуты, каждый селектор
   начинается с класса catalog-*. Движение — только transform/opacity
   (и отдельное свойство translate, которое ими же и считается).
     20.1  бейджи ушли с фотографии в тело карточки на ВСЕХ экранах;
     20.2  название без резерва высоты, низ карточки прижат сам;
     20.3  «повтор невозможен» — одной строкой в узкой колонке;
     20.4  «по запросу» не рвётся на две строки;
     20.5  ховер карточки: подъём, а не одна чёрточка;
     20.6  телефон: сводка «сейчас на столе» — строка, а не карточка;
     20.7  телефон: лид в две строки;
     20.8  телефон: полка фильтров прилипает и складывается в 60 px;
     20.9  широкий экран: в сложенной полке короткие подписи и компактная галка;
     20.10 счётчик работ переехал под полку;
     20.11 подпись под фотографией гачи — по левому краю;
     20.12 быстрый просмотр: правая колонка без дыры в 150 px;
     20.13 корзина: штучная работа не множится степпером.
   ═══════════════════════════════════════════════════════════════════════ */

/* ─── 20.1 бейджи под названием на всех экранах ───────────────────────────
   На широком экране два чипа стояли стопкой 151×65 поверх фотографии 273×271
   и накрывали товар: Помни — колпак, Джозефу — лицо, Шермочке — шляпку.
   Решение уже было найдено для телефона и для быстрого просмотра — здесь оно
   распространяется на все ширины: слева вверху остаётся только статус,
   «возможен повтор» становится строкой в тексте карточки. */
/* Строку собирает app.js для любой карточки сайта, стили — .card-repeat
   в разделе 6. Здесь остался только этот указатель (2026-08-12). */

/* ─── 20.2 название без резерва высоты ────────────────────────────────────
   min-height под три строки давал у однострочных карточек («Морской кролик»,
   «Нико из OneShot») сорок пикселей пустоты сразу под названием, а у
   трёхстрочных — ни одного: ряд выглядел рассыпанным. Высоту рядов держит
   не название, а прижатый к низу блок «цена + кнопка» (margin-top:auto у
   .card-foot) — пустота собирается под кнопкой и в глаза не бросается. */
.catalog-card .card-name{ min-height: 0; }

/* ─── 20.3 узкая карточка телефона ───────────────────────────────────────
   «повтор невозможен» в колонке 165 px переносился на две строки и делал
   пилюлю вдвое выше соседних. Слова Дарьи не сокращаем — ужимаем кегль. */
@media (max-width: 740px){
  .card-repeat{ font-size: 12.5px; padding: 3px 9px 4px 7px; }
}

/* ─── 20.4 «по запросу» одной строкой ─────────────────────────────────────
   Двухстрочная «цена по запросу» сбивала базовую линию в ряду, где соседи
   показывают «3 700 ₽» одной строкой. Полная формулировка осталась в
   быстром просмотре — там для неё есть место. */
.catalog-card .catalog-price-ask{
  white-space: nowrap;
  font-size: 15px; line-height: 1.2;
}

/* ─── 20.5 ховер карточки: её приподняли пальцем ──────────────────────────
   Подъём .card:hover не работал: правило .reveal.is-in{transform:none} стоит
   в файле ниже при равной силе селектора и гасило его — от отклика оставалась
   только сорокапиксельная нитка под названием. Поднимаем отдельным свойством
   translate: оно складывается с transform, а не спорит с ним. Тень — --sh-2,
   в системе это ровно «предмет приподняли пальцем». */
@media (hover: hover){
  .catalog-card.reveal.is-in{
    transition: opacity var(--t-in) var(--ease-out),
                transform var(--t-in-lg) var(--ease-out),
                translate var(--t) var(--ease),
                box-shadow var(--t) var(--ease);
    /* задержка догона остаётся только у появления, отклик мгновенный */
    transition-delay: var(--rd, 0s), var(--rd, 0s), 0s, 0s;
  }
  .catalog-card.reveal.is-in:hover{ translate: 0 -6px; box-shadow: var(--sh-2); }
  .catalog-card:hover .card-ph img{ transform: scale(1.06); }
}
@media (prefers-reduced-motion: reduce){
  .catalog-card.reveal.is-in:hover{ translate: none; }
}

/* ─── 20.6 телефон: сводка одной строкой ──────────────────────────────────
   Карточка «Сейчас на столе» забирала 164 px первого экрана и на две трети
   повторяла полку фильтров (20 = бирка «Все 20», 6 = счётчик галочки).
   Числа остаются — но как строка под лидом, без бумаги и без рамки. */
.catalog-nums-sm{ display: none; }

@media (max-width: 740px){
  .catalog-facts{
    padding: 0; background: none; border: 0; box-shadow: none;
  }
  .catalog-facts .overline{ display: none; }
  .catalog-nums{
    display: flex; flex-wrap: wrap; align-items: baseline;
    gap: 2px 9px; margin: 0;
  }
  .catalog-nums li{
    flex-direction: row; align-items: baseline; gap: 5px;
    padding: 0; border: 0;
  }
  .catalog-nums li + li{ border-left: 0; }
  /* точка-разделитель ставится ПОСЛЕ всех, кроме последнего: у последнего
     пункта порядок перевёрнут (подпись перед числом), и ::before уехал бы
     в самый конец строки — висел хвостик «640 ₽ ·» */
  .catalog-nums li:not(:last-child)::after{
    content: '·'; color: var(--ink-faint); font-weight: 800;
  }
  .catalog-nums b{ font-size: 16px; }
  .catalog-nums span{
    min-height: 0; font-size: 12.5px; font-weight: 700; color: var(--ink-2);
  }
  .catalog-nums-lg{ display: none; }
  .catalog-nums-sm{ display: inline; }
  /* «цены от 640 ₽»: подпись встаёт перед числом, порядок в разметке цел */
  .catalog-nums li:last-child{ flex-direction: row-reverse; }
}

/* ─── 20.7 телефон: лид в две строки ─────────────────────────────────────
   Оговорка про цены под заказ занимала две строки из четырёх и повторялась
   в каждой такой карточке кнопкой «узнать цену». */
@media (max-width: 740px){
  .catalog-lead-more{ display: none; }
}

/* ─── 20.7б телефон: последние сорок пикселей до фотографий ───────────────
   Надзаголовок «вязано крючком · ручная работа» слово в слово повторяет
   подпись под логотипом в шапке, которая на телефоне стоит прямо над ним, —
   на узком экране это 22 px, купленные повтором. Остальное собрано по
   мелочи: поля вводного блока и бирки раздела. Кегль текста не тронут. */
@media (max-width: 740px){
  .catalog-top .overline{ display: none; }
  .catalog-top{ padding-bottom: 8px; }
  .catalog-hero{ gap: 9px; }
  .catalog-top .hand{ margin-top: 6px; }
  .catalog-fandom:first-child{ padding-top: 4px; }
  .catalog-fandom-head{ margin-bottom: 8px; }
  .catalog-fandom-tag{ padding: 8px 13px 9px 22px; }
  .catalog-fandom-name{ font-size: 16px; }
}

/* ─── 20.8 телефон: полка фильтров прилипает ──────────────────────────────
   Страница длиной 10 464 px, а полка стояла в потоке: сменить фандом можно
   было, только вернувшись в самый верх. Теперь полка липнет под шапкой и
   складывается в одну строку 60 px: лента бирок и галочка-иконка.
   Шапка на телефоне уезжает вверх при прокрутке вниз — полка едет за ней
   тем же transform и той же длительностью, без пересчёта раскладки. */
@media (max-width: 740px){
  .catalog-filters{
    position: sticky;
    transition: transform var(--t) var(--ease), box-shadow var(--t) var(--ease);
  }
  .catalog-filters.is-up{
    transform: translateY(calc(var(--catalog-up, 132px) * -1));
  }
  .catalog-filters-in{
    flex-direction: row; align-items: center;
    gap: 8px; padding-block: 8px;
  }
  /* лента бирок уходит левым краем под поле страницы (обрез читается как
     «есть ещё»), но справа обязана закончиться до галочки: с отрицательным
     полем справа бирки заезжали прямо под неё */
  .catalog-chips{
    flex: 1 1 auto; min-width: 0;
    margin-inline: calc(var(--pad-page) * -1) 0;
    padding-inline: var(--pad-page) 4px;
  }
  /* тонкий шов отделяет галочку от ленты: без него обрезанная маской бирка
     упиралась прямо в переключатель и читалась как его часть */
  .catalog-tools{
    flex: none;
    padding-left: 9px;
    border-left: var(--hair);
  }
  /* стрелка-подсказка «лента листается» была приклеена к правому краю полки
     (right:0) и после пересборки в одну строку показывала не на конец ленты,
     а за переключатель. Ставим её в поток — ровно на стык ленты и галочки. */
  .catalog-chips-hint{
    position: static; flex: none;
    width: 17px; height: 34px; padding-right: 0;
    margin-left: -3px;
  }
}

/* ─── 20.9 компактная галочка «в наличии» ─────────────────────────────────
   В сложенной полке на 1440 лента бирок получала 832 px при собственной
   ширине 1595: четыре мира уезжали под маску, а колёсико горизонтальную
   ленту не крутит. Освобождаем ~380 px: подписи бирок становятся короткими
   («The Binding of Isaac» → «Айзек», «Все работы» → «Все»), а переключатель
   сворачивается в галочку со счётчиком. Слова уходят под clip-path, а не под
   display:none — голосовое чтение по-прежнему получает полное имя кнопки. */
.catalog-switch{ position: relative; }

/* Имя мира на бирке одно и то же в любом состоянии полки (2026-08-12):
   раньше при прилипании «The Amazing Digital Circus» превращался в
   «Цифровой цирк», числа пропадали, а бирка раздела ниже по странице
   говорила третье имя. Теперь скрипт печатает одну подпись — ту, что
   короче, — и счётчик остаётся при ней всегда.
   Прячется только слово у переключателя «в наличии»: это не имя мира,
   а команда, и её смысл остаётся в галочке и в подписи для чтения вслух. */
.catalog-filters.is-pinned .catalog-switch-tx{
  position: absolute; width: 1px; height: 1px;
  padding: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap;
  display: block;                       /* clip вместо display:none */
}
.catalog-filters.is-pinned .catalog-switch{ padding: 8px 12px; gap: 7px; }
@media (min-width: 741px){
  .catalog-filters.is-pinned .catalog-chips{ gap: 7px; }
  .catalog-filters.is-pinned .catalog-tools{ padding-left: 14px; border-left: var(--hair); }
}

/* на телефоне полка компактна всегда: там каждый пиксель — это фотография */
@media (max-width: 740px){
  .catalog-switch-tx{
    position: absolute; width: 1px; height: 1px;
    padding: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap;
    display: block;
  }
  .catalog-switch{ padding: 8px 11px; gap: 7px; }
}

/* ─── 20.10 счётчик работ — под полкой ────────────────────────────────────
   Раньше он жил внутри полки и в прилипшем виде его всё равно приходилось
   прятать. Теперь это обычная строка каталога: видна всегда, места в липкой
   полке не занимает. Пока ничего не отобрано, на телефоне она повторяет
   сводку — тогда уезжает под clip (чтение вслух её по-прежнему получает). */
.catalog-count{
  margin: 0 0 var(--sp-1); margin-left: 0;
  font-weight: 700; color: var(--ink-soft);
}
@media (max-width: 740px){
  .catalog-count{ margin-bottom: 6px; text-align: left; font-size: 12.5px; }
  .catalog-count.is-idle{
    position: absolute; width: 1px; height: 1px;
    overflow: hidden; clip-path: inset(50%); white-space: nowrap;
  }
}

/* ─── 20.10б имя общего раздела длиннее прочих ────────────────────────────
   «миры, где пока по одной-две работы» — это правило отбора, а не название
   игры, и в узкой бирке-ярлыке оно занимало три строки. Кегль поменьше —
   бирка встаёт в две строки и не спорит с названиями игр. */
.catalog-fandom--mixed .catalog-fandom-name{
  font-size: clamp(15.5px, 1.6vw, 18px);
}

/* ─── 20.11 подпись под фотографией гачи ──────────────────────────────────
   Весь текст страницы держит левый край — центрированная подпись выпадала
   из строя. */
.catalog-gacha-ph figcaption{ text-align: left; }

/* ─── 20.12 быстрый просмотр: правая колонка без дыры ─────────────────────
   Группа «оплата + цена + кнопка» прижималась к низу колонки, и между
   строкой «все работы из этого мира» и оплатой зияло полтораста пикселей.
   Колонка больше не растягивается: содержимое стоит одним блоком по центру
   против фотографии, пустота ушла в поля. */
@media (min-width: 741px){
  .catalog-qv-side{ align-self: center; max-height: 100%; }
  .catalog-qv-pay{ margin-top: 0; padding-top: var(--sp-3); }
  .catalog-qv-side:has(.catalog-qv-pay[hidden]) .catalog-qv-foot{ margin-top: 0; }
}

/* ─── 20.12б плашка при открытой корзине не растягивается ─────────────────
   БЛОКЕР, найден при проверке: в корзине что-то лежит (body.catalog-has-bar
   поднимает плашку над полосой итога) и корзина открыта (body.is-cart-open
   переносит плашку наверх). Два правила складывались: у плашки оказывались
   заданы и top, и bottom — она растягивалась во весь экран телефона и
   закрывала список с кнопкой заказа. Здесь низ снова отпускается. */
body.is-cart-open.catalog-has-bar .toast{ bottom: auto; }

/* ─── 20.13 корзина: штучная работа не множится ───────────────────────────
   У работы «в наличии» существует ровно один экземпляр, а степпер позволял
   поставить 2-3 штуки. Вместо «− 1 +» в такой строке стоит пометка «одна
   такая» и честная кнопка: второй экземпляр уходит отдельной строкой в
   изготовление, со сроком из данных. */
.catalog-cart-one{
  display: flex; flex-wrap: wrap; align-items: center;
  gap: 4px 10px; margin-top: 8px;
}
.catalog-cart-one-tx{
  display: inline-flex; align-items: center; gap: 6px;
  padding: 3px 10px 4px 8px;
  border-radius: var(--r-pill);
  background: var(--paper-shade);
  border: var(--hair);
  font-size: 12px; font-weight: 700; color: var(--ink-2);
}
.catalog-cart-one-tx::before{
  content:''; flex: none; width: 6px; height: 6px; border-radius: 50%;
  background: var(--st-ok);
  box-shadow: inset 0 0 0 1px rgba(90,60,35,.35);
}
.catalog-cart-more{
  display: inline-flex; align-items: center;
  min-height: var(--tap); padding: 4px 2px;
  background: none; border: 0; cursor: pointer;
  font-family: var(--font-text); font-size: 13px; font-weight: 800;
  color: var(--clay-ink);
  text-decoration: underline; text-decoration-style: dashed;
  text-underline-offset: 4px;
  transition: color var(--t-fast) var(--ease), transform var(--t-fast) var(--ease);
}
@media (hover: hover){
  .catalog-cart-more:hover{ color: var(--thread); transform: translateY(-1px); }
}
.catalog-cart-more:active{ transform: scale(.97); }

/* ═══════════════════════════════════════════════════════════════════════════
   18. ГЛАВНАЯ · ПЕРЕСБОРКА ПЕРВОГО ЭКРАНА (правки по разбору)
   Только префикс index- и только через body.index-page там, где правило
   касается общих частей (шапка, меню). Другие страницы не задеваются.
   :root не трогается, в анимациях только transform и opacity.
   ══════════════════════════════════════════════════════════════════════════ */

/* ─── 18.1 пятый пункт меню: «Как заказать» ───────────────────────────────
   ТЗ называет заказы отдельным разделом, секция #how на странице есть, а
   дороги к ней из меню не было. На телефоне подпись короче — иначе пять
   пунктов не помещаются в одну строку и меню переносится. */
.index-nav-short{ display: none; }
/* короткая запись срока в бирке — только для узкой бирки телефона */
.index-term-short{ display: none; }

/* Полосу 741–930 px, где пятый пункт выталкивал корзину за экран, чинит
   общий для всех страниц блок «шапка на средних экранах» ниже по файлу:
   там же прячется подпись у корзины и включается короткая «Заказать».
   Своего дубля здесь не держим — шапка на сайте одна. */

/* ─── 18.2 широкий экран: первый экран целиком в окне ────────────────────
   Было: шапка + первый экран 881 = 985 при окне 900, и деревянный стол
   показывался полосой в 41 px, разрезанной нижним краем окна. Сцена
   «мастерская на столе» теряла пол.
   Стало: первый экран ростом ровно в оставшееся под шапкой окно,
   столешница кончается на самом сгибе.
   2026-08-12: своей укороченной шапки у главной больше нет — она такая же,
   как на остальных страницах (113 px), и вычитается здесь именно эта цифра. */
@media (min-width: 741px){
  .index-hero{
    /* столешница чуть тоньше прежней: её нижняя кромка должна совпасть
       с нижним краем окна, а не уехать за него */
    --shelf-h: clamp(64px, 6.4vw, 92px);
    padding-bottom: calc(var(--shelf-h) + var(--prop-h) * .3);
    min-height: calc(100svh - 114px);     /* 114 = высота общей шапки сайта */
    display: flex; flex-direction: column; justify-content: center;
  }
  /* снимок приподнят над столешницей: рукописной строке под ним нужно
     место, иначе она ложится на дерево и теряет контраст */
  .index-photo{ margin-bottom: -20px; }

  /* Шапка стала общей и подросла на 18 px — ровно столько же собрано
     обратно в первом экране, чтобы столешница по-прежнему кончалась на
     сгибе окна 900 px: воздух под нитью и над абзацем (2026-08-12) */
  .index-hero .index-thread{ margin-block: 2px 12px; }

  /* чтобы первый экран уместился, воздух между блоками собран, а вводный
     абзац стал на полторы фразы короче. Кегль текста не тронут, ширина
     колонки тоже: правее неё идёт коридор соединительной нити, и текст
     туда заходить не должен. */
  .index-cta{ margin-top: 16px; }
  /* строка условий в две строки вместо трёх: 40ch давали узкую колонку в
     302 px, а справа до клубка ещё сотня пикселей пустого поля */
  .index-terms{ margin-top: var(--sp-1); max-width: 52ch; }

  /* ─── 18.2.1 планшет: бирка не накрывает игрушку целиком ────────────────
     При 741–1000 px колонка со снимком узкая (317–427 px), а бирка на ней
     оставалась «десктопной»: 185 px и 29–31% площади снимка. Здесь она
     ужимается по содержимому (имя мельче, срок записан коротко) и уходит
     левее — за край карточки, на пустое поле. Низ бирки при этом не
     двигается, поэтому вся вертикальная раскладка экрана не меняется. */
  @media (max-width: 1000px){
    .index-tag{ left: -34px; width: clamp(150px, 46%, 168px); padding-right: 12px; }
    .index-tag-nm{ font-size: 18px; }
    .index-tag-price{ font-size: 19px; line-height: 1.15; }
    .index-tag-sub{ line-height: 1.3; }
    .index-term-long{ display: none; }
    .index-term-short{ display: inline; }
  }

  /* ─── 18.3 рукописная строка не сталкивается с биркой ───────────────────
     Было: низ бирки 810,4 и верх строки 814,0 — зазор 3,6 px, который
     съедало качание бирки, и строки склеивались. Строка уходит вправо и
     вниз: между ней и биркой почти три десятка пикселей воздуха. */
  .index-pull{ margin-top: 56px; text-align: right; }
}

/* ─── 18.4 снимок героя получил приписку слева вверху ─────────────────────
   Дословная просьба Дарьи: «приписки слева вверху "в наличии, возможен
   повтор, повтор невозможен" ... хотелось бы у себя такое же сделать».
   На главном снимке её не было, статус прятался мелкой строкой в бирке. */
.index-photo-card{ position: relative; }
/* 8 px паспарту + 10 px поля внутри снимка — ровно так же, как чип стоит
   на карточках каталога, чтобы приписка везде выглядела одной и той же */
.index-photo-badge{ position: absolute; left: 18px; top: 18px; z-index: 2; }

/* ─── 18.5 нить: на телефоне своя, низкая и с двумя концами ───────────────
   Широкая нить занимала 88 px высоты и обрывалась плоскими торцами с обеих
   сторон: связку с клубком на телефоне не рисуем, и шнурок висел ни к чему
   не привязанный. Мобильная версия вдвое ниже, слева у неё петелька-хвостик,
   справа маленький клубок — тот самый, из которого нить и тянется. */
.index-thread--m{ display: none; }

/* ═══════════════ 18.6 ТЕЛЕФОН: первый экран продаёт ═══════════════════════
   Было при 390×844: кнопка «Смотреть каталог» на 949 px — на 105 px ниже
   сгиба; видно только фото и бирку, абзац разрезан посередине строки.
   Стало: имя — нить — игрушка с ценой — кнопки, всё выше сгиба, а сгиб
   приходится на промежуток между абзацем и строкой условий. */
@media (max-width: 740px){

  /* шапка на телефоне общая для всех страниц — раздел 10; своих правок
     у главной здесь больше нет (сведено 2026-08-12) */
  .index-nav-long{ display: none; }
  .index-nav-short{ display: inline; }

  /* — нить: низкая версия — */
  .index-thread--d{ display: none; }
  .index-thread--m{ display: block; width: min(100%, 358px); margin: 0 0 6px; }

  /* — верхний блок плотнее: имя тише на пару пунктов, воздух убран — */
  .index-hero .overline{ margin-bottom: 2px; }
  .index-h1{ font-size: clamp(38px, 11.6vw, 52px); }

  /* — снимок меньше: 369 px карточки съедали 44% высоты экрана — */
  .index-photo{
    width: min(100%, 300px);
    margin-top: 10px;
    margin-bottom: 84px;       /* место бирке, которая свисает с угла */
  }
  .index-photo-badge{ left: 16px; top: 16px; }

  /* — бирка свисает с нижнего-левого УГЛА, а не лежит на игрушке —
     Было: 22% площади снимка закрыто, и закрыто самое интересное — низ
     плаща, колокольчик и нога. Стало: бирка уходит за левый край карточки
     и вниз, на снимок заходит только пустой угол фона. */
  .index-tag{
    /* бирка свисает влево за карточку, но не за поле страницы: на 360 px
       снимок стоит ближе к краю, и прежние -30 px срезали её левые углы
       о край экрана. 166px − 50vw — это ровно та точка, где левый бок бирки
       встаёт в 10 px от края при любой ширине; на 390 px и шире выбирается
       прежние −30 px, то есть привычный вид не меняется */
    left: max(-30px, min(2px, calc(168px - 50vw))); bottom: -80px;
    width: clamp(150px, 58%, 172px);
    padding: 10px 24px 12px 12px;   /* дырка под нить теперь справа */
    transform: rotate(3.2deg);
    transform-origin: calc(100% - 19px) -20px;
    animation-name: index-tag-sway-m;
  }
  .index-tag::before{ left: auto; right: 15px; top: 12px; }
  /* короткая завязка вместо длинной нити: длинная упиралась в плащ игрушки
     и заканчивалась в пустоте — теперь бирка просто привязана к карточке */
  .index-tag::after{ left: auto; right: 18px; top: -18px; height: 34px; }
  .index-tag-nm{ font-size: 18px; }
  .index-tag-price{ font-size: 19px; line-height: 1.15; }
  /* строка срока помещается в одну: «ДНЕЙ» больше не остаётся сиротой */
  .index-tag-sub{ margin-top: 3px; font-size: 12.5px; letter-spacing: .02em; line-height: 1.3; }
  .index-term-long{ display: none; }
  .index-term-short{ display: inline; }
  .index-tag-btn{ margin-top: 8px; padding: 8px 10px; font-size: 14px; }

  /* — кнопки в один ряд: столбиком они занимали 111,6 px вместо 49 — */
  .index-cta{
    order: 5;                       /* сразу под игрушкой, до объяснения */
    display: grid; grid-template-columns: 1fr 1fr;
    gap: 10px; margin-top: var(--sp-2);
  }
  .index-cta .btn{ padding-inline: 12px; font-size: 15px; }

  /* абзац короче ровно настолько, чтобы уместиться в две строки: при трёх
     нижний край экрана разрезал последнюю строку пополам. Отступ до условий
     увеличен намеренно — в этот промежуток и приходится сгиб. */
  .index-lede{ order: 6; margin-top: var(--sp-2); text-wrap: balance; }
  .index-terms{ order: 7; margin-top: 26px; }
}

/* ─── 18.6.1 узкий телефон: шапка в две строки, а не в три ────────────────
   При 360 px (одна из самых частых ширин на андроиде) логотип, корзина и
   меню требовали 332 px при доступных 328 — кнопка корзины переносилась на
   отдельную строку, и шапка вырастала со 126 до 180 px, съедая четверть
   первого экрана. Логотип-бирка ужимается на 15 px: подпись и название
   мельче на пол-пункта, поля плотнее. Правило общее для всех страниц —
   шапка на сайте одна, и разной высоты на разных страницах быть не должно. */
@media (max-width: 400px){
  .logo{ padding: 6px 10px 6px 8px; gap: 9px; }
  .logo-name{ font-size: 13.5px; }
  .logo-sub{ font-size: 11px; letter-spacing: .01em; }
}

/* ─── 18.7 самые узкие экраны: сетка не вылезает за край ──────────────────
   При 320 px две кнопки в ряд требуют 305 px при колонке 288 — колонка
   растягивалась, и вместе с ней уезжали вправо фотография, абзац и имя
   бренда. Здесь кнопки снова встают друг под друга, а имя набирается
   мельче: «comfortable» — самое длинное неразрывное слово страницы. */
@media (max-width: 359px){
  .index-cta{ grid-template-columns: 1fr; }
  .index-h1{ font-size: min(10.6vw, 52px); }
  /* бирка не свисает за край экрана: при 320 px её левый край уходил на
     −20 и кнопка «В корзину» обрезалась. Ноль вместо −12: при повороте
     бирки нижний угол забирает ещё около 6 px влево */
  .index-tag{ left: 2px; }
}

/* качание мобильной бирки: она подвешена за правый верхний угол, поэтому
   и качается в другую сторону, чем широкая. Только transform. */
@keyframes index-tag-sway-m{
  from{ transform: rotate(1.4deg); }
  to  { transform: rotate(4.6deg); }
}

/* ═════════════════════════════════════════════════════════════════════════
   19. ОТЗЫВЫ — вторая правка по разбору (2026-08-12)
   Дописано в конец файла: ничего выше не переписано, :root не тронут,
   свои селекторы с приставкой reviews-. Движение — только transform
   и opacity, бесконечных анимаций не добавлено.

   Что чинится:
     19.1 контраст масштабов: заголовок страницы был ростом с цифру в бирке;
     19.2 висячее слово «доехала» отдельной строкой в лиде;
     19.3 нить обрывалась в воздухе, а бирка висела без опоры;
     19.4 самолётик в кнопках, которые открывают телеграм;
     19.5 системные эмодзи в чужих словах кричали громче фотографий;
     19.6 телефон: снимки-доказательства были ростом 117×150;
     19.7 телефон: кнопка каталога стояла по центру, всё прочее — по левому краю;
     19.8 планшет 741–860 px: шапка не помещалась в окно.
   ═══════════════════════════════════════════════════════════════════════ */

/* ─── 19.1 КОНТРАСТ МАСШТАБОВ ─────────────────────────────────────────────
   Было: h1 страницы 44 px и число «24» в служебной бирке — тоже 44 px.
   Титул раздела равнялся цифре из подписи, и весь экран лежал в одной
   средней зоне: смотреть было не на что. Стало: заголовок до 60 px (на
   главной имя бренда 68 — иерархия страниц сохраняется), число — до 32.
   Каталог и бинго получают ту же величину, чтобы страницы остались одной
   семьёй; на телефоне значения совпадают со старыми, первый экран
   каталога не сдвинулся. */
.reviews-hero h1{ font-size: clamp(34px, 5.4vw, 60px); }

@media (min-width: 741px){
  .catalog-top h1, .bingo-top h1{ font-size: clamp(34px, 5.4vw, 60px); }
}

.reviews-num b{ font-size: clamp(24px, 2.6vw, 32px); }

/* ─── 19.2 ЛИД БЕЗ ВИСЯЧЕГО СЛОВА ─────────────────────────────────────────
   «…когда посылка / доехала.» — вторая строка из одного слова. Колонка
   ужата до 36 знаков, строки уравнены. Только на широком экране: на
   телефоне лид и так во всю ширину. */
@media (min-width: 981px){
  .reviews-hero .lead{ max-width: 36ch; text-wrap: balance; }
}

/* ─── 19.3 НИТЬ ДОХОДИТ ДО БИРКИ, БИРКА ВИСИТ НА НИТИ ─────────────────────
   Было: нить кончалась круглым колпачком посреди пустого места, а бирка с
   числами стояла по центру колонки — выше нити и с четырьмя сотнями
   пикселей пустоты под собой. Читалось как недоделка. Стало: нить уходит
   за левый край бирки, в углу бирки — точка-гвоздик, та же, что держит
   пункты навигации, и высота бирки считается по нити (--rv-hang задаёт
   скрипт страницы; не сработал — остаётся запасное значение отсюда). */
.reviews-cord-far{ display: none; }
/* лента шла вплотную к нити по правилу «.reviews-cord + .reviews-strip»;
   между ними появился второй рисунок нити, и соседство разорвалось —
   возвращаем его правому отрезку */
.reviews-cord-far + .reviews-strip{ margin-top: 0; }

@media (min-width: 981px){
  .reviews-hero{ align-items: start; }
  .reviews-hero-main{ position: relative; }

  /* правый отрезок нити: от края ленты (она не шире 560 px) до бирки, и
     ещё 30 px за её левый край — конец уходит под бумагу, а не обрывается.
     Высоту берёт из --rv-hang, который считает скрипт страницы: это ровно
     та высота, на которой идёт нить над снимками. */
  .reviews-cord-far{
    display: block;
    position: absolute;
    left: min(100%, 558px);
    /* Ширину задаём числом, а не парой left/right: рисунок — замещаемый
       элемент, при width:auto он берёт свой размер из viewBox (200×40) и
       правый край улетает мимо бирки.
       Конец нити приходит ровно на гвоздик в углу бирки: пустить его дальше,
       под бумагу, нельзя — нить идёт на 2 px выше верхней кромки и торчала
       бы над ней огрызком в три пикселя. */
    width: calc(100% - min(100%, 558px) + clamp(24px, 3.6vw, 46px) + 2px);
    right: auto;
    top: calc(var(--rv-hang, clamp(294px, 30vw, 320px)) - 2px);   /* −2: бирка висит на 2 px ниже нити */
    height: 40px;
    overflow: visible;
    pointer-events: none;
  }
  .reviews-cord-far[hidden]{ display: none; }
  /* короткий кусок дорисовывается первым — дальше нить уходит влево,
     к снимкам: получается один жест, а не два отдельных */
  .reviews-cord-far .reviews-draw{ animation-duration: .3s; animation-delay: .05s; }

  .reviews-facts{
    position: relative;
    margin-top: var(--rv-hang, clamp(294px, 30vw, 320px));
  }
  .reviews-facts::before{           /* гвоздик, на котором держится бирка */
    content: '';
    position: absolute; left: -4.5px; top: -4.5px;
    width: 9px; height: 9px;
    border-radius: 50%;
    background: var(--ball);
    box-shadow: 0 1px 2px rgba(122,74,40,.35);
    pointer-events: none;
  }
}

/* ─── 19.3-бис ЛЕНТА ДЕРЖИТ СВОЮ ВЫСОТУ ───────────────────────────────────
   Место под ленту зарезервировано пропорцией (aspect-ratio), но строка
   сетки набиралась по картинке: снимок 450×800 растягивал ленту на 80 px
   выше зарезервированного, и всё, что ниже, прыгало вниз в момент загрузки
   фотографии. minmax(0,1fr) прибивает строку к высоте самой ленты —
   пропорция снова главнее содержимого, скачка нет. */
.reviews-strip{ grid-template-rows: minmax(0, 1fr); }

/* ─── 19.4 САМОЛЁТИК НА КНОПКАХ В ТЕЛЕГРАМ ────────────────────────────────
   Дарья отдельно отметила в ТЗ «открытие телеграма по кнопке» — значит по
   кнопке должно быть видно, куда она ведёт. Рисунок обводкой 2 px, как у
   корзины в шапке; зазор до текста берётся у самой .btn (gap:10px). */
.reviews-tg-ic{ flex: none; }

/* ─── 19.5 ЭМОДЗИ В ЧУЖИХ СЛОВАХ ──────────────────────────────────────────
   Слова покупателя дословны, но системный 🌸 и 😊 — самые насыщенные
   пиксели страницы и чужие тёплой палитре (тот же разбор, что в 17.1 для
   каталога). Не вырезаем, а приглушаем: чуть мельче и прозрачнее. */
.reviews-emo{ font-size: .86em; opacity: .8; vertical-align: -.04em; }

/* строка-подсказка под лентой: на телефоне она ломалась на две строки так,
   что во второй оставалось одно слово «все.» — уравниваем длину строк */
.reviews-strip-note{ text-wrap: balance; }

/* ─── 19.6 ТЕЛЕФОН: СНИМКИ, КОТОРЫЕ ВИДНО ─────────────────────────────────
   Было: три снимка по 117×150 px, лицо игрушки — тридцать пикселей. Вся
   ценность страницы в доказательстве, а доказательство не читалось.
   Стало: два снимка по ~175×225. Третий убран, а не сжат: лучше два
   разборчивых, чем три никаких. */
@media (max-width: 560px){
  .reviews-strip{
    grid-template-columns: repeat(2, minmax(0, 1fr));
    aspect-ratio: 1.55;
  }
  .reviews-snap:nth-child(3){ display: none; }
}

/* ─── 19.7 ТЕЛЕФОН: КНОПКА КАТАЛОГА ПО ЛЕВОМУ КРАЮ ────────────────────────
   Была ссылка-пунктир, выключенная по центру колонки, — единственный
   элемент экрана не по левому краю. Теперь это главная кнопка раздела и
   занимает всю ширину, как остальные главные кнопки на телефоне. */
@media (max-width: 740px){
  .reviews-actions .btn{ width: 100%; margin-inline: 0; }
}

/* ─── 19.8 ПЛАНШЕТ 741–930 px: ШАПКА НЕ ВЛЕЗАЛА В ОКНО ────────────────────
   На ширине 768 px (айпад Дарьи) документ был шире окна: логотип, пункты
   меню и корзина не помещались в строку и съедали правое поле целиком, а
   кнопка корзины упиралась в край экрана. С появлением пятого пункта
   «Как заказать» не хватало уже 80 px, и полоса разъезжалась вплоть до
   930 px. Ниже 741 px шапка перестроена в две строки и всё в порядке.
   Верхняя граница поднята с 930 до 965 px (проверено замером): при 940 px
   корзина всё ещё вылезала на 17 px, свободно становится только с 966.
   Что делаем в этой полосе: поджимаем промежутки, у корзины оставляем
   значок без слова (ровно как на телефоне, подпись для голосового чтения
   на месте) и берём короткую подпись «Заказать» — она уже заготовлена в
   разметке для узких экранов. Ничего не выбрасываем. Правило общее для
   всех страниц: шапка одна на весь сайт. */
@media (min-width: 741px) and (max-width: 965px){
  .head-inner{ gap: 8px; }
  .logo{ padding: 8px 12px 8px 10px; }
  .logo-sub{ letter-spacing: .06em; }
  .nav{ gap: 5px; }
  .nav-link{ padding-inline: 4px; }
  .nav .index-nav-long{ display: none; }
  .nav .index-nav-short{ display: inline; }
  .cart-btn{ padding: 0 14px; }
  .cart-word{ display: none; }
}

/* ═════════════════════════════════════════════════════════════════════════
   18. БИНГО — доводка по разбору арт-критика (2026-08-12)

   Все правила ниже относятся ТОЛЬКО к странице bingo.html: она помечена
   классом .bingo-page на <body>. Ни одно правило выше не переписано, :root
   не тронут, новых токенов нет. Движение — только transform и opacity.

   Почему через класс страницы, а не правкой правил на месте: над файлом
   параллельно работают другие страницы, и правка в середине их сломает.
   Блоки 18.1 и 18.2 (шапка) по смыслу общие для всего сайта — когда
   остальные страницы дойдут до той же доводки, их можно поднять из-под
   .bingo-page наверх одним движением.
   ═══════════════════════════════════════════════════════════════════════ */

/* Блоки 18.1 и 18.2 (шапка) подняты в базовые правила разделов 5 и 10
   (2026-08-12): шапка на сайте одна, страничных переопределений у неё больше нет. */


/* ─── 18.3 НИТЬ ПРОГРЕССА: клубок едет и наматывает ───────────────────────
   Было: клубок стоял концевой фишкой у правого края пустой дорожки — при
   «0 из 25» это читалось как «всё пройдено». Стало: клубок лежит на дорожке
   и едет по ней слева направо ровно на долю пройденного. Сдвиг — transform
   по переменной, длину пути в пикселях подставляет скрипт. */
.bingo-page .bingo-bar{ overflow: visible; }
.bingo-page .bingo-clew{
  position: absolute; left: 0; top: 50%; z-index: 2;
  width: 18px; height: 18px; margin: -9px 0 0 0;
  transform: translate(calc(var(--p, 0) * var(--travel, 0px)), -50%) scale(var(--clew-sc, 1));
  transition: transform var(--t-slow) var(--ease);
}
.bingo-page .bingo-clew.is-full{ --clew-sc: 1.35; }

/* ─── 18.4 БИРКА ЗВАНИЯ: висит на нити прогресса, лежит на полотне ────────
   Было: шнурок бирки уходил на 26 px в пустую бумагу и обрывался, а на
   телефоне бирка вообще парила в зазоре между строкой прогресса и полем.
   Стало: шнурок дотягивается до дорожки прогресса и завязан на ней узлом,
   бирка легла на верхний правый угол полотна с небольшим нахлёстом.
   Заодно бирка стала однострочной — это те самые 24 px, которые она
   съедала у поля. */
.bingo-page .bingo-stage{ padding-top: 20px; }
.bingo-page .bingo-rank-tag{
  top: 4px; right: 12px;
  max-width: min(74%, 420px);
  padding: 7px 15px 8px 27px;
}
.bingo-page .bingo-rank-cap{ display: inline; }
.bingo-page .bingo-rank-nm{ display: inline; margin-top: 0; margin-left: 7px; }
.bingo-page .bingo-rank-tag::after{ height: 34px; }
/* узел, которым шнурок привязан к дорожке прогресса */
.bingo-page .bingo-rank-cap::before{
  content:''; position:absolute; left:9px; top:-32px;
  width:9px; height:9px; border-radius:50%;
  background: var(--ball);
  box-shadow: 0 1px 2px rgba(122,74,40,.38), inset -1px -1px 0 rgba(122,60,30,.3);
}

/* ─── 18.5 ПОЛОТНО ЦЕЛИКОМ, А НЕ ПОЛОВИНА ────────────────────────────────
   Подпись резервировала место под вторую строку, которой нет ни у одного из
   25 имён, — это 95 px пустоты на поле. Плюс само поле было шире, чем нужно
   игре: клетка 141 px против 126 px. Вместе полотно похудело почти на
   200 px, и в первый экран попадает вчетверо больше, чем раньше. */
.bingo-page .bingo-nm{ min-height: calc(1.22em + 10px); }
@media (min-width: 981px){
  /* ширину задаём всему столбцу, а не одному полотну: иначе дорожка
     прогресса тянулась бы на 72 px дальше поля и висела в воздухе */
  .bingo-page .bingo-stage-block{ max-width: 690px; }
  /* Воздух между заголовком и полотном: каждый десяток пикселей здесь — это
     кусок нижнего ряда, которого человек не увидит. Двухколоночную шапку
     (правило справа от заголовка) пробовал — не дала ничего: строка правила
     в узкой колонке рвётся на три и съедает ровно то, что экономит. */
  .bingo-page .bingo-top{ padding-bottom: 0; }
  .bingo-page .bingo-section{ padding-top: 0; }
  .bingo-page .bingo-stage{ margin-top: var(--sp-1); }
}

/* ─── 18.6 ШВЫ: одна система пунктира, а не две ───────────────────────────
   Пунктиром на этой странице говорится ровно одно: «отмечено». Разлиновка
   полотна стала тем, чем и должна быть, — сплошной волосяной линией, и
   теперь она смыкается в решётку, а не рассыпается штрихами. */
.bingo-page .bingo-cell::before,
.bingo-page .bingo-cell::after{ opacity: 1; }
.bingo-page .bingo-cell::after{
  top: 0; bottom: 0; right: calc(var(--bgap) / -2 - 1px);
  border-right: 1px solid rgba(140,100,64,.14);
}
.bingo-page .bingo-cell::before{
  left: 0; right: 0; bottom: calc(var(--bgap) / -2 - 1px);
  border-bottom: 1px solid rgba(140,100,64,.14);
}

/* ─── 18.6б ОТМЕТИТЬ — НЕ ЗНАЧИТ СПРЯТАТЬ ────────────────────────────────
   Сердечко-отметка съедало игрушку: на телефоне оно закрывало клетку почти
   целиком, на широком экране — голову и плечи. А человек пришёл сюда именно
   на игрушки смотреть. Сердечко ужалось и переехало в нижний правый угол —
   единственное место, где на всех 25 кадрах пусто; вуаль отмеченной клетки
   ослаблена втрое, чтобы отмеченный ряд не выглядел выцветшим рядом с
   неотмеченным. Отметку по-прежнему видно: рамка клетки, наклон и сердечко. */
.bingo-page .bingo-mark{
  width: 26%; max-width: 30px;
  right: 4%; top: auto; bottom: 4%;
  transform-origin: 80% 80%;
}
.bingo-page .bingo-ph::after{ background: rgba(190,95,53,.12); }
.bingo-page .bingo-cell.is-line .bingo-ph::after{ background: rgba(91,112,82,.15); }
@media (max-width: 740px){
  .bingo-page .bingo-mark{ width: 30%; max-width: 20px; }
}

/* ─── 18.7 НИТКА СОБРАННОЙ ЛИНИИ ─────────────────────────────────────────
   Нитка опущена на низ фотографий (это делает скрипт) и получила тёмный
   подштрих: теперь она лежит на бумаге под игрушками, а не царапает их. */
.bingo-page .bingo-thread::after{
  content:''; position:absolute; left:3px; right:3px; bottom:-1px; height:1px;
  border-radius: 1px;
  background: rgba(96,58,28,.30);
}

/* ─── 18.8 ПОЛОСА ОТВЕТА ПОД ПОЛОТНОМ ────────────────────────────────────
   На телефоне это единственное место, где ответ на тап виден без прокрутки.
   На широком экране его роль играет панель справа, поэтому полоса там не
   нужна — см. конец раздела. */
/* Длинные имена («Шестая из „Маленьких кошмаров“») тянули полосу шире экрана
   и заодно раздували всё поле: строка стоит в сетке, а сетка растёт под самый
   широкий элемент. Поэтому и полоса, и её столбец умеют сжиматься до нуля, а
   текст обрезается многоточием. */
.bingo-page .bingo-stage-block{ min-width: 0; }
.bingo-echo{
  display: flex; align-items: center; gap: var(--sp-2);
  min-width: 0; max-width: 100%; overflow: hidden;
  min-height: 56px;
  margin-top: var(--sp-2);
  padding: 6px 8px 6px 16px;
  background: linear-gradient(165deg, var(--tag), var(--tag-2));
  border-radius: var(--r-md);
  box-shadow: var(--sh-1), inset 0 1px 0 rgba(255,248,232,.7);
}
.bingo-echo-txt{ min-width: 0; flex: 1 1 0; }
.bingo-echo-nm{
  font-family: var(--font-display); font-weight: 700; font-size: 15px; line-height: 1.2;
  color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.bingo-echo-sub{
  margin-top: 2px;
  font-size: 13.5px; font-weight: 700; line-height: 1.25; color: var(--tag-ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.bingo-echo-price{ color: var(--clay-ink); font-weight: 800; }
.bingo-echo-price--ask{ color: var(--ink-soft); font-weight: 700; }
.bingo-echo-btn{ flex: none; min-height: 44px; white-space: nowrap; }
.bingo-echo-btn[hidden]{ display: none; }
/* пока не тыкали: строка объясняет, что делать, и не притворяется товаром */
.bingo-echo[data-empty] .bingo-echo-nm{
  font-family: var(--font-text); font-weight: 700; font-size: 14px; color: var(--tag-ink);
}
.bingo-echo[data-empty] .bingo-echo-sub{ color: var(--ink-soft); font-weight: 600; }

/* ─── 18.9 ПАСПАРТУ ВМЕСТО ЗОНЫ ЗАГРУЗКИ ─────────────────────────────────
   Пунктирная рамка вокруг фотографии в панели выбора выглядела как пустое
   поле «перетащите файл». Взято паспарту, которое уже работает на отзывах. */
.bingo-page .bingo-pick-ph{
  padding: 6px;
  background: var(--card);
  border: var(--hair);
}
.bingo-page .bingo-pick-ph img{ display: block; border-radius: 9px; }

/* ─── 18.10 ПЛАШКА ПОЗДРАВЛЕНИЯ — НАВЕРХ ─────────────────────────────────
   В момент триумфа она закрывала собой два нижних ряда поля: человек читал
   «смотрите, кого вы собрали», а собранного не видел. Теперь она приходит
   сверху, под шапку, и поле остаётся целиком на виду. */
.bingo-page .toast{
  top: 118px; bottom: auto;
  /* ширину задаём явно: у плавающей плашки с left:50% доступного места
     ровно полэкрана, и на телефоне она сама сжималась в столбик из трёх
     строк высотой почти в сотню пикселей */
  width: min(92vw, 460px);
  transform: translate(-50%, -22px);
}
.bingo-page .toast.is-on{ transform: translate(-50%, 0); }

/* ─── 18.11 ТЕЛЕФОН ──────────────────────────────────────────────────────
   Главная правка: отметить игрушку больше не значит спрятать её. Сердечко
   ужалось до 20 px и переехало в нижний правый угол — единственное место,
   где на всех 25 фотографиях пусто; вуаль отмеченной клетки ослаблена втрое,
   чтобы отмеченный ряд не выглядел выцветшим рядом с неотмеченным. */
@media (max-width: 740px){
  /* фотографии почти касались края листа — полотну вернули поля */
  .bingo-page .bingo-mat{ padding: 10px; }
  /* Бирка звания на телефоне стоит в потоке над полотном (так решено раньше:
     в две строки поверх поля она закрывала верхний ряд). Оставляем как есть,
     но кладём её углом НА полотно с нахлёстом 12 px — иначе она парит в
     зазоре и не выровнена ни по чему. Шнурка тут нет, значит и узла нет.
     Длинные звания на узком экране в строку не помещаются — две строки. */
  .bingo-page .bingo-rank-cap{ display: block; }
  .bingo-page .bingo-rank-nm{ display: block; margin-left: 0; margin-top: 1px; }
  .bingo-page .bingo-rank-tag{
    top: auto; right: auto;      /* в потоке «right» сдвигал бирку влево от края */
    max-width: 74%;
    margin: 0 0 -12px 0;
    padding: 6px 13px 8px 24px;
    z-index: 4;
  }
  .bingo-page .bingo-rank-cap::before{ display: none; }

  /* Место под поле. Полотно с полосой ответа обязано уместиться в один экран
     телефона: иначе человек тыкает в игрушку и не видит, кто это. Каждая
     строчка ниже отнимает у вводной части несколько пикселей в пользу игры. */
  .bingo-page .bingo-top{ padding-top: 6px; }
  .bingo-page .bingo-lead{ margin-top: 6px; }
  .bingo-page .bingo-section{ padding-top: 0; }
  /* на телефоне бирка стоит в потоке, место сверху под неё не резервируем */
  .bingo-page .bingo-stage{ margin-top: 8px; padding-top: 0; }
  .bingo-page .toast{ top: 96px; }
}

/* на широком экране ответ на тап показывает панель справа — полоса лишняя */
@media (min-width: 981px){
  .bingo-echo{ display: none; }
}

/* ─── 18.12 БЕЗ ДВИЖЕНИЯ ─────────────────────────────────────────────────
   Клубок остаётся на своём месте по прогрессу, но едет мгновенно. */
@media (prefers-reduced-motion: reduce){
  .bingo-page .bingo-clew{ transition: none; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   21. СТРАНИЦА «КАК ЗАКАЗАТЬ»
   ТЗ Дарьи называет «заказы» отдельным разделом наравне с каталогом и
   отзывами (docs/tz-darya.md), а раздел жил секциями на трёх страницах —
   пункта меню и своего адреса у него не было. Страница собрана из уже
   существующих деталей сайта: панели, бирка, шаги, карточки условий.
   Ничего нового в :root не заводится, движение — только opacity и transform.
   ══════════════════════════════════════════════════════════════════════════ */

.order-hero{
  display:grid; grid-template-columns: minmax(0,1.35fr) minmax(0,.85fr);
  gap: clamp(20px, 3vw, 46px); align-items:start;
}
.order-hero-main h1{ margin-top: 6px; }
.order-hero-main .lead{ margin-top: 14px; max-width: 46ch; }

/* нить рисуется один раз при загрузке — как на других страницах */
.order-thread{ display:block; width:min(100%, 420px); height:auto; margin: 16px 0 4px; }
.order-draw{ stroke-dasharray: 100 100; stroke-dashoffset: 100; animation: ct-order-draw 1.5s var(--ease-out) .15s forwards; }
@keyframes ct-order-draw{ to{ stroke-dashoffset: 0; } }

.order-actions{ display:flex; flex-wrap:wrap; gap: var(--sp-2); margin-top: var(--sp-2); }

.order-facts{ display:grid; gap: 12px; }
.order-facts-list{ list-style:none; display:grid; gap: 12px; }
.order-facts-list li{ display:grid; gap:1px; }
.order-facts-list b{
  font-family: var(--font-display); font-weight:700;
  font-size: clamp(19px, 1.6vw, 23px); line-height:1.15; color: var(--tag-ink);
}
.order-facts-list span{ font-size: var(--fs-small); line-height:1.4; color: var(--tag-ink); }
.order-rule{ border:0; border-top: 2px dashed rgba(190,95,53,.4); margin: 2px 0; }
.order-hand{ color: var(--clay-ink); }

/* ссылки в трёх шагах стоят на одной базовой линии: карточки одной высоты,
   а текста в них разное количество — прижимаем ссылку к низу карточки,
   иначе средняя проваливается на пару десятков пикселей (2026-08-12) */
.order-step-link{ margin-top: auto; padding-top: 12px; align-self:flex-start; }
.index-step{ display:flex; flex-direction:column; align-items:flex-start; }

/* частые вопросы: раскрывающиеся строки на бумаге */
.order-faq{ display:grid; gap: 10px; }
.order-q{
  background: var(--card); border: var(--hair); border-radius: var(--r-md);
  box-shadow: var(--sh-1); overflow:hidden;
}
.order-q summary{
  display:flex; align-items:center; gap:12px;
  min-height: var(--tap); padding: 14px clamp(14px,2vw,20px);
  font-family: var(--font-display); font-weight:700;
  font-size: clamp(15.5px, 1.2vw, 17.5px); line-height:1.3; color: var(--ink);
  cursor:pointer; list-style:none;
  transition: color var(--t-fast) var(--ease);
}
.order-q summary::-webkit-details-marker{ display:none; }
.order-q summary::after{
  content:''; flex:none; margin-left:auto;
  width:11px; height:11px; border-right:2.6px solid var(--clay);
  border-bottom:2.6px solid var(--clay); border-radius:2px;
  transform: rotate(45deg) translate(-2px,-2px);
  transition: transform var(--t) var(--ease);
}
.order-q[open] summary::after{ transform: rotate(225deg) translate(-2px,-2px); }
.order-q summary:hover{ color: var(--clay-ink); }
/* summary не входит в общий список фокуса (:where(a, button, …)) — рамку
   ему надо дать отдельно, той же пунктирной нитью, что и всему сайту */
.order-q summary:focus-visible{ outline: 3px dashed var(--thread); outline-offset: -3px; }
.order-q p{
  padding: 0 clamp(14px,2vw,20px) 16px;
  font-size: var(--fs-small); line-height:1.65; color: var(--ink-2);
}

.order-end{
  display:flex; flex-wrap:wrap; align-items:center; justify-content:space-between;
  gap: var(--sp-3);
}
.order-end > div:first-child{ flex:1 1 340px; }
.order-end .lead{ margin-top: 8px; color: var(--tag-ink); }
.order-end-btns{ display:flex; flex-wrap:wrap; gap: var(--sp-2); }

@media (max-width: 900px){
  .order-hero{ grid-template-columns: 1fr; }
}
@media (max-width: 740px){
  /* телефон: бирка с фактами идёт двумя колонками — четыре строки подряд
     съедали целый экран до первого шага */
  .order-facts-list{ grid-template-columns: repeat(2, minmax(0,1fr)); gap: 14px 12px; }
  .order-thread{ margin: 12px 0 2px; }
  .order-actions .btn, .order-end-btns .btn{ width: 100%; }
  .order-end{ flex-direction: column; align-items: stretch; }
  .order-end-btns{ width: 100%; }
}
@media (prefers-reduced-motion: reduce){
  .order-draw{ animation: none; stroke-dasharray: none; stroke-dashoffset: 0; }
}

/* ─── 21.1 САМЫЕ УЗКИЕ ТЕЛЕФОНЫ: шапка в одну строку ──────────────────────
   Подпись под названием раньше ужимали до 8,5 px, чтобы логотип-бирка и
   корзина уместились в строку. Читать её при этом было нельзя, а ради
   строки жертвовать разборчивостью не стоит: кегль вернули на 11 px, а
   место отыграли разрядкой — она съедала больше, чем сами буквы.
   Ниже 340 px убираем разрядку совсем: бирка становится на 16 px уже,
   и кнопка корзины остаётся рядом с логотипом, а не съезжает под него. */
@media (max-width: 340px){
  .logo-sub{ font-size: 10.5px; letter-spacing: 0; }
}

/* ═════════════════════════════════════════════════════════════════════════
   21. СВЕДЕНИЕ ПОВТОРЯЮЩИХСЯ БЛОКОВ (2026-08-12)
   Дописано в конец файла: ничего выше не переписано, :root не тронут.
   Движение — только transform и opacity.
   ═══════════════════════════════════════════════════════════════════════ */

/* ─── 21.1 узкий телефон: полка фильтров в две строки, пока не прилипла ───
   При 360 px лента бирок получала 229 px из 328: справа от неё стоит
   галочка «в наличии», и вторая бирка обрывалась вместе со своим числом —
   счётчик «2» уезжал под растушёвку и стрелку.
   Ниже 401 px галочка переезжает на свою строку, лента получает всю ширину,
   и «Культ ягнёнка 2» помещается целиком. Как только полка прилипает к
   верху экрана, она снова складывается в одну строку: там каждый пиксель
   отнят у фотографий, а числа человек уже прочитал выше. */
@media (max-width: 400px){
  .catalog-filters:not(.is-pinned) .catalog-filters-in{ flex-wrap: wrap; row-gap: 8px; }
  /* база 0, а не auto: иначе лента считает своей шириной всю длину бирок
     (больше километра) и стрелка-подсказка уезжает на отдельную строку */
  .catalog-filters:not(.is-pinned) .catalog-chips{ flex: 1 1 0; min-width: 0; }
  .catalog-filters:not(.is-pinned) .catalog-tools{
    flex: 1 0 100%;
    padding-left: 0; border-left: 0;
    display: flex; justify-content: flex-start;
  }
  .catalog-filters:not(.is-pinned) .catalog-switch{ flex: none; }
}

/* ─── 21.2 прилипшая полка на широком экране: бирки переносятся, а не уезжают
   под маску ───────────────────────────────────────────────────────────────
   Счётчики вернулись на бирки и в прилипшем виде (иначе полка сама себя
   переименовывала при прокрутке), и в одну строку девять миров с числами
   больше не помещаются: три последних уходили под растушёвку, а мышь
   горизонтальную ленту не крутит — фильтр становился недоступен.
   Здесь лента переносится на вторую строку: всё видно и всё нажимается.
   Условие — не только ширина, но и наличие мыши: на телефоне и планшете
   лента прокручивается пальцем, там перенос не нужен и только съел бы
   высоту (на 760 px он давал третью строку). */
@media (min-width: 900px) and (hover: hover) and (pointer: fine){
  .catalog-filters.is-pinned .catalog-chips{
    flex-wrap: wrap; overflow-x: visible;
    row-gap: 7px;
    padding-right: 0;
    -webkit-mask-image: none;
            mask-image: none;
  }
  .catalog-filters.is-pinned .catalog-filters-in{ align-items: flex-start; }
  .catalog-filters.is-pinned .catalog-tools{ align-self: center; }
}
