/* Общий костяк деталь-страниц (Material/Sample/Pattern/Project) — toolbar,
   таббар, контейнер .page, скелет карусели, spec-таблица, обёртки секций
   b1-b5. Найден сравнением локальных <style> блоков всех 4 макетов —
   почти идентичны, отличия по двум группам:
   - drift (забытый перенос дизайна) — здесь применён канонический вариант
     (используется в Sample/Pattern): .tabseg (flex:1 1 0, white-space:nowrap),
     .page padding-bottom:80px.
   - осознанные различия (aspect-ratio карусели, положение стрелок,
     margin у .carousel-wrap и т.п.) — НЕ здесь, остаются оверрайдами в
     page-specific CSS файле каждой страницы (напр. project-page.css).
   shared.css уже даёт: :root, nav, blk-title, sec-* heading kit,
   area/service strip, footer, fcta, канонические .pcard/.pjcard/.mcard/.scard. */

/* ── BREADCRUMB + TOOLBAR ── */
.toolbar-wrap{position:sticky;top:64px;z-index:95;background:var(--surface);border-bottom:1px solid var(--line)}
/* .bc — общий компонент, см. shared.css. */
/* .tabbar/.tabseg — общий компонент, см. shared.css. Здесь только
   специфика детальных страниц: sticky даёт обёртка .toolbar-wrap, поэтому
   тут нужен просто border-top (на главной иначе — border-bottom, т.к.
   .tabbar там sticky сам по себе). */
.tabbar{border-top:1px solid var(--line)}

/* ── SECTION FRAMING ── */
/* .page, .b1-.b5 (вертикальный ритм) и .section-content (фон секции) — общие, shared.css. */

/* ── HEADER: название + бейдж уровня ── */
.mat-head{margin-bottom:32px}
.mname-row{display:flex;align-items:center;justify-content:space-between;gap:20px;flex-wrap:wrap}
.mname-sub{font-family:var(--mono);font-size:11px;letter-spacing:.12em;text-transform:uppercase;color:var(--ink-faint);margin-top:8px}

/* ── OVERVIEW (carousel + spec table, side by side — Material/Sample/Pattern;
   Project использует свой page-specific оверрайд для full-width раскладки) ── */
.ov-grid{display:grid;grid-template-columns:55fr 45fr;gap:56px;align-items:start}
/* min-width:0 обязателен на grid/flex-элементах с картинкой/каруселью
   внутри — без этого браузер использует "автоматический минимальный
   размер" = intrinsic-ширина содержимого как пол, из-за чего .carousel-wrap
   (и вложенный .main-viewer) может вылезти за границы своей колонки .ov-grid
   и, в свою очередь, за .page — именно так на мобильном ломалась ширина
   карусели, хотя текстовые блоки рядом (у которых такого intrinsic-контента
   нет) оставались в пределах padding. */
.ov-grid > *{min-width:0}

/* ── CAROUSEL SKELETON ── */
.carousel-wrap{display:flex;flex-direction:column;gap:12px}
.tstrip-col{display:flex;flex-direction:row;align-items:center;gap:7px}
.tstrip{display:flex;flex-direction:row;gap:6px;overflow-x:auto;scrollbar-width:none;flex:1}
.tstrip::-webkit-scrollbar{display:none}
.tscroll{width:26px;height:44px;border-radius:7px;border:1px solid var(--line-2);background:var(--surface);color:var(--ink-dim);cursor:pointer;display:flex;align-items:center;justify-content:center;font-size:11px;flex:0 0 auto;transition:.15s}
.tscroll:hover{border-color:var(--accent-deep);color:var(--accent)}
/* Активная миниатюра выделяется РАЗМЕРОМ — но увеличивать её саму (scale>1)
   визуально вылезает за пределы своей ячейки (соседи стоят вплотную через
   gap, а .tstrip{overflow-x:auto} без явного overflow-y обрезает по высоте —
   классический CSS-эффект: один явный overflow-x/y без другого превращает
   второй в auto). Вместо этого — обратный приём: неактивные чуть УМЕНЬШЕНЫ
   (scale<1), активная остаётся в 100% размере своей ячейки, никогда не
   вылезая за неё. */
