/* ============================================================
   J-Park — раздел «Каталог»
   Только то, что специфично для каталога. Палитра, типографика,
   шапка/футер, .section / .wrap / .card / .btn / .deflist /
   [data-reveal] — всё общее приезжает из site.css, который
   подключается ПЕРЕД этим файлом.
   ============================================================ */

/* ---------- шапка раздела ----------
   Общее (.section--head, .crumbs) — в site.css; здесь только заголовок
   каталога: он короче, поэтому мера строки уже. */
.section--head .h1{max-width:16ch}
/* цифры-итоги в CTA стоят после лида и кнопок — им нужен воздух сверху */
.section .deflist{margin-top:clamp(36px,5vh,64px)}

/* ============================================================
   Панель фильтров
   Каркас (.bar / .bar__in / .chips / .chip) — в site.css;
   здесь только сортировка и счётчик каталога.
   ============================================================ */
.bar__sort{display:flex;align-items:center;gap:10px;margin-left:auto}
.bar__sort label{
  font-family:var(--f-mono);font-size:10px;letter-spacing:.2em;
  text-transform:uppercase;color:var(--ink-soft);
}
.bar__sort select{
  font-family:var(--f-body);font-size:14px;color:var(--ink);
  background:var(--cream);border:1px solid var(--line);
  border-radius:2px;padding:8px 12px;cursor:pointer;
  transition:border-color .25s ease;
}
.bar__sort select:hover{border-color:rgba(22,33,43,.4)}
.bar__count{margin:0 0 clamp(18px,2.4vh,26px)}

/* ============================================================
   Сетка карточек каталога
   ============================================================ */
/* .grid--parks — только сброс списка (сетка карточек всегда <ul>);
   раскладку задаёт либо .grid--cols (хаб), либо .grid-4 из site.css (похожие). */
.grid--parks{list-style:none;margin:0;padding:0}
.grid--cols{grid-template-columns:repeat(auto-fill,minmax(300px,1fr))}
.grid__empty{
  grid-column:1/-1;padding:60px 0;text-align:center;
  font-family:var(--f-mono);font-size:12px;letter-spacing:.16em;
  text-transform:uppercase;color:var(--ink-soft);
}

/* Появление карточек. Не через [data-reveal] из site.css: у каталога свой
   жизненный цикл — фильтр гасит карточку (.is-out) и показывает заново,
   поэтому состояния разведены явно, а hover поднят по специфичности. */
.park-card{
  opacity:0;transform:translateY(18px);
  transition:
    opacity .55s var(--ease) var(--d,0s),
    transform .55s var(--ease) var(--d,0s),
    box-shadow .4s var(--ease),border-color .4s ease;
}
.park-card.is-in{opacity:1;transform:none}
/* смена фильтра: гаснем на месте, display переключается уже невидимыми —
   поэтому сетка не прыгает */
.park-card.is-out{opacity:0;transform:scale(.965);transition:opacity .2s ease,transform .2s ease}
.park-card.is-hidden{display:none}
@media (hover:hover) and (pointer:fine){
  .park-card.is-in:hover{transform:translateY(-5px)}
}

.card__title{font-size:1.08rem;line-height:1.2}
.card__title a{text-decoration:none;transition:color .25s ease}
.card__title a:hover{color:var(--blue)}
.card__sub{
  font-family:var(--f-mono);font-size:10px !important;
  letter-spacing:.16em;text-transform:uppercase;color:var(--ink-soft);
}
/* в .card__body стоит gap — собственные отступы детям не нужны */
.park-card .card__body{gap:10px}

