/* ── карточка модели ───────────────────────────────────── */
.prod{padding-bottom:clamp(56px,7vw,110px)}

.prod__cols{display:grid;grid-template-columns:1fr;gap:clamp(24px,3vw,48px);padding-top:8px}

@media (min-width:1040px){
.prod__cols{grid-template-columns:auto minmax(0,1fr)}
}

.gal{display:flex;flex-direction:column-reverse;gap:12px;min-width:0}

/* обёртка нужна только для градиента-затухания (::before/::after ниже): сама лента
   миниатюр (.gal__thumbs) скроллится внутри неё, а обёртка — нет, поэтому градиент
   остаётся на месте у края и не уезжает вместе с контентом */
.gal__thumbs-wrap{position:relative;min-width:0}

.gal__thumbs{display:flex;flex-direction:row;gap:8px;overflow-x:auto;overflow-y:hidden;
               scrollbar-width:none;padding-bottom:2px;scroll-snap-type:x proximity;
               scroll-behavior:smooth}

.gal__thumbs::-webkit-scrollbar{display:none}

@media (prefers-reduced-motion:reduce){
.gal__thumbs{scroll-behavior:auto}
}

.gal__thumb{flex:none;position:relative;width:64px;padding:0;background:none;
              border:1px solid var(--line);cursor:pointer;line-height:0;scroll-snap-align:start}

.gal__thumb[aria-current="true"]{border:2px solid var(--accent)}

.gal__thumb img{width:100%;height:auto;aspect-ratio:2/3;object-fit:cover;display:block}

/* лента продолжается за краем: градиент-затухание к цвету фона страницы, а не стрелки —
   решение задачи T69 (простая для 320px, автоматическая при смене темы через var(--bg),
   не требует показывать/скрывать активность стрелок). Классы can-scroll-prev/-next
   ставит model.js по факту скролла — на 4 кадрах (лента не скроллится) классов нет,
   градиент невидим, требование «без лишних стрелок» выполняется тем, что стрелок нет
   вовсе. */
.gal__thumbs-wrap::before,.gal__thumbs-wrap::after{content:"";position:absolute;
    pointer-events:none;opacity:0;transition:opacity .15s ease;z-index:1}

.gal__thumbs-wrap::before{left:0;top:0;bottom:0;width:28px;
    background:linear-gradient(to right,var(--bg),rgba(0,0,0,0))}

.gal__thumbs-wrap::after{right:0;top:0;bottom:0;width:28px;
    background:linear-gradient(to left,var(--bg),rgba(0,0,0,0))}

.gal__thumbs-wrap.can-scroll-prev::before,.gal__thumbs-wrap.can-scroll-next::after{opacity:1}

.gal__main{width:100%;position:relative;aspect-ratio:2/3;padding:0;border:none;
             background:var(--photo-bg);cursor:zoom-in;line-height:0;overflow:hidden}

.gal__main img{width:100%;height:100%;object-fit:cover;display:block}

/* у модели без фото вместо кнопки-кадра — div с текстом-заглушкой: line-height:0 и зум-курсор
   от кадра ему не подходят, иначе текст вылезает над рамкой */
div.gal__main{display:grid;place-items:center;padding:16px;cursor:default;line-height:1.4;
                font-size:13px;color:var(--text-muted);text-align:center}

@media (min-width:1040px){
/* --gal-h — общая высота колонки миниатюр и главного фото. Задаём её явно на обоих (а не
   рассчитываем на align-items:stretch у .gal): стретч выравнивает auto-высоту по САМОМУ
   ВЫСОКОМУ элементу строки, а у .gal__main высота задана числом, а не auto — на 8 кадрах
   контент .gal__thumbs (1030px) выше 760px главного фото и растягивал бы всю строку вместе
   с макетом вместо внутреннего скролла миниатюр. */
.gal{flex-direction:row;gap:14px;--gal-h:min(760px,calc(100svh - var(--chrome-h) - 120px))}
.gal__thumbs-wrap{height:var(--gal-h);min-height:480px}
.gal__thumbs{flex-direction:column;gap:10px;height:100%;overflow-x:hidden;overflow-y:auto;
               scroll-snap-type:y proximity}
.gal__thumb{width:80px}
.gal__main{width:auto;height:var(--gal-h);min-height:480px;aspect-ratio:2/3}
.gal__thumbs-wrap::before{left:0;right:0;top:0;bottom:auto;height:28px;width:auto;
    background:linear-gradient(to bottom,var(--bg),rgba(0,0,0,0))}
.gal__thumbs-wrap::after{left:0;right:0;bottom:0;top:auto;height:28px;width:auto;
    background:linear-gradient(to top,var(--bg),rgba(0,0,0,0))}
}