.titem{aspect-ratio:1/1;width:64px;border-radius:7px;overflow:hidden;border:1px solid var(--line);background:var(--bg-main);cursor:pointer;position:relative;transition:.12s,transform .2s ease;flex:0 0 auto;transform:scale(.86)}
.titem img{width:100%;height:100%;object-fit:cover;display:block}
.titem.on{border-color:var(--accent);box-shadow:0 0 0 1px var(--accent);transform:scale(1)}
.main-viewer{position:relative;border-radius:var(--r);overflow:hidden;aspect-ratio:3/4;-webkit-user-select:none;user-select:none}
.main-viewer #mv-media{width:100%;height:100%}
.main-viewer img{width:100%;height:100%;object-fit:contain;display:block}
/* ── MEDIA-FIT (фото + размытая подложка) — .main-viewer использует
   object-fit:contain: вертикальное/непропорциональное фото в нём раньше
   оставляло голый леттербокс по краям. .media-fit-bg — та же картинка
   позади, object-fit:cover+blur, заполняет контейнер целиком под чётким
   фото — вместо пустых полей размытое продолжение того же кадра
   (см. mkMediaFit()/mkMediaFitInner() в site.js). Специфичность через
   класс+класс (.main-viewer .media-fit-bg), а не один (.media-fit-bg),
   намеренно — иначе её перебивает более специфичное `.main-viewer img`
   выше (тег+класс).
   В лайтбоксе (.lb-media) блюр НЕ нужен (запрос пользователя 2026-08-13) —
   там просто скрыт, леттербокс остаётся тёмным фоном самого .lightbox
   (--overlay-darkest, см. ниже) вместо размытого увеличенного кадра. */
.media-fit{position:relative;width:100%;height:100%;overflow:hidden}
.main-viewer .media-fit-bg{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;filter:blur(32px) saturate(1.15) brightness(.72);transform:scale(1.15)}
.lb-media .media-fit-bg{display:none}
.media-fit-fg{position:relative;z-index:1;transition:transform .25s ease}
/* Zoom (tz-gallery-zoom.md) — только в лайтбоксе (.lb-media), .main-viewer
   больше не зумится вообще (см. site.js — enableSwipeDrag для неё вызван
   без onTap). Масштаб/сдвиг во время зума — inline transform от JS
   (LB_ZOOM/applyLightboxTransform в site.js), тут только курсоры по
   состоянию: в покое — намёк на зум, увеличено — можно тащить (grab),
   во время самого перетаскивания — grabbing. */
.lb-media .media-fit-fg{cursor:zoom-in}
.lb-media .media-fit-fg.is-zoomed{cursor:grab}
.lb-media .media-fit-fg.is-panning{cursor:grabbing}
@media(prefers-reduced-motion:reduce){.media-fit-bg,.media-fit-fg{transition:none}}
/* Бейдж/подпись/стрелки/лупа рендерятся В DOM РАНЬШЕ, чем временные
   .media-fit клоны (peek при свайпе, incoming при анимированном переходе —
   см. site.js), которые JS дописывает в конец .main-viewer уже ПОСЛЕ них —
   без явного z-index они оказались бы выше (стекование абсолютных
   элементов без z-index идёт по порядку в DOM) и перекрывали controls на
   время свайпа/перехода. */