/* моно-подписи параметров */
.specs{
  display:grid;grid-template-columns:1fr 1fr;
  gap:1px;background:var(--cream-deep);
  border:1px solid var(--cream-deep);margin:2px 0 0;
}
.specs>div{background:var(--light);padding:11px 12px 12px}
.specs dt{
  font-family:var(--f-mono);font-size:9px;letter-spacing:.18em;
  text-transform:uppercase;color:var(--ink-soft);margin:0 0 5px;
}
.specs dd{
  margin:0;font-family:var(--f-display);font-weight:500;font-size:1.02rem;
  letter-spacing:-.01em;color:var(--blue);font-variant-numeric:tabular-nums;
}
.specs dd small{font-family:var(--f-body);font-size:.72em;font-weight:400;letter-spacing:0}
/* габариты — длинная строка, ей нужен свой кегль, иначе ломается на две */
.specs dd.is-size{font-size:.86rem;letter-spacing:0}
.specs dd.is-empty{color:var(--ink-soft);opacity:.5;font-size:.95rem}

.card__foot{align-items:center;gap:12px 18px}

/* ============================================================
   Листалка снимков внутри карточки (см. gallery.js)
   ------------------------------------------------------------
   Кадры лежат в одной flex-дорожке и едут все разом (--i),
   а не переносятся по одному: тогда палец на телефоне тянет
   картинку за собой, и это единственный способ показать, что
   снимков больше одного, без подписей.
   Рамку и обрезку по-прежнему держит .card__media из site.css —
   листалка только заполняет её.
   ============================================================ */
.cshots{
  position:absolute;inset:0;overflow:hidden;
  touch-action:pan-y;              /* вертикальная прокрутка остаётся странице */
  outline:none;
}
.cshots:focus-visible{outline:2px solid var(--blue);outline-offset:-2px}
.cshots__track{
  display:flex;height:100%;
  transform:translate3d(calc(var(--i,0) * -100%),0,0);
  transition:transform .42s var(--ease);
}
/* пока тянут пальцем — никакой инерции перехода, дорожка идёт след в след */
.cshots.is-drag .cshots__track{transition:none}
.cshots__slide{
  flex:0 0 100%;width:100%;height:100%;object-fit:cover;
  -webkit-user-drag:none;user-select:none;
}

/* Стрелки: только для мыши и только по наведению на карточку.
   На тач-экранах они не появляются и, главное, не перехватывают
   тап — иначе невидимая кнопка съедала бы открытие во весь экран. */
.cshots__nav{
  position:absolute;top:50%;transform:translateY(-50%);z-index:3;
  width:34px;height:34px;border-radius:50%;border:0;padding:0;cursor:pointer;
  background:rgba(242,237,228,.92);color:var(--ink);
  font-size:17px;line-height:1;
  display:flex;align-items:center;justify-content:center;
  opacity:0;pointer-events:none;
  transition:opacity .25s ease,background .25s ease;
}
.cshots__nav--prev{left:10px}
.cshots__nav--next{right:10px}
@media (hover:hover) and (pointer:fine){
  .park-card:hover .cshots__nav:not([disabled]){opacity:1;pointer-events:auto}
  .cshots__nav:hover{background:var(--amber)}
}
.cshots__nav:focus-visible{opacity:1;pointer-events:auto;outline:2px solid var(--blue)}

.cshots__dots{
  position:absolute;left:0;right:0;bottom:9px;z-index:3;
  display:flex;justify-content:center;gap:5px;pointer-events:none;
}
.cshots__dots i{
  width:5px;height:5px;border-radius:50%;
  background:rgba(242,237,228,.5);box-shadow:0 0 0 1px rgba(22,33,43,.22);
  transition:background .25s ease,transform .25s ease;
}
.cshots__dots i.is-on{background:var(--cream);transform:scale(1.4)}
/* когда снимков больше, чем точек можно пересчитать глазом */
.cshots__num{
  position:absolute;right:10px;bottom:9px;z-index:3;pointer-events:none;
  font-family:var(--f-mono);font-size:9.5px;letter-spacing:.12em;
  background:rgba(242,237,228,.9);color:var(--ink);
  padding:3px 7px;border-radius:999px;font-variant-numeric:tabular-nums;
}