.info{max-width:52ch;min-width:0}

.info__h1{margin:0;font-weight:300;font-size:clamp(26px,3vw,38px);line-height:1.15}

/* Артикул покупатель называет по телефону, когда звонит в салон, — это рабочий
   идентификатор вещи, а не служебная подпись. Приглушённым 13px он читался хуже
   всего на странице (контраст 5.24 против 13.07 у основного текста) и терялся
   между крупным заголовком и ещё более крупной ценой. Замечание заказчицы
   25.09.2026: «артикул плохо читается». */
/* Разрядка и полужирное — не украшение: в Montserrat цифра 1 нарисована голой
   вертикалью, без засечки сверху и основания снизу, и вплотную к «Т» превращается
   в её правую ногу — «Т138Я» читается как «П38Я». Та же ловушка в «ЛОТ104Н»:
   «Т1» и следом «О0». Замечание заказчицы 25.09.2026. Значение 0.1em подобрано
   по пробе: при 0.06em знаки ещё близко, при 0.14em строка выглядит искусственно
   разреженной (скриншоты — design/screens/2026-09-25_article-*). */
.info__art{margin:10px 0 0;font-size:15px;font-weight:500;letter-spacing:.1em;color:var(--text)}

.info__price{margin:24px 0 0;font-size:28px;font-weight:500}

.info__stock{margin:10px 0 0;display:flex;align-items:center;gap:8px;font-size:14px}

.info__stock i{width:8px;height:8px;border-radius:50%;background:var(--accent);flex:none}

.info__stock--order i{background:var(--line)}

.info__cap{margin:0;font-size:12px;letter-spacing:.12em;text-transform:uppercase;color:var(--text-muted)}

.sizes{padding-top:28px}

.sizes__row{display:flex;flex-wrap:wrap;gap:8px;padding-top:12px}

/* T75: размер из выгрузки может быть нечисловым текстом («универсальный размер»),
   а не только цифрой — кнопка растёт по высоте и переносит текст, а не вылезает за
   пределы строки. min-width/min-height (не height) сохраняют прежний вид у коротких
   цифровых размеров и не режут длинный текст на 360px. */
.sizes__row button{display:inline-flex;align-items:center;justify-content:center;
                     text-align:center;min-width:48px;min-height:44px;max-width:100%;
                     padding:8px 12px;background:none;border:1px solid var(--line);
                     color:var(--text);font-size:14px;line-height:1.25;white-space:normal;
                     overflow-wrap:break-word;cursor:pointer}