.mv-badge{position:absolute;top:12px;left:12px;font-family:var(--mono);font-size:10px;letter-spacing:.05em;background:color-mix(in srgb,var(--shadow-black) 55%,transparent);color:var(--text-inverse);padding:4px 10px;border-radius:99px;z-index:2}
.mv-cap{position:absolute;bottom:0;left:0;right:0;padding:26px 16px 12px;font-size:12px;color:var(--text-inverse);background:linear-gradient(to top,color-mix(in srgb,var(--shadow-black) 60%,transparent),transparent);z-index:2}
.mv-nav{position:absolute;top:50%;transform:translateY(-50%);width:100%;display:flex;justify-content:space-between;padding:0 10px;pointer-events:none;z-index:2}
.mv-nav button{width:40px;height:40px;border-radius:50%;background:color-mix(in srgb,var(--shadow-black) 55%,transparent);border:1px solid color-mix(in srgb,var(--text-on-accent) 20%,transparent);color:var(--text-inverse);font-size:22px;display:flex;align-items:center;justify-content:center;pointer-events:auto;transition:.15s}
.mv-nav button:hover{background:color-mix(in srgb,var(--shadow-black) 80%,transparent)}
.mv-zoom{position:absolute;top:12px;right:12px;width:32px;height:32px;border-radius:50%;background:color-mix(in srgb,var(--shadow-black) 55%,transparent);border:1px solid color-mix(in srgb,var(--text-on-accent) 20%,transparent);color:var(--text-inverse);cursor:pointer;display:flex;align-items:center;justify-content:center;transition:.15s;z-index:2}
.mv-zoom:hover{background:color-mix(in srgb,var(--shadow-black) 80%,transparent)}
/* position:absolute;inset:0 — та же рамка, что у .media-fit-fg (тоже 100%
   .main-viewer/.lb-media), поэтому синхронный transform (см.
   syncHotspotsTransform() в site.js) двигает/масштабирует точки ТОЧНО как
   само фото при zoom+pan. pointer-events:none на контейнере — иначе пустая
   область между точками перехватывала бы клики/драг по фото под ней;
   .hotspot возвращает pointer-events:auto самим точкам (см. shared.css). */
#mv-hotspots,#lb-hotspots{position:absolute;inset:0;transition:opacity .15s ease;pointer-events:none;z-index:2}

/* ── DETAILS: description ── */
.b1-desc .desc-lbl{font-family:var(--display);font-size:16.5px;font-weight:700;margin-bottom:8px}
.b1-desc{margin-left:auto;margin-right:auto;text-align:left}
.b1-desc .desc{color:var(--ink-dim);font-size:14px;line-height:1.75;margin-bottom:12px}
.b1-desc .desc:last-child{margin-bottom:0}

/* ── spec table ── */
.spec{width:100%;border-collapse:collapse;border-top:1px solid var(--line);border-bottom:1px solid var(--line)}
.spec tr{border-bottom:1px solid var(--line)}
.spec tr:last-child{border-bottom:none}
.spec th{text-align:left;padding:12px 0;font-family:var(--display);font-size:13px;font-weight:700;letter-spacing:-.005em;color:var(--ink);width:28%;vertical-align:top;padding-right:14px}
.spec td{padding:12px 0;font-size:13px;color:var(--ink);vertical-align:top}
.spec .sub{display:block;font-size:11px;color:var(--ink-faint);margin-top:3px}
.sub-inline{font-size:11px;color:var(--ink-faint)}
.tlink{font-family:var(--body);font-size:13px;font-weight:500;color:var(--accent);border-bottom:1px solid var(--accent-deep)}
.tlink:hover{text-decoration:none;color:var(--accent-deep)}
/* ── CTA (Request a quote / WhatsApp) — было только на sample.php
   (sample-page.css), как <button> без href (ничего не делали). Перенесено
   сюда (общий для material/sample/project — все три грузят detail-page.css)
   и переведено с <button> на <a href> — ведёт на /quote/ с контекстом
   (?interest=...&source=...), см. material.php/sample.php/project.php.
   Классы .cta-p/.cta-wa унифицированы с общими .fcta-main/.fcta-sub
   (shared.css) — те же кнопки, что у hero-CTA/footer FCTA/contact.php,
   2026-08-19 по прямому запросу. .cta-p/.cta-wa удалены, больше нигде не
   используются. .fcta-main/.fcta-sub сами по себе display:inline-block без
   width — здесь они авто-растягиваются на всю ширину БЛАГОДАРЯ
   align-items:stretch (значение по умолчанию) у родителя .cta-stack,
   flex-item любого display становится блочным по cross-axis; text-align
   ниже — то немногое, что .fcta-main/.fcta-sub сами не задают (в остальных
   местах сайта они inline-block по размеру контента, центрировать нечего). */