/* ============================================================
   Страница модели
   ============================================================ */
.model__grid{
  display:grid;gap:clamp(28px,3.4vw,54px);
  grid-template-columns:minmax(0,1.15fr) minmax(0,.85fr);
  align-items:start;
}
.model__lead{margin:0 0 26px;color:var(--ink-soft);font-size:16.5px;line-height:1.65}
.model h1{margin:0 0 16px}

/* галерея: кадры лежат стопкой, меняется только opacity — поток не двигается */
/* min-width:0 — потому что .gal лежит ячейкой в .model__grid, а у элемента
   грида min-width по умолчанию auto: ячейка раздаётся под min-content
   содержимого. Полоса миниатюр как раз шире колонки, когда кадров много,
   и без этой строки она растягивала бы всю колонку вместо того, чтобы
   прокручиваться внутри неё. */
.gal{margin:0;min-width:0}
/* система координат для стрелок и счётчика — по кадру, а не по всей
   фигуре: миниатюр может быть сколько угодно строк */
.gal__frame{position:relative}
.gal__main{
  position:relative;aspect-ratio:16/9;overflow:hidden;
  background:var(--cream-deep);border:1px solid var(--cream-deep);
}
.gal__main img{
  position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  opacity:0;transition:opacity .45s ease;
}
.gal__main img.is-on{opacity:1}
/* кадр раскрывается во весь экран по клику/Enter, поэтому он же —
   точка входа с клавиатуры (tabindex ставит gallery.js) */
.gal__main{cursor:zoom-in;touch-action:pan-y}
.gal__main:focus-visible{outline:2px solid var(--blue);outline-offset:2px}
/* у модели может быть всего один снимок — тогда листать нечего */
.gal--single .gal__nav,.gal--single .gal__count,.gal--single .gal__thumbs{display:none}
.gal__nav{
  position:absolute;top:50%;transform:translateY(-50%);z-index:2;
  width:40px;height:40px;border-radius:50%;border:0;cursor:pointer;
  background:rgba(242,237,228,.9);color:var(--ink);
  font-size:18px;line-height:1;display:flex;align-items:center;justify-content:center;
  transition:background .25s ease,transform .25s ease;
}
.gal__nav:hover{background:var(--amber);transform:translateY(-50%) scale(1.06)}
.gal__nav--prev{left:12px}
.gal__nav--next{right:12px}
.gal__count{
  position:absolute;right:12px;bottom:12px;z-index:2;
  font-family:var(--f-mono);font-size:10px;letter-spacing:.16em;
  color:var(--ink);background:rgba(242,237,228,.9);
  padding:5px 10px;border-radius:999px;font-variant-numeric:tabular-nums;
}
/* Полоса миниатюр — всегда ОДИН ряд. Сколько кадров у модели, известно
   только из manifest.json, и колонок под них нельзя назначить заранее:
   на repeat(4,1fr) пятая миниатюра переносилась во вторую строку и висела
   там одна у левого края. Здесь колонки нарезаются по числу элементов
   (grid-auto-flow:column), делят ширину поровну и сжимаются до 60px —
   ниже этого миниатюру уже не разобрать, поэтому ряд начинает
   прокручиваться вбок вместо того, чтобы ломаться. Порог выбран по узкому
   экрану: на 390px в колонку влезает пять миниатюр по 62px, то есть
   нынешние пять кадров умещаются целиком, а шестой и дальше уезжают
   в прокрутку. */