.sizes__row button[aria-pressed="true"]{background:var(--accent);border-color:var(--accent);color:#24211D}

/* T110: заказчица (2026-09-29) — «Выберите размер» терялось среди кнопок размеров и
   ссылки «Как определить размер»: отличалось только цветом (.field__err, base.css), а
   текста вокруг много, взгляд не цепляет. Усилено точечно, только для этого сообщения:
   жирный вес и покрупнее, плюс короткая встряска при появлении (model.js добавляет класс
   is-shaking и перезапускает её при каждой повторной попытке). Разовая анимация, не
   бесконечное мигание — оно раздражает и плохо для доступности; общее правило в конце
   base.css (`prefers-reduced-motion:reduce`) отключает её для тех, кому мешает движение. */
#sizesErr{font-weight:700;font-size:14px}

@keyframes sizes-err-shake{
  0%,100%{transform:translateX(0)}
  20%{transform:translateX(-5px)}
  40%{transform:translateX(5px)}
  60%{transform:translateX(-3px)}
  80%{transform:translateX(3px)}
}
#sizesErr.is-shaking{animation:sizes-err-shake .5s ease-in-out}

/* T114: была ссылка в никуда (href="#"), теперь открывает попап — семантически это
   действие, а не переход, поэтому тег сменён на button и ему нужен свой сброс кнопочных
   стилей браузера (фон/рамка/отступы/шрифт), которого не требовал прежний <a>. */
.sizes__help{display:inline-block;margin-top:12px;background:none;border:none;padding:0;
               font:inherit;cursor:pointer;font-size:13px;color:var(--text-muted);
               box-shadow:inset 0 -1px 0 var(--line)}

/* рост и параметры модели помогают выбрать размер по фотографии */
.onmodel{margin:20px 0 0;display:flex;flex-wrap:wrap;align-items:baseline;gap:6px 10px;
           font-size:13.5px;line-height:1.5;color:var(--text)}

.onmodel__cap{font-size:12px;letter-spacing:.12em;text-transform:uppercase;color:var(--text-muted)}

.onmodel__ph{color:var(--text-muted)}

.specs{margin:28px 0 0;padding:0;list-style:none;border-top:1px solid var(--line)}

.specs li{display:flex;align-items:center;justify-content:space-between;gap:16px;
            min-height:44px;border-bottom:1px solid var(--line)}

.specs dt,.specs .k{font-size:13px;color:var(--text-muted)}

.specs .v{font-size:14px;color:var(--text);text-align:right}

.buy{display:flex;gap:12px;padding-top:28px}

.buy__main{flex:1;height:56px;display:inline-flex;align-items:center;justify-content:center;
             background:var(--accent);color:#24211D;border:none;font-size:12px;font-weight:600;
             letter-spacing:.14em;text-transform:uppercase;cursor:pointer}

.buy__fav{width:56px;height:56px;flex:none;display:grid;place-items:center;background:none;
            border:1px solid var(--line);color:var(--text);cursor:pointer}

@media (hover:hover){
.buy__fav:hover{border-color:var(--text)}
}

.ship{margin:24px 0 0;padding:0;list-style:none;display:flex;flex-direction:column;gap:8px}

.ship li{display:flex;align-items:center;gap:10px;font-size:13px;color:var(--text-muted)}

.ship li::before{content:"";width:4px;height:4px;border-radius:50%;background:var(--text-muted);flex:none}

.desc{padding:64px 0 80px;max-width:65ch}

.desc h2{margin:0;font-size:22px;font-weight:500;line-height:1.3}

.desc p{margin:20px 0 0;font-size:16px;line-height:1.6;color:var(--text);text-wrap:pretty}

.desc p + p{margin-top:16px}

/* затемнение делаем фоном самого окна, а не ::backdrop:
     при запасном пути открытия (setAttribute open) backdrop не появляется вовсе */
dialog{border:none;padding:0;max-width:100%;max-height:100dvh;width:100%;height:100dvh;
         display:grid;place-items:center;background:rgba(20,18,15,.88)}

dialog:not([open]){display:none}

dialog::backdrop{background:rgba(20,18,15,.88)}

.zoom{width:100%;height:100dvh;position:relative;display:grid;place-items:center;padding:24px}

.zoom img{max-width:100%;max-height:100%;width:auto;height:auto;object-fit:contain}

/* T87: у зума нет одного «нормального» размера, чтобы под него подгонять заглушку — реальное
   фото занимает столько места, сколько позволяют его собственные пиксели (object-fit:contain
   от натуральных width/height, которых у сломанного файла попросту нет). Поэтому заглушка —
   комфортного вида блок в той же пропорции 2/3, что и настоящие фото, отцентрованный в окне
   тем же классическим приёмом (inset:0 + margin:auto), а не растянутая копия рамки .zoom
   (которая размером с весь экран). */
.zoom .photo-fallback{position:absolute;inset:0;margin:auto;width:min(60vw,340px);
                        aspect-ratio:2/3;max-height:80dvh}

.zoom__arrow{position:fixed;top:50%;transform:translateY(-50%);width:56px;height:56px;
               display:grid;place-items:center;background:rgba(238,231,223,.9);border:none;
               color:#24211D;cursor:pointer;border-radius:2px}

@media (hover:hover){
.zoom__arrow:hover{background:#FFCB00}
}

.zoom__arrow--prev{left:12px}

.zoom__arrow--next{right:12px}

/* T90: клик по главному фото открывает <dialog>, showModal() по спецификации сам переносит
   фокус на первую фокусируемую кнопку внутри (#zoomPrev). С клавиатуры (Enter на фото) рамку
   фокуса нужно оставить — во всех трёх движках она и так корректно показывается. При открытии
   мышью Chromium/Firefox верно не рисуют рамку (эвристика :focus-visible распознаёт перенос
   фокуса как не связанный с клавиатурой), а WebKit рисует её всегда — это баг конкретно
   WebKit, а не разница в дизайне. Правило ниже гасит outline только у той самой кнопки и
   только на тот один программный перенос фокуса, которым помечает её model.js при открытии
   мышью/тачем (класс снимается по первому же blur — см. комментарий в model.js), поэтому
   последующий реальный Tab/Shift+Tab внутри диалога по-прежнему получает рамку как обычно. */
.zoom__arrow--no-init-ring:focus{outline:none}

.zoom__count{position:fixed;left:50%;bottom:18px;transform:translateX(-50%);margin:0;
               padding:6px 14px;background:rgba(238,231,223,.9);color:#24211D;
               font-size:13px;border-radius:2px}

@media (max-width:600px){
.zoom__arrow{width:48px;height:48px}
.zoom__arrow--prev{left:6px}
.zoom__arrow--next{right:6px}
}

.modal__close{position:fixed;top:12px;right:12px;width:44px;height:44px;display:grid;
                place-items:center;background:var(--surface-alt);border:1px solid var(--line);
                color:var(--text);cursor:pointer;border-radius:2px}

.ask{width:min(440px,92vw);background:var(--bg);border:1px solid var(--line);padding:28px;
       max-height:90dvh;overflow-y:auto}

.ask h2{margin:0;font-size:18px;font-weight:500;line-height:1.3}

.ask h2 span{display:block;font-size:13px;font-weight:400;color:var(--text-muted);margin-top:6px}

.ask label{display:block;margin-top:18px;font-size:12px;letter-spacing:.08em;
             text-transform:uppercase;color:var(--text-muted)}

.ask input,.ask textarea{width:100%;margin-top:8px;min-height:48px;padding:12px 14px;
             background:var(--surface-alt);border:1px solid var(--line);border-radius:2px;
             color:var(--text);font-size:15px;font-family:inherit}

.ask textarea{min-height:88px;resize:vertical}

.ask__send{width:100%;margin-top:22px;height:52px;background:var(--accent);color:#24211D;
             border:none;font-size:12px;font-weight:600;letter-spacing:.14em;
             text-transform:uppercase;cursor:pointer}

/* чек-бокс согласия внутри .ask переопределяет общие .ask label/.ask input —
   они рассчитаны на текстовые поля, а не на чек-бокс */
.ask .agree{display:flex;align-items:flex-start;gap:10px;margin-top:18px;
             font-size:14px;line-height:1.5;letter-spacing:normal;
             text-transform:none;color:var(--text)}

.ask .agree input{width:20px;height:20px;min-height:0;margin:2px 0 0;padding:0;
                    background:none;border:none;border-radius:0;accent-color:#FFCB00;flex:none}

/* общее .ask a (base.css) делает ссылки диалога 18px — в тексте согласия ссылка как текст */
.ask .agree a{font-size:inherit;font-weight:inherit}

/* T103: тот же WebKit-фикс, что в base.css (`.agree input[type="checkbox"]`, подробный
   комментарий там) — отдельным правилом здесь, потому что этот чекбокс переопределён
   `.ask .agree input` выше (border:none;background:none под текстовые поля диалога) с той
   же специфичностью селектора; без своего .ask-правила фикс из base.css был бы перебит
   этим сбросом (подключён позже — .ask .agree input побеждает для border/background). */
@supports (-webkit-hyphens: none){
.ask .agree input[type="checkbox"]{
    appearance:none;-webkit-appearance:none;position:relative;
    border-radius:2px;border:1px solid var(--line);background:var(--bg);
  }
.ask .agree input[type="checkbox"]:checked{
    border:1px solid #24211D;background:var(--accent);
  }
.ask .agree input[type="checkbox"]:checked::after{
    content:"";position:absolute;left:6px;top:2px;width:5px;height:10px;
    border:solid #24211D;border-width:0 2px 2px 0;transform:rotate(45deg);
  }
}

/* сообщение об успехе на месте формы «Узнать цену» */
.ask__done{margin:12px 0 0;font-size:15px;line-height:1.6;color:var(--text-muted)}

/* T114: попап «Как определить размер» — таблица из двух колонок (обхват груди к обхвату
   талии/бёдер), поэтому даже на 320px влезает без горизонтального скролла; .sizeguide__scroll
   остаётся на случай, если админ в будущем добавит в список лишние строки/колонки и таблица
   всё же не поместится — тогда скроллится только она, а не весь попап (design.md §21). */
.sizeguide{width:min(400px,92vw);background:var(--bg);border:1px solid var(--line);
             padding:28px;max-height:90dvh;overflow-y:auto}

.sizeguide h2{margin:0;font-size:18px;font-weight:500;line-height:1.3}

.sizeguide__scroll{margin-top:18px;max-width:100%;overflow-x:auto}

.sizeguide__table{width:100%;border-collapse:collapse}

.sizeguide__table th,.sizeguide__table td{padding:10px 8px;text-align:center;
             font-size:14px;color:var(--text);border-bottom:1px solid var(--line);
             white-space:nowrap}

.sizeguide__table thead th{font-size:12px;font-weight:500;color:var(--text-muted);
             vertical-align:bottom}

.sizeguide__note{margin:16px 0 0;font-size:13px;color:var(--text-muted)}

/* мобильные браузеры зумят страницу при фокусе, если кегль поля меньше 16px */
.sorter select,.field input,.field textarea,.sub__row input,
  .promo__row input,.qty input,.ask input,.ask textarea{font-size:16px}

@media (min-width:768px){
.field input,.field textarea,.sub__row input,
    .promo__row input,.qty input,.ask input,.ask textarea{font-size:15px}
}