.cta-stack{display:flex;flex-direction:column;gap:9px;margin-top:20px}
.cta-stack .fcta-main,.cta-stack .fcta-sub{text-align:center}
/* .wa-dot раньше центровался/получал отступ от родительского
   display:flex;gap:8px (.cta-wa) — тот класс удалён, поэтому здесь теперь
   свой display/margin, чтобы зелёная точка была видна и с отступом от
   текста "WhatsApp" независимо от родителя (.fcta-sub — inline-block, не
   flex). */
/* #3fae64 — сознательно НЕ токен: фирменный зелёный WhatsApp, а не цвет
   темы сайта (не должен меняться вместе с --green/тёмной темой). */
.wa-dot{display:inline-block;width:9px;height:9px;border-radius:50%;background:#3fae64;margin-right:7px;vertical-align:middle}

.utags{display:flex;flex-wrap:wrap;gap:6px}
.utag{display:inline-flex;align-items:center;padding:4px 10px;border-radius:99px;font-size:12px}
.utag.ok{border:1px solid color-mix(in srgb,var(--green) 32%,transparent);color:var(--green);background:var(--green-bg)}
.utag.no{border:1px solid color-mix(in srgb,var(--clay) 25%,transparent);color:var(--clay);text-decoration:line-through;opacity:.6}
.coverage-note{font-size:12px;color:var(--ink-dim);margin-top:20px;padding:16px 20px;background:var(--bg-card);border:1px solid var(--line);border-radius:var(--r);line-height:1.65}

/* ── карточные гриды (используются в блоках "X in this Y") ── */
.proj-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:20px}

/* "Samples Made With <Material>" (BLOCK 3, material.php) — карточки-
   планшеты MDF вместо плоской .card. detail-page.css общий для
   material.php/sample.php/master-sample.php — #matSampleRow есть только
   в разметке material.php, на остальные страницы это не влияет.

   Сетка вместо flex-wrap — 3/2/1 колонки по ширине страницы, gap
   фиксированный 20px, а вот сама ширина (и с ней высота — aspect-ratio
   3/4 в mdf-card.css) карточки НЕ фиксирована пикселями: --mdf-w
   считается через container query units (cqw) от фактической ширины
   .mdf-row (container-type:inline-size на нём), а не от ширины
   вьюпорта — так geometрия карточки (--mdf-unit и все размеры от неё:
   отверстие подвеса, радиус, паддинги) всегда точно совпадает с
   реальным рендер-размером колонки, при любой ширине страницы, не
   только на заданных брейкпоинтах. Формула — (100cqw − сумма gap'ов
   между колонками) / число колонок. */
#matSampleRow.mdf-row{
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 20px;
  padding: 0;
  container-type: inline-size;
}
#matSampleRow.mdf-row .mdf-card{
  width: 100%;
  --mdf-tilt: 0deg;
  --mdf-w: calc((100cqw - 40px) / 3);
}
@media (min-width: 641px){
  /* -4px (2026-08-19) — тот же единый подъём, что и у остальных карточек
     сайта (см. .card в shared.css, базовое правило .mdf-card в
     mdf-card.css), раньше здесь было отдельно заданное -8px. */
  #matSampleRow.mdf-row .mdf-card:hover, #matSampleRow.mdf-row .mdf-card:focus-visible{
    transform: rotate(0deg) translateY(-4px);
  }
}
@media (max-width: 640px){
  #matSampleRow.mdf-row .mdf-card:hover, #matSampleRow.mdf-row .mdf-card:focus-visible{
    transform: none;
  }
}
/* 3 → 2 → 1 колонки по ширине страницы (не самого .mdf-row — тот почти
   всегда = ширине .page) — тот же брейкпоинт, что у .proj-grid чуть выше
   в этом файле для аналогичного "X in this Y" грида. */
@media (max-width: 980px){
  #matSampleRow.mdf-row{ grid-template-columns: repeat(2, 1fr); gap: 20px; }
  #matSampleRow.mdf-row .mdf-card{ --mdf-w: calc((100cqw - 20px) / 2); }
}
@media (max-width: 560px){
  #matSampleRow.mdf-row{ grid-template-columns: 1fr; }
  #matSampleRow.mdf-row .mdf-card{ --mdf-w: 100cqw; }
}