.gal__thumbs{
  display:grid;grid-auto-flow:column;grid-auto-columns:minmax(60px,1fr);
  gap:8px;margin-top:8px;list-style:none;padding:0;
  overflow-x:auto;overscroll-behavior-x:contain;scrollbar-width:thin;
  scroll-snap-type:x proximity;
}
.gal__thumbs li{scroll-snap-align:start}
.gal__thumbs button{
  display:block;width:100%;aspect-ratio:16/10;padding:0;cursor:pointer;
  border:1px solid var(--cream-deep);background:var(--cream-deep);overflow:hidden;
  opacity:.72;transition:border-color .25s ease,opacity .25s ease;
}
.gal__thumbs button img{width:100%;height:100%;object-fit:cover}
.gal__thumbs button:hover{opacity:1}
.gal__thumbs button[aria-current="true"]{border-color:var(--blue);opacity:1}

/* таблица характеристик */
.tbl{width:100%;border-collapse:collapse;margin:0 0 28px;border-top:1px solid var(--cream-deep)}
.tbl th,.tbl td{
  text-align:left;padding:12px 0;border-bottom:1px solid var(--cream-deep);
  vertical-align:baseline;
}
.tbl th{
  font-family:var(--f-mono);font-size:10px;font-weight:500;letter-spacing:.18em;
  text-transform:uppercase;color:var(--ink-soft);width:44%;padding-right:16px;
}
.tbl td{font-size:16px;color:var(--ink)}
.tbl td b{font-family:var(--f-display);font-weight:500;color:var(--blue);font-size:1.05rem}
.tbl td.is-empty{color:var(--ink-soft);opacity:.55}

.model__tel{
  font-family:var(--f-mono);font-size:15px;text-decoration:none;
  border-bottom:1px solid var(--line);padding-bottom:2px;
  transition:color .25s ease,border-color .25s ease;
}
.model__tel:hover{color:var(--blue);border-color:var(--blue)}
.model__note{
  margin:14px 0 0;font-family:var(--f-mono);font-size:10.5px;
  letter-spacing:.1em;color:var(--ink-soft);line-height:1.7;
}
.model .cta-row{margin-top:clamp(20px,3vh,32px)}

/* ---------- форма «Запрос цены» (#request на catalog.html и
   catalog-item.html) ----------
   .form/.field/.check — общие, приезжают из site.css. А вот .ask/
   .ask__form и цвета .form__note (тот же компонент, что «Задать вопрос»
   на project.html) заведены в pages.css, которую эти две страницы не
   грузят — как и с .cutout--knot выше, тащить сюда весь pages.css ради
   трёх правил накладнее, чем продублировать их с пояснением. Источник
   истины — pages.css, здесь только зеркало. */