/* ── общие подписи для секций-списков ("Patterns Used" и т.п.) — заголовок/
   подзаголовок унифицированы с общим .section-title/.section-subtitle
   (shared.css), 2026-08-19, по прямому запросу; .b3-title/.b3-sub удалены,
   больше нигде не используются. ── */
.b3-hdr{display:flex;align-items:flex-end;justify-content:space-between;gap:16px;margin-bottom:18px;flex-wrap:wrap}
.b3-more{display:inline-block;margin-top:16px}

@media(max-width:980px){.proj-grid{grid-template-columns:repeat(2,1fr)}}
@media(max-width:760px){.ov-grid{grid-template-columns:1fr;gap:32px}}
/* .proj-grid — тот же брейкпоинт (560px), что у компактного вида pjcard
   (см. shared.css) — раньше был 620px, из-за разрыва в 561-620px карточка
   попадала в 1-колоночную сетку ещё десктопного размера. */
@media(max-width:620px){.spec th{width:44%}}
@media(max-width:560px){.proj-grid{grid-template-columns:1fr}}
/* Единая ширина карточки на мобильном — --card-side-pad (header.php, из
   site_settings.mobile_card_width_pct, настраивается в adm-settings.php),
   раньше был захардкожен 10vw здесь и ещё в 5 файлах — теперь один
   источник для всех. Раньше здесь стоял то 40px (по умолчанию), то 28px
   (первая, «на глаз», версия фикса), из-за чего карточки с одинаковым
   соотношением сторон получались разной ширины на разных страницах. */
@media(max-width:560px){.page,.bc{padding-left:var(--card-side-pad);padding-right:var(--card-side-pad)}}
/* .blk-title sticky top на детальных страницах — под nav+хлебными
   крошками (.tabbar скрыт на мобильном, см. shared.css): 64px nav + 22px
   .bc = 86px. */
@media(max-width:560px){.blk-title{top:86px}}

/* ── SERVICE AREAS ── */
/* .section-content (фон секции) — общий, shared.css. */

/* ── LIGHTBOX (полноэкранная галерея карусели) ──
   Открывается кликом по главному фото (.main-viewer #mv-media), см. site.js:
   openLightbox/closeLightbox/lightboxGoSlide/updateLightbox. Общий для всех
   деталь-страниц (Material/Sample/Pattern/Project) — часть карусели, не
   зависит от hotpoint'ов и прочих page-specific надстроек. */
.lightbox{position:fixed;inset:0;background:color-mix(in srgb,var(--overlay-darkest) 96%,transparent);z-index:2000;display:none;flex-direction:column;align-items:center;justify-content:center;padding:24px}
.lightbox.show{display:flex}
/* z-index явно выше .hspop (2100, попап хотспота — position:fixed, рендерится
   в корневом стекинг-контексте) — если хотспот на фото открывается рядом с
   верхним правым углом, его карточка визуально перекрывала кнопку закрытия
   и блокировала клик по ней. */
.lb-close{position:absolute;top:20px;right:24px;width:40px;height:40px;border-radius:50%;background:color-mix(in srgb,var(--text-on-accent) 10%,transparent);border:1px solid color-mix(in srgb,var(--text-on-accent) 20%,transparent);color:var(--text-inverse);font-size:22px;line-height:1;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:.15s;z-index:2200}
.lb-close:hover{background:color-mix(in srgb,var(--text-on-accent) 20%,transparent)}
/* Индикатор зума (tz-gallery-zoom.md) — зеркальная пара .lb-close (тот же
   верхний отступ/z-index/тёмная плашка), только слева и не кнопка —
   текст обновляет site.js (applyLightboxTransform), pointer-events:none —
   сама плашка не должна перехватывать тап/клик/драг по фото под собой. */