.ask{display:grid;grid-template-columns:minmax(0,.95fr) minmax(0,1.05fr);gap:clamp(28px,4vw,72px);align-items:start}
.ask__form{
  background:var(--cream);border:1px solid var(--line-soft);border-radius:4px;
  padding:clamp(24px,2.8vw,38px);box-shadow:var(--shadow-card);
}
.section--deep .ask__form{background:var(--light)}
.form__note{
  margin:12px 0 0;font-family:var(--f-mono);font-size:11px;letter-spacing:.08em;
  color:var(--ink-soft);min-height:1.2em;
}
.form__note[data-state="ok"]{color:var(--blue-text)}
.form__note[data-state="err"]{color:#B4553A}
@media (max-width:900px){.ask{grid-template-columns:1fr}}

/* ============================================================
   Состав маршрута
   ============================================================ */
.stages{
  display:grid;gap:1px;background:var(--cream-deep);
  grid-template-columns:repeat(auto-fill,minmax(280px,1fr));
  border:1px solid var(--line-soft);
  list-style:none;margin:0;padding:0;
}
.stage{
  background:var(--cream);padding:22px 22px 24px;
  opacity:0;transform:translateY(14px);
  transition:opacity .5s var(--ease) var(--d,0s),
             transform .5s var(--ease) var(--d,0s),
             background .3s ease;
}
.stage.is-in{opacity:1;transform:none}
.stage:hover{background:var(--light)}
.stage__n{
  font-family:var(--f-mono);font-size:10px;letter-spacing:.22em;
  text-transform:uppercase;color:var(--amber);margin:0 0 10px;
  display:flex;align-items:center;gap:9px;
}
.stage__n::after{content:"";height:1px;flex:1;background:var(--cream-deep)}
.stage h3{font-size:1.02rem;letter-spacing:-.015em;line-height:1.2;margin:0 0 8px}
.stage p{margin:0;font-size:14.5px;line-height:1.55;color:var(--ink-soft)}
.stage__mat{
  margin-top:10px;padding-top:9px;border-top:1px solid var(--cream-deep);
  font-family:var(--f-mono);font-size:10.5px;
  letter-spacing:.06em;color:var(--wood);line-height:1.6;
}
.stage--edge{background:var(--cream-deep)}
.stage--edge .stage__n{color:var(--blue-text)}

/* ============================================================
   Адаптив
   ============================================================ */
@media (max-width:1000px){
  .model__grid{grid-template-columns:1fr;gap:32px}
}
@media (max-width:900px){
  .grid--cols{grid-template-columns:repeat(auto-fill,minmax(250px,1fr))}
  .bar__sort{margin-left:0}
}
@media (max-width:620px){
  .bar__sort{width:100%}
  .bar__sort select{flex:1;min-width:0}
  .grid--cols{grid-template-columns:1fr}
  .gal__thumbs{gap:6px}
  .gal__nav{width:34px;height:34px}
  .stages{grid-template-columns:1fr}
  .tbl th{width:50%;font-size:9.5px;letter-spacing:.14em}
  .tbl td{font-size:15px}
  .model .btn{width:100%;justify-content:center}
}

/* Условие сознательно сужено 09.09.2026 (правка владельца).
   Системный флаг «уменьшить движение» включается не только осознанно:
   его ставят эмуляция в DevTools, энергосбережение, политики и
   расширения — и сайт превращался в набор неподвижных картинок.
   Решение о движении принимает motion.js (одна точка на все скрипты),
   но CSS он переопределить не может, поэтому здесь добавлено
   `and (scripting: none)`: правила остаются в силе там, где скрипты
   выключены и переопределить нечем, и не срабатывают там, где
   решение уже принято в motion.js. Вернуть прежнее поведение —
   убрать `and (scripting: none)` и поставить RESPECT_SYSTEM = true. */
@media (prefers-reduced-motion:reduce) and (scripting:none){
  .park-card,.stage{transition-duration:.01ms !important;transform:none !important}
  .gal__main img{transition-duration:.01ms !important}
  /* .cshots__track исключён из общего transform:none — им задаётся
     позиция дорожки, а не украшение; гасим только длительность */
  .cshots__track,.cshots__dots i,.cshots__nav{
    transition-duration:.01ms !important;
  }
}

/* ---------- cutout узла (#request) ----------
   Приём общий с главной и внутренними страницами (site.css .cutout), но
   правило координат лежит именно здесь: catalog.html подключает site.css +
   catalog.css и pages.css НЕ грузит. Положенное в pages.css правило просто
   не применялось, и контейнер растягивался на натуральные 900px картинки,
   накрывая заголовок и оба абзаца секции запроса.

   Возврат в дело: с task 12 файл cut-knot.webp лежал в img-src без единой
   ссылки в разметке — сирота после правки промо-полосы на главной.

   Короткая тень в дополнение к общей: светлая пенька на кремовом фоне
   иначе читается выцветшим пятном — общая тень отнесена на 20px вниз и
   силуэт не обводит. */
.cutout--knot{
  top:clamp(-52px,-5.5vh,-30px);left:clamp(16px,5.5vw,86px);
  width:clamp(92px,8vw,142px);
  transform:rotate(8deg);
}
.cutout--knot img{
  filter:drop-shadow(0 1px 2px rgba(27,33,24,.50))
         drop-shadow(0 18px 30px rgba(27,33,24,.34));
}