.lb-zoom-badge{position:absolute;top:20px;left:24px;display:flex;align-items:center;gap:5px;padding:0 12px;height:32px;border-radius:99px;background:color-mix(in srgb,var(--text-on-accent) 10%,transparent);border:1px solid color-mix(in srgb,var(--text-on-accent) 20%,transparent);color:var(--text-inverse);font-family:var(--mono);font-size:12px;letter-spacing:.02em;font-variant-numeric:tabular-nums;z-index:2200;pointer-events:none}
/* Контейнер имеет ФИКСИРОВАННЫЙ размер (не max-*) — 90vw на 90% высоты
   экрана за вычетом места под бейдж и полосу миниатюр (112px), т.е.
   [фото + бейдж + миниатюры] суммарно = 90vh. object-fit:contain внутри
   контейнера с фиксированными шириной/высотой — стандартный приём: фото
   ВСЕГДА масштабируется, чтобы поместиться в контейнер целиком, сохраняя
   пропорции — и уменьшается, если было больше, и УВЕЛИЧИВАЕТСЯ, если было
   меньше (маленькие/низкого разрешения фото раньше показывались в своём
   исходном мелком размере — теперь дотягиваются до полной высоты). Для
   нормального фото рабочая сторона — высота (контейнер даёт одну и ту же
   высоту всем фото), а для панорамного/широкого, которому не хватает
   ширины контейнера, — высота фото уменьшается пропорционально, чтобы не
   вылезти за 90vw. */
/* position:relative — точки (.hotspot, см. project-page.css/shared.css)
   позиционируются в процентах именно от этого контейнера, как .hotspot от
   .main-viewer в обычной карусели (см. site.js::renderHotspots()). Фото
   рендерится JS не прямо сюда, а во вложенный #lb-media-img (100%×100%
   этого контейнера) — чтобы смена слайда (замена innerHTML фото) не стирала
   соседний #lb-hotspots. */
.lb-media{position:relative;width:90vw;height:calc(90vh - 112px);display:flex;align-items:center;justify-content:center;overflow:hidden;-webkit-user-select:none;user-select:none;touch-action:none}
#lb-media-img{width:100%;height:100%}
.lb-media img,.lb-media video{width:100%;height:100%;object-fit:contain;display:block}
.lb-badge{color:var(--text-inverse);font-family:var(--mono);font-size:12px;margin-top:16px;letter-spacing:.03em;text-align:center;max-width:90vw;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* Стрелки пролистывания — рядом с лентой миниатюр, не поверх фото (было
   position:absolute по бокам .lightbox — мешало свайпу/зуму по фото, легко
   промахнуться и задеть стрелку вместо зума, запрос 2026-08-13). Тот же
   приём, что у .tscroll/.tstrip в обычной (не fullscreen) карусели выше в
   этом файле. */
.lb-tstrip-row{display:flex;align-items:center;gap:8px;margin-top:14px;max-width:90vw}
.lb-nav{flex:0 0 auto;width:32px;height:48px;border-radius:8px;background:color-mix(in srgb,var(--text-on-accent) 10%,transparent);border:1px solid color-mix(in srgb,var(--text-on-accent) 20%,transparent);color:var(--text-inverse);font-size:18px;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:.15s}
.lb-nav:hover{background:color-mix(in srgb,var(--text-on-accent) 20%,transparent)}
.lb-tstrip{display:flex;gap:8px;overflow-x:auto;padding:4px;scrollbar-width:none;flex:1;min-width:0}
.lb-tstrip::-webkit-scrollbar{display:none}
.lb-titem{width:56px;height:56px;border-radius:6px;overflow:hidden;border:2px solid transparent;cursor:pointer;flex:0 0 auto;opacity:.55;transition:.15s,transform .2s ease;transform:scale(.86)}
.lb-titem img{width:100%;height:100%;object-fit:cover;display:block}
.lb-titem.on{border-color:var(--accent);opacity:1;transform:scale(1)}
.lb-titem:hover{opacity:1}

/* Мобильный fullscreen — media-fit во всю ширину экрана (запрос 2026-08-13),
   без бокового отступа .lightbox (padding убран только по горизонтали —
   верх/низ остаётся, под кнопку закрытия/бейдж). .lb-badge/.lb-tstrip-row
   намеренно НЕ растянуты на 100vw — им отступ по бокам не мешает и даже
   читабельнее, только у самого фото требовалась полная ширина. */
@media(max-width:620px){
  .lb-close{top:10px;right:14px}
  .lb-nav{width:36px;height:44px;font-size:18px}
  .lightbox{padding-left:0;padding-right:0}
  .lb-media{width:100vw}
}
