/* ═══════════════════════════════════════════════════════════════════════
   PORTFOLIO-CASE.CSS — Codex Studio v0.5
   ──────────────────────────────────────────────────────────────────────
   Стили, нужные ТОЛЬКО когда пользователь открыл кейс (lazy-loaded).
   Содержит: case-view, case-item, case-row, case-text, case-share,
   case-progress, case-tabs, case-nav, case-3d, case-blueprints,
   bp-export, mobile case-view, fullscreen overlay (media-fs),
   .work-card--active, .is-clip-reveal*.

   ВАЖНО: подключать ПОСЛЕ shared.css и portfolio-core.css. Опирается
   на токены из tokens.css и базовые стили work-card из shared.css.

   v0.5 [#3]: вынесено из main.css. Free-assets.html этот файл НЕ грузит.
   Split-out: вынесено из portfolio.css ради LCP — case-view изначально
   hidden, эти стили не нужны до клика по карте.
   ═══════════════════════════════════════════════════════════════════════ */

/* ═══════════════════════════════════════════════════════════════════════
   CASE VIEW — полноформатный кейс (v0.6: вертикальный скролл)
   ──────────────────────────────────────────────────────────────────────
   Структура:
     .case-view (flex column, padding 64px 64px 0)
       .case-view__header  — тайтл + мета + табы 2D / 3D / Blueprints
       .case-progress      — тонкая полоса прогресса (ВНЕ маски)
       .case-scroll        — flex:1, overflow-y:auto + top mask
         .case-scroll__track — flex column, gap 64px
           .case-item — wide (100 %) или tall (50 %)
═══════════════════════════════════════════════════════════════════════ */
.case-view {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  /* v0.15.4 [П4] — desktop top 64→16 (− 48px). Горизонтальные 64px сохранены. */
  padding: 16px 64px 0;
  gap: var(--space-4);
  box-sizing: border-box;
  overflow: hidden;
  /* v0.8.5: position:relative смержен из дубль-объявления (бывший L373)
     для абсолютного позиционирования .case-scroll-hint ниже. */
  position: relative;
}

@media (max-width: 1100px) {
  .case-view {
    padding: var(--space-8) var(--space-8) 0;
    gap: var(--space-3);
  }
}

/* ─── HEADER ─── */
/* v0.15.3 [П3] — desktop: align-items flex-start → flex-end.
   actions (tabs + case-nav) прижимаются к нижнему краю title. */
.case-view__header {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--space-6);
  flex-shrink: 0;
}
.case-view__left { min-width: 0; }
.case-view__meta {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-bottom: var(--space-2);
  flex-wrap: wrap;
}
.case-view__cat {
  font-family: var(--font-body);
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-accent-text);
}
.case-view__sep {
  color: var(--color-text-faint);
  font-size: var(--text-xs);
}
.case-view__year {
  font-family: var(--font-body);
  font-size: var(--text-xs);
  color: var(--color-text-faint);
  letter-spacing: 0.06em;
}
.case-view__title {
  font-family: var(--font-display);
  font-size: var(--text-2xl);
  font-weight: 600;
  color: var(--color-text);
  line-height: 1.1;
  letter-spacing: -0.01em;
}

/* v0.21.4 — Desktop ≥1024px: tightening case-view header.
   Размещено ПОСЛЕ базового правила сверху, чтобы CSS cascade override
   действительно сработал (предыдущие v0.21.2 / v0.21.3 были выше базы
   в файле и проигрывали по source-order при равной специфичности).

   .case-view__header уже align-items: flex-end — buttons row выровнен
   по нижнему краю flex-контейнера. Только line-height: 1 (вместо 1.1)
   убирает ~5px line-leading ниже descender'а h1. Этого достаточно:
   buttons border-bottom попадает в район visual descender title,
   gap до case-progress separator остаётся комфортным ~14-15px (через
   case-view gap: var(--space-4)).

   v0.21.5 — Откат margin-bottom: -0.45em (был слишком aggressive,
   схлопывал header так что title визуально упирался в separator,
   особенно на cold start без SplitText когда h1 element height равен
   font-size без extra padding'а от .case-title__word). Tablet/mobile
   блоки ниже не задеваем. */
@media (min-width: 1024px) {
  .case-view__title {
    line-height: 1;
  }
}

/* ─── CASE VIEW ACTIONS (v0.10, v0.15.2 [B2]) ───
   v0.15.2 [B2]: Contact pill ушла в .site-footer, case-view__actions теперь
   содержит только .case-view__tabs (внутри которого табы + case-nav).
   Одиночный дочерний блок — flex-direction не критичен. */
.case-view__actions {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: var(--space-2);
  flex-shrink: 0;
}

/* ─── CASE NAV (v0.10, v0.14.0 [11]): стрелки prev/next + счётчик ───
   v0.14.0 [11]: кнопки 28→36px, counter font-size: text-sm (был text-xs).
   Сама оболочка .case-nav подросла с ~34→~44px (visual weight на линии с .case-tab 32px).
   Свет-подсветка при hover уплотнена (bg=surface-offset вместо surface-2) для чёткого feedback. */
/* v0.15.2 [B1]: case-nav перенесён в .case-view__tabs.
   Высота 32px = .case-tab (было ~44px с паддингом). Кнопки 30×30 внутри (было 36×36). */
.case-nav {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  padding: 1px;
  height: 32px;
  box-sizing: border-box;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-tag);
  background: color-mix(in srgb, var(--color-surface-2) 54%, transparent);
}
.case-nav__btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 28px;
  background: transparent;
  border: none;
  border-radius: calc(var(--radius-tag) - 2px);
  color: var(--color-text-muted);
  cursor: pointer;
  transition:
    color 160ms var(--ease-out),
    background 160ms var(--ease-out),
    transform 160ms var(--ease-out);
}
/* v0.15.1 [1.3] — hover только для fine pointer (desktop мышь). На touch-устройствах
   без этого ограничения после tap :hover «залипает» (#case-prev показывает bg,
   а #case-next — нет). Итог: обе кнопки на mobile выглядят одинаково в default или tap. */
@media (hover: hover) and (pointer: fine) {
  .case-nav__btn:hover:not(:disabled) {
    color: var(--color-text);
    background: var(--color-surface-offset);
  }
}
.case-nav__btn:active:not(:disabled) {
  transform: scale(0.94);
}
.case-nav__btn:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}
.case-nav__btn:disabled {
  opacity: 0.3;
  cursor: not-allowed;
}
.case-nav__btn svg {
  display: block;
  /* v0.15.2 [B1] — svg шевроны 18→14px под новые 30×28 кнопки. */
  width: 14px;
  height: 14px;
}
.case-nav__counter {
  font-family: var(--font-body);
  /* v0.15.2 [B1] — text-sm→text-xs для паритета с лейблами .case-tab. */
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: 0.06em;
  color: var(--color-text-muted);
  min-width: 48px;
  text-align: center;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* ─── 2D / 3D / BLUEPRINTS TABS + CASE NAV (v0.15.2 [B1]) ───
   v0.15.2 [B1]: .case-nav перемещён внутрь .case-view__tabs, после Blueprints.
   Desktop: выравнивание по правому краю (flex-end), case-nav 32px (= .case-tab).
   Mobile: вся группа от края до края, gap 8px. См. @media max-width:767 ниже. */
.case-view__tabs {
  display: flex;
  gap: var(--space-2);
  flex-shrink: 0;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
}
.case-view__tablist {
  display: flex;
  gap: var(--space-2);
  flex-wrap: wrap;
  align-items: center;
}
.case-tab {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  height: 32px;
  padding: 0 var(--space-3);
  background: transparent;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-tag);
  color: var(--color-text-muted);
  font-family: var(--font-body);
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  cursor: pointer;
  box-shadow: 0 0 0 0 transparent;
  transition:
    color 160ms var(--ease-out),
    border-color 160ms var(--ease-out),
    background 160ms var(--ease-out),
    box-shadow 160ms var(--ease-out);
}
/* v0.8.5: .case-tab--soon, .case-tab__badge удалены — классы не
   присутствуют в DOM (3 таба 2D/3D/Blueprints всегда активны).
   :not(.case-tab--soon) из :hover тоже убран. */
.case-tab:hover {
  color: var(--color-text);
  border-color: var(--color-text-muted);
}
.case-tab:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}
.case-tab--active {
  color: var(--color-text);
  border-color: var(--color-primary);
  background: var(--color-primary-highlight);
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--color-primary) 42%, transparent) inset;
}

/* ═══════════════════════════════════
   v0.2.3 [П2] — CASE SHARE (Copy link to case)
   Две кнопки: .case-share--desktop (в .case-view__tabs) и
   .case-share--mobile (в .case-mobile-bar__row). Каждая видима
   только на своём brekpoint. Паритет стиля с .case-tab.
═══════════════════════════════════ */
/* v0.7.12 [UX] — accent: border + icon = --color-primary; text = --color-text.
   WCAG: text=color-text сохраняет ≥4.5:1 на обоих темах; border+icon в primary
   проходят non-text AA (≥3:1). Hover усиливает primary до --color-primary-hover
   и добавляет --color-primary-highlight tint. */
.case-share {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  height: 32px;
  padding: 0 var(--space-3);
  background: transparent;
  border: 1px solid var(--color-primary);
  border-radius: var(--radius-tag);
  color: var(--color-text);
  font-family: var(--font-body);
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  cursor: pointer;
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--color-primary) 18%, transparent) inset;
  transition:
    color 160ms var(--ease-out),
    border-color 160ms var(--ease-out),
    background 160ms var(--ease-out),
    box-shadow 160ms var(--ease-out);
}
@media (hover: hover) and (pointer: fine) {
  .case-share:hover {
    color: var(--color-text);
    border-color: var(--color-primary-hover);
    background: var(--color-primary-highlight);
  }
}
.case-share:active { transform: scale(0.97); }
.case-share:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}
.case-share svg { flex-shrink: 0; }
.case-share--copied {
  color: var(--color-primary);
  border-color: var(--color-primary);
  background: var(--color-primary-highlight);
}

/* Desktop: показываем .case-share--desktop в ряду с табами;
   mobile-версия скрыта в мобильном bar'е. */
.case-share--mobile { display: none; }
.case-share--desktop { display: inline-flex; }

/* ═══════════════════════════════════
   PROGRESS BAR — тонкая полоса НАД маской
═══════════════════════════════════ */
.case-progress {
  flex-shrink: 0;
  height: 2px;
  background: var(--color-divider);
  border-radius: 1px;
  overflow: hidden;
  position: relative;
}
.case-progress__bar {
  height: 100%;
  width: 0%;
  background: var(--color-primary);
  border-radius: 1px;
  transition: width 120ms linear;
  will-change: width;
}

/* ═══════════════════════════════════
   VERTICAL SCROLL — контейнер с маской сверху
═══════════════════════════════════ */
.case-scroll {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;

  /* scroll-behavior: smooth — snap убран в v0.8 */

  /* Маска сверху — плавно растворяет содержимое, скроллящееся вверх */
  -webkit-mask-image: linear-gradient(
    to bottom,
    transparent 0,
    #000 56px,
    #000 100%);
  mask-image: linear-gradient(
    to bottom,
    transparent 0,
    #000 56px,
    #000 100%);

  /* Скроллбар — тонкий */
  scrollbar-width: thin;
  scrollbar-color: var(--color-border) transparent;
}
.case-scroll::-webkit-scrollbar        { width: 4px; }
.case-scroll::-webkit-scrollbar-track  { background: transparent; }
.case-scroll::-webkit-scrollbar-thumb  {
  background: var(--color-border);
  border-radius: 2px;
}
.case-scroll:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: -2px;
}

/* ═══════════════════════════════════════════════════════════════════════
   v0.6 [Z7] — Scroll hint chevron
   ─────────────────────────────────────────────────────────
   Тонкая стрелка вниз, абсолютно позиционирована к низу .case-view.
   Появляется при первом открытии кейса (3 цикла мигания с задержкой 1.5s),
   гасится через .has-scrolled класс на .case-scroll при первом scroll-action.
   Использует реальный DOM-element (создаётся в main.js openCase) — pseudo-element
   с position: sticky внутри overflow:auto + mask-image нестабильно в Chromium.
   ВАЖНО: translateY указан ДО rotate в transform — иначе стрелка дрожит
   по диагонали (translateY после rotate работает в локальной системе координат).
═══════════════════════════════════════════════════════════════════════ */
/* v0.8.5: дубль `.case-view { position: relative }` смержен в основной
   блок на L27. position:relative нужен для абсолютного позиционирования
   .case-scroll-hint ниже. */
.case-scroll-hint {
  position: absolute;
  bottom: var(--space-4);
  left: 50%;
  width: 18px;
  height: 18px;
  border-right: 2px solid var(--color-text);
  border-bottom: 2px solid var(--color-text);
  transform: translate(-50%, 0) rotate(45deg);
  opacity: 0;
  pointer-events: none;
  z-index: 5;
  animation: case-scroll-hint 1.6s ease-in-out 1.2s 3 forwards;
}
/* v0.8.5: .case-scroll-hint.is-hidden удалён — класс нигде не toggle'ится
   в JS. Скрытие происходит через .case-scroll.has-scrolled (~). */
.case-scroll.has-scrolled ~ .case-scroll-hint {
  display: none;
}
@keyframes case-scroll-hint {
  0%, 100% {
    opacity: 0;
    transform: translate(-50%, -6px) rotate(45deg);
  }
  50% {
    opacity: 0.85;
    transform: translate(-50%, 6px) rotate(45deg);
  }
}
@media (prefers-reduced-motion: reduce) {
  .case-scroll-hint { display: none; }
}

.case-scroll__track {
  display: flex;
  flex-direction: column;
  gap: 64px;
  padding-top: 24px;
  padding-bottom: 64px;
}

/* ═════════════════════════════════════
   CASE ROW — контейнер для одного логического блока (row).
   Варианты:
   • --wide        — 1 horizontal media
   • --tall-1      — 1 vertical media (слева)
   • --tall-2      — 2 vertical media в ряд (50/50)
   • --tall-text   — 1 vertical media + text (top-aligned)
   • --text        — full-width text block
═════════════════════════════════════ */
.case-row {
  display: flex;
  flex-direction: row;
  align-items: flex-start;
  gap: 48px;
  width: 100%;
}
.case-row--wide,
.case-row--text { flex-direction: column; gap: 0; }
.case-row--tall-1 { justify-content: flex-start; }
.case-row > .case-item { width: 100%; }

/* tall-2 — две вертикальные 50/50 */
.case-row--tall-2 > .case-item--tall { flex: 1 1 0; min-width: 0; }

/* tall-1 — одна вертикальная на всю ширину case-трека (v0.9: media внутри ограничен своим max-width 1022px) */
.case-row--tall-1 > .case-item--tall { flex: 1 1 100%; }

/* tall-text — вертикальная слева, текст справа выровнен по верху */
.case-row--tall-text > .case-item--tall { flex: 0 1 calc(50% - 24px); }
.case-row--tall-text > .case-item--text-inline {
  flex: 1 1 calc(50% - 24px);
  min-width: 0;
  padding-top: var(--space-2);
}
.case-text--inline {
  padding: 0;
  border: 0;
  max-width: 48ch;
}
.case-text--inline .case-text__title { font-size: var(--text-xl); }

/* ═══════════════════════════════════
   CASE ITEM — карточка иллюстрации / видео + подпись
   Начальное состояние скрыто — GSAP делает lift-анимацию.
═══════════════════════════════════ */
.case-item {
  min-width: 0;
  flex-shrink: 0;
}

/* MEDIA — контейнер для <img> / <video> / placeholder */
.case-item__media {
  width: 100%;
  border-radius: var(--radius-card);
  overflow: hidden;
  background: var(--color-surface);
  position: relative;
}
/* Ограничиваем высоту медиа, чтобы caption всегда помещался в экране.
   4K-экраны: без max-height wide-иллюстрации становятся слишком высокими
   и caption уходит ниже viewport. */
/* v0.6 [Z3] — Wide: aspect-ratio 16:9 + clamp на max-height.
   Раньше: жёсткий height: 1040px → на 4K caption уезжал ниже viewport,
   на 14"-15" ноутбуках 1040px было избыточно высоко.
   Теперь: aspect-ratio держит форму, max-height ограничен 60vh с потолком 1040px.
   Mobile override (@768px) использует aspect-ratio 16/9 — не пересекается. */
.case-item--wide .case-item__media {
  width: 100%;
  aspect-ratio: 16 / 9;
  height: auto;
  max-height: clamp(480px, 60vh, 1040px);
}
/* v0.6 [Z3] — Tall: aspect-ratio 4:5 + clamp на max-height.
   Раньше: жёсткий height: 1100px → на 14"-15" ноутбуках занимал больше viewport.
   Теперь: aspect-ratio 4:5 держит форму, max-height clamp 70vh потолок 1100px.
   Mobile override (@768px) использует aspect-ratio 4/5 + max-height calc(100vh - 180px). */
.case-item--tall .case-item__media {
  width: 100%;
  max-width: 1022px;
  aspect-ratio: 4 / 5;
  height: auto;
  max-height: clamp(520px, 70vh, 1100px);
}

/* ══════════════════════════════════════════════════════════════════════════
   v0.7.10 [tall-2-stretch] — переопределение для tall-2 media: убираем
   max-width и max-height, чтобы media растягивалась до полной ширины item.
   ──────────────────────────────────────────────────────────────────────────
   Контекст: default `.case-item--tall .case-item__media max-width: 1022px`
   нужен для tall-1 (одна media full-width track) и tall-text (50/50 split с
   text). В этих row-типах media по дизайну ограничена 1022.

   Но в tall-2 (две media side-by-side, flex 1 1 0) cap 1022 на media создаёт
   проблему: на 2K+ COLLAPSED item шире 1022, media упирается в cap, справа
   от media появляется void внутри item. Visual gap между media скачет:
   - 2560 OPEN:      48px (item=media=1022, no void) ✓
   - 2560 COLLAPSED: 190px (item=1164, media=1022, +142 void) ❌
   - 4K COLLAPSED:   830px (item=1804, media=1022, +782 void) ❌

   Решение: media растягивается на полную ширину item. Gap всегда 48,
   right edge of right media = case-view padding 64.

   max-height: none — без него aspect-ratio 4:5 ломалось бы на больших
   item width (max-height clamp 1100 ограничивал бы высоту, image становился
   pancake). Без cap на height, image держит 4:5 на любой ширине; чуть-чуть
   overflow viewport на 4K COLLAPSED, но case-scroll скроллится.

   Specificity: .case-row--tall-2 .case-item--tall .case-item__media = (0,3,0)
   override default = (0,2,0).

   Range: применяется глобально, но эффект виден только на ≥2K (на меньших
   viewport item никогда не достигал 1022, cap не активен).
   ══════════════════════════════════════════════════════════════════════════ */
.case-row--tall-2 .case-item--tall .case-item__media {
  max-width: none;
  max-height: none;
}

.case-row--motion-wide {
  flex-direction: column;
  gap: 0;
}
.case-row--motion-halves > .case-motion--half {
  flex: 1 1 0;
  min-width: 0;
}
.case-motion__media {
  width: 100%;
  aspect-ratio: 16 / 9;
  max-height: clamp(420px, 58vh, 960px);
}
.case-motion--half .case-motion__media {
  max-height: none;
}
.case-motion__video {
  z-index: 3;
}
.case-motion__poster,
.case-motion__vimeo,
.case-motion__iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
}
.case-motion__poster {
  z-index: 2;
  background-position: center;
  background-size: cover;
  pointer-events: none;
}
.case-motion__vimeo {
  z-index: 3;
  background: transparent;
}
.case-motion__iframe {
  border: 0;
  background: transparent;
}
.case-motion__control {
  position: absolute;
  right: var(--space-3);
  bottom: var(--space-3);
  z-index: 4;
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  height: 32px;
  padding: 0 var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-tag);
  background: color-mix(in srgb, var(--color-surface-2) 78%, transparent);
  color: var(--color-text);
  font-family: var(--font-body);
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  cursor: pointer;
  backdrop-filter: blur(12px);
  transition:
    background 160ms var(--ease-out),
    border-color 160ms var(--ease-out),
    color 160ms var(--ease-out),
    transform 160ms var(--ease-out);
}
.case-motion__control:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}
@media (hover: hover) and (pointer: fine) {
  .case-motion__control:hover {
    border-color: var(--color-primary);
    background: var(--color-primary-highlight);
  }
}
.case-motion__control:active {
  transform: scale(0.96);
}
.case-motion__control-dot {
  width: 0.58em;
  height: 0.58em;
  border-radius: 999px;
  background: currentColor;
  box-shadow: 0 0 0 3px color-mix(in srgb, currentColor 18%, transparent);
}
.case-motion[data-motion-playing="false"] .case-motion__control-dot {
  background: transparent;
  box-shadow: 0 0 0 1px currentColor inset;
}

/* TEXT BLOCK (full-width) — на всю ширину блока кейса, с border-top/bottom.
   Идёт в начале каждого кейса — intro тон. */
.case-item--text {
  width: 100%;
}
.case-text {
  /* v0.13.8 — full-width intro: контейнер на всю ширину case-трека,
     читаемая ширина ограничена только у тела текста (.case-text__body). */
  width: 100%;
  padding: var(--space-6) 0;
  border-top: 1px solid var(--color-divider);
  border-bottom: 1px solid var(--color-divider);
}
.case-text__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  flex-wrap: wrap;
  margin-bottom: var(--space-3);
}
.case-text__header-left {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  flex-wrap: wrap;
  min-width: 0;
}
/* v0.13.8 — external link button (ArtStation / Behance) в правой части header.
   v0.13.8.1 — отступ 64px от правого края case-трека (margin-right: 64px). */
.case-text__external-btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: 32px;
  padding: 0 14px;
  margin-right: 64px;
  font-family: var(--font-body);
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-text);
  background: var(--color-surface-2);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-tag);
  text-decoration: none;
  white-space: nowrap;
  flex-shrink: 0;
  line-height: 1;
  transition: background 160ms var(--ease-out), border-color 160ms var(--ease-out), color 160ms var(--ease-out);
}
.case-text__external-btn:hover {
  background: var(--color-surface-offset);
  border-color: var(--color-accent-text);
  color: var(--color-accent-text);
}
.case-text__external-btn:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}
.case-text__external-btn-arrow {
  font-size: 1.1em;
  line-height: 1;
  transition: transform 160ms var(--ease-out);
}
.case-text__external-btn:hover .case-text__external-btn-arrow {
  transform: translateX(2px);
}
.case-text__eyebrow {
  font-family: var(--font-body);
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-primary);
  margin: 0;
}
.case-text__meta {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex-wrap: wrap;
}
.case-text__meta-item {
  font-family: var(--font-body);
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-text-muted);
  padding: 4px 10px;
  border: 1px solid var(--color-divider);
  border-radius: 999px;
  white-space: nowrap;
}
.case-text__meta-item--role {
  color: var(--color-text);
  /* v0.7.11 [P2 #13] — было #3f3f3f, заменено на ближайший токен --color-divider (#404040, Δ1).
     Цель прежняя: role-чип совпадает по обводке с другими метками (дата/стэк). */
  border-color: var(--color-divider);
}
.case-text__title {
  font-family: var(--font-display);
  font-size: var(--text-2xl);
  font-weight: 500;
  letter-spacing: -0.01em;
  line-height: 1.15;
  color: var(--color-text);
  margin-bottom: var(--space-4);
}
.case-text__body {
  font-family: var(--font-body);
  font-size: var(--text-base);
  line-height: 1.7;
  color: var(--color-text-muted);
  /* v0.13.8 — читаемая ширина сохранена только на самом тексте */
  max-width: 72ch;
}

.case-item__img,
.case-item__video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: 2;
  display: block;
  pointer-events: none;
}
.case-item__video { pointer-events: auto; }
/* v0.20.1 — img снова кликабельна (gallery fullscreen trigger,
   .closest('[data-gallery] img') в main.js delegated click handler
   из коммита eebae22). Раньше pointer-events:none блокировал клики
   на img, и FLIP-viewer не активировался. */
.case-item__img { pointer-events: auto; }

/* v0.13.6 — SplitText-маска для H1 кейса.
   SplitText ставит каждый символ в inline-block-спанс .case-title__char
   и каждое слово в .case-title__word. yPercent:100 из GSAP поднимает
   char из-под нижней границы слова — нужен overflow:hidden на word.
   Пробелы между словами SplitText сам оставляет. */
.case-title__word {
  display: inline-block;
  overflow: hidden;
  padding-bottom: 0.05em;  /* защита от обрезки хвостов g, y, p у Clash Display */
}
.case-title__char {
  display: inline-block;
  will-change: transform;  /* только на время анимации — GSAP снимает в onComplete */
}
/* Reduced-motion: отключаем маску чтобы IIFE-early-return не скрыл текст */
@media (prefers-reduced-motion: reduce) {
  .case-title__word { overflow: visible; }
}

/* v0.13.5 — clip-path reveal для медиа внутри case-item.
   Закрытое состояние только при no-preference, reduced видит сразу. */
@media (prefers-reduced-motion: no-preference) {
  .case-item__media img.is-clip-reveal-case,
  .case-item__media video.is-clip-reveal-case,
  .case-motion__poster.is-clip-reveal-case {
    clip-path: inset(0 100% 0 0);
  }
}

.case-item__placeholder {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-display);
  font-size: var(--text-sm);
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--color-text-faint);
  pointer-events: none;
  z-index: 1;
}

/* CAPTION — label + описание */
.case-item__caption {
  margin-top: var(--space-4);
  padding-inline: var(--space-1);
  max-width: 72ch;
}
.case-item__caption-label {
  font-family: var(--font-display);
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--color-text);
  line-height: 1.3;
  margin-bottom: var(--space-1);
  letter-spacing: -0.005em;
}
.case-item__caption-desc {
  font-family: var(--font-body);
  font-size: var(--text-xs);
  color: var(--color-text-muted);
  line-height: 1.6;
}

/* ═══════════════════════════════════
   BLUEPRINTS VIEW (v0.10) — технический чертёж
   Dark canvas, primary-color grid + dimension lines,
   моноширинный стиль за счёт tabular-nums + letter-spacing.
═══════════════════════════════════ */
.case-blueprints {
  flex: 1;
  min-height: 0;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  padding: 12px 0 24px;
  gap: 10px;
}
.case-blueprints[hidden] { display: none; }

/* v0.13.8 — export toolbar above blueprint canvas
   v0.15.1 [2.3] — gap: 10px для пары [Export SVG] [fs-btn] */
.case-blueprints__toolbar {
  flex: 0 0 auto;
  display: flex;
  justify-content: flex-end;
  align-items: center;
  gap: 10px;
}
.bp-export-btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 36px;
  padding: 8px 14px;
  font-family: var(--font-body);
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-text);
  background: var(--color-surface-2);
  border: 1px solid var(--color-border);
  border-radius: 4px;
  cursor: pointer;
  transition: background 180ms var(--ease-out), border-color 180ms var(--ease-out), color 180ms var(--ease-out);
}
.bp-export-btn:hover {
  background: var(--color-surface-offset);
  border-color: var(--color-accent-text);
  color: var(--color-accent-text);
}
.bp-export-btn:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}
.bp-export-btn[disabled] {
  opacity: 0.5;
  cursor: not-allowed;
}
.bp-export-btn__icon {
  width: 14px;
  height: 14px;
  flex: 0 0 14px;
  color: currentColor;
}
.bp-export-btn__label { line-height: 1; }
@media (max-width: 768px) {
  .bp-export-btn { min-height: 44px; padding: 10px 14px; }
}

.case-blueprints__canvas {
  position: relative;          /* positioning context для pager-overlay */
  flex: 1;
  min-height: 0;
  overflow: hidden;
  /* v0.22.2 — рамка/bg/сетка переехали на .case-blueprints__page-canvas,
     чтобы сетка визуально доходила до краёв canvas на широких экранах (4K)
     где SVG xMidYMid meet оставляет letterbox по бокам. */
}

/* v0.22 — Multi-page Blueprints
   ─────────────────────────────────────────────────────────────────
   На desktop одна .case-blueprints__page активна (is-current) и
   занимает всю canvas. На mobile все страницы выводятся колонкой
   (см. media max-width:767 ниже). Per-page тулбар скрыт на desktop. */
.case-blueprints__page {
  display: none;
  flex-direction: column;
  width: 100%;
  height: 100%;
  min-height: 0;
}
.case-blueprints__page.is-current { display: flex; }
.case-blueprints__page-canvas {
  position: relative;
  flex: 1;
  min-height: 0;
  display: flex;
  align-items: stretch;
  justify-content: stretch;
  border: 1px solid var(--color-divider);
  border-radius: 4px;
  overflow: hidden;
  /* v0.22.2 — CSS-сетка фоном: тянется до краёв page-canvas даже на 4K,
     где SVG xMidYMid meet оставляет letterbox по бокам. Цвета/частота
     соответствуют SVG-сетке (.blueprint__grid-minor/major) — оба слоя
     накладываются внутри viewBox и сливаются визуально. */
  background:
    repeating-linear-gradient(to right,  var(--bp-grid-major) 0 1px, transparent 1px 100px),
    repeating-linear-gradient(to bottom, var(--bp-grid-major) 0 1px, transparent 1px 100px),
    repeating-linear-gradient(to right,  var(--bp-grid-minor) 0 1px, transparent 1px 20px),
    repeating-linear-gradient(to bottom, var(--bp-grid-minor) 0 1px, transparent 1px 20px),
    radial-gradient(ellipse at top, var(--color-3d-canvas-glow) 0%, transparent 70%),
    var(--color-bg);
}
.case-blueprints__page-canvas svg {
  display: block;
  width: 100%;
  height: 100%;
}
.case-blueprints__page-toolbar {
  display: none;       /* desktop: per-page тулбар скрыт, используется верхний */
}

/* v0.22.3 — Title-block HTML-оверлей: позиционируется по правому-нижнему
   углу .case-blueprints__page-canvas (16px от краёв), не уезжает в SVG
   letterbox на широких экранах. Визуал 1:1 со старой SVG-версией.
   Для экспортированного .svg блок рендерится внутри SVG (см. buildBlueprintSVG
   с forExport:true). */
.case-blueprints__title-block {
  position: absolute;
  right: 16px;
  bottom: 16px;
  width: 320px;
  max-width: calc(100% - 32px);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: 3px;
  z-index: 2;
  pointer-events: none;
  user-select: none;
  font-variant-numeric: tabular-nums;
}
.case-blueprints__title-block-top {
  padding: 8px 12px;
  border-bottom: 1px solid var(--color-border);
}
.case-blueprints__title-block-bottom {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
}
.case-blueprints__title-block-cell {
  padding: 6px 12px;
  border-left: 1px solid var(--color-border);
  min-width: 0;
}
.case-blueprints__title-block-cell:first-child { border-left: none; }
.case-blueprints__title-block-key {
  display: block;
  font-family: var(--font-body);
  font-size: 8px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-text-faint);
  line-height: 1.2;
}
.case-blueprints__title-block-project {
  display: block;
  font-family: var(--font-display);
  font-size: 14px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-primary);
  margin-top: 4px;
  line-height: 1.1;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.case-blueprints__title-block-val {
  display: block;
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.04em;
  color: var(--color-text);
  margin-top: 4px;
  line-height: 1.1;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Pager overlay — стрелки + counter поверх canvas (desktop, при N>1). */
.case-blueprints__pager[hidden] { display: none; }
.case-blueprints__pager-btn {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  padding: 0;
  background: var(--color-fs-close-bg);
  border: 1px solid var(--color-fs-close-border);
  border-radius: 3px;
  color: var(--color-fs-close-text);
  cursor: pointer;
  z-index: 4;
  transition: color 160ms var(--ease-out), border-color 160ms var(--ease-out), opacity 200ms var(--ease-out);
}
.case-blueprints__pager-btn--prev { left: 16px; }
.case-blueprints__pager-btn--next { right: 16px; }
@media (hover: hover) and (pointer: fine) {
  .case-blueprints__pager-btn:hover {
    color: var(--color-fs-close-text-hover);
    border-color: var(--color-fs-close-border-hover);
  }
}
.case-blueprints__pager-btn:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}
.case-blueprints__pager-btn svg {
  width: 16px;
  height: 16px;
  display: block;
}
.case-blueprints__pager-counter {
  position: absolute;
  bottom: 16px;
  left: 50%;
  transform: translateX(-50%);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: 0.1em;
  color: var(--color-text);
  opacity: 0.6;
  pointer-events: none;
  user-select: none;
  font-variant-numeric: tabular-nums;
  z-index: 3;
}

/* Сетка */
/* v0.13.8.3 GOLDEN — grid через токены (в light усилены для читаемости) */
.blueprint__grid-minor { stroke: var(--bp-grid-minor); stroke-width: 0.5; fill: none; }
.blueprint__grid-major { stroke: var(--bp-grid-major); stroke-width: 1;   fill: none; }

/* Части — прямоугольники деталей */
.blueprint__part {
  fill: none;
  stroke: var(--color-primary);
  stroke-width: 1.2;
  vector-effect: non-scaling-stroke;
}
.blueprint__part-label {
  fill: var(--color-text-muted);
  font-family: var(--font-body);
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  font-variant-numeric: tabular-nums;
}

/* Размерные линии */
.blueprint__dim-line,
.blueprint__dim-ext {
  stroke: var(--color-text-muted);
  stroke-width: 0.8;
  fill: none;
}
.blueprint__dim-ext { stroke-dasharray: 2 3; opacity: 0.5; }
.blueprint__dim-arrow { fill: var(--color-text-muted); stroke: none; }
.blueprint__dim-label {
  fill: var(--color-text);
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.04em;
  font-variant-numeric: tabular-nums;
  text-anchor: middle;
}
.blueprint__dim-label-bg {
  fill: var(--color-bg);
}

/* Коллауты — нумерованные аннотации */
.blueprint__callout-leader {
  stroke: var(--color-primary);
  stroke-width: 0.8;
  fill: none;
}
.blueprint__callout-circle {
  fill: var(--color-bg);
  stroke: var(--color-primary);
  stroke-width: 1.2;
}
.blueprint__callout-num {
  fill: var(--color-primary);
  font-family: var(--font-body);
  font-size: 10px;
  font-weight: 600;
  text-anchor: middle;
  dominant-baseline: central;
  font-variant-numeric: tabular-nums;
}
.blueprint__callout-label {
  fill: var(--color-text-muted);
  font-family: var(--font-body);
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

/* Title block — правый нижний угол */
.blueprint__title-block-frame {
  fill: var(--color-surface);
  stroke: var(--color-border);
  stroke-width: 1;
}
.blueprint__title-block-divider {
  stroke: var(--color-border);
  stroke-width: 0.5;
}
.blueprint__title-block-key {
  fill: var(--color-text-faint);
  font-family: var(--font-body);
  font-size: 8px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}
.blueprint__title-block-val {
  fill: var(--color-text);
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.04em;
  font-variant-numeric: tabular-nums;
}
.blueprint__title-block-project {
  fill: var(--color-primary);
  font-family: var(--font-display);
  font-size: 14px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.blueprint__view-tag {
  fill: var(--color-text-faint);
  font-family: var(--font-body);
  font-size: 9px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
}

/* Анимация раскрытия — управляется через JS, но базовое поведение в CSS */
@media (prefers-reduced-motion: reduce) {
  .case-blueprints svg * { animation: none !important; }
}

/* ═══════════════════════════════════
   3D VIEW (v0.11) — Google <model-viewer>
   Размеры и отступы точно как у Blueprints.
═══════════════════════════════════ */
.case-3d {
  flex: 1;
  min-height: 0;
  overflow: hidden;
  display: flex;
  padding: 12px 0 24px;
}
.case-3d[hidden] { display: none; }

.case-3d__canvas {
  position: relative;
  flex: 1;
  min-height: 0;
  border: 1px solid var(--color-divider);
  border-radius: 4px;
  background:
    radial-gradient(ellipse at top, var(--color-3d-canvas-glow) 0%, transparent 70%),
    var(--color-3d-canvas-bg);
  overflow: hidden;
}

.case-3d__canvas.is-switching-3d::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 5;
  pointer-events: none;
  background:
    radial-gradient(ellipse at top, var(--color-3d-canvas-glow) 0%, transparent 70%),
    var(--color-3d-canvas-bg);
}

/* <model-viewer> заполняет контейнер */
.case-3d__canvas model-viewer {
  display: block;
  width: 100%;
  height: 100%;
  background-color: transparent;
  /* На мобильных — разрешаем вертикальную прокрутку, 3D крутим по X */
  touch-action: pan-y;
  --poster-color: transparent;
  --progress-bar-color: var(--color-primary);
  --progress-bar-height: 2px;
}

.case-3d__canvas .case-3d__three-canvas {
  display: block;
  width: 100%;
  height: 100%;
  background-color: transparent;
  touch-action: none;
}

/* Плейсхолдер до загрузки <model-viewer>-скрипта или когда у кейса нет модели */
.case-3d__fallback {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 12px;
  padding: var(--space-5);
  text-align: center;
}
.case-3d__fallback-icon {
  width: 48px;
  height: 48px;
  color: var(--color-text-faint);
  opacity: 0.4;
}
.case-3d__fallback-title {
  font-family: var(--font-display);
  font-size: var(--text-sm);
  color: var(--color-text);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  margin: 0;
}
.case-3d__fallback-hint {
  font-family: var(--font-body);
  font-size: var(--text-xs);
  color: var(--color-text-muted);
  max-width: 320px;
  line-height: 1.5;
  margin: 0;
}

/* Hint-плашка в углу с подсказкой по управлению */
.case-3d__hint {
  position: absolute;
  bottom: 12px;
  left: 12px;
  padding: 6px 10px;
  border: 1px solid var(--color-divider);
  border-radius: 3px;
  background: var(--color-ctrl-bg);  /* v0.13.8.1 — токен, инверсируется light/dark */
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  font-family: var(--font-body);
  font-size: 10px;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--color-text-muted);
  font-variant-numeric: tabular-nums;
  pointer-events: none;
  opacity: 0;
  transition: opacity 240ms ease;
}
.case-3d__canvas.is-ready .case-3d__hint { opacity: 1; }

/* v0.15.1 [1.5] — desktop видит RIGHT MOUSE · ROTATE, mobile — DRAG · ZOOM */
.case-3d__hint--mobile { display: none; }

/* v0.11.4 — на узких экранах контролы занимают весь bottom-row, hint переезжает наверх */
@media (max-width: 640px) {
  .case-3d__hint {
    bottom: auto;
    top: 12px;
    left: 12px;
  }
  /* v0.15.1 [1.5] — инверсия видимости для mobile */
  .case-3d__hint--desktop { display: none; }
  .case-3d__hint--mobile { display: block; }
}

/* v0.11.1 — панель тогглов AUTO / INFO (правый нижний угол) */
.case-3d__controls {
  position: absolute;
  bottom: 12px;
  right: 12px;
  display: flex;
  gap: 5px;
  opacity: 0;
  transition: opacity 240ms ease;
  z-index: 2;
}
.case-3d__canvas.is-ready .case-3d__controls { opacity: 1; }

.case-3d__ctrl {
  /* v0.13.8.1 — фон из токена --color-ctrl-bg (инверсируется light/dark) */
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 9px;
  border: 1px solid var(--color-divider);
  border-radius: 3px;
  background: var(--color-ctrl-bg);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  font-family: var(--font-body);
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--color-text-muted);
  cursor: pointer;
  transition: color 160ms ease, border-color 160ms ease, background 160ms ease;
}
.case-3d__ctrl::before {
  content: '';
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--color-text-faint);
  transition: background 160ms ease, box-shadow 160ms ease;
}
.case-3d__ctrl:hover { color: var(--color-text); border-color: var(--color-text-muted); }
.case-3d__ctrl:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}
.case-3d__ctrl.is-on { color: var(--color-primary); border-color: var(--color-primary); }
.case-3d__ctrl.is-on::before {
  background: var(--color-primary);
  box-shadow: 0 0 6px var(--color-primary);
}

/* v0.11.2 — icon-only reset-кнопка: квадрат, без LED-точки, с pulse при клике
   v0.15.2 [B5] — размер приведён к .case-3d__fs-btn: 32×32, svg 16×16.
   v0.15.4 [П1] — desktop размер 32→36, эталон .case-3d__fs-btn. Mobile остаётся 36×36. */
.case-3d__ctrl--icon {
  padding: 0;
  width: 36px;
  height: 36px;
  justify-content: center;
}
.case-3d__ctrl--icon::before { display: none; }
.case-3d__ctrl-icon { width: 16px; height: 16px; display: block; }

/* v0.7.7 [planshet-fix]: dual-text для AUTO/INFO кнопок.
   .full виден на mobile (≤767) и desktop (≥1024) по дефолту.
   .short ('AUTO' / 'INFO') показывается только на planshet — см.
   @media (min-width: 768px) and (max-width: 1023px) ниже. */
.case-3d__ctrl__txt-short { display: none; }

.case-3d__ctrl--icon.is-pulse {
  color: var(--color-primary);
  border-color: var(--color-primary);
  animation: case-3d-pulse 520ms var(--ease-out, ease-out);
}
@keyframes case-3d-pulse {
  0%   { transform: rotate(0deg); }
  100% { transform: rotate(-360deg); }
}

/* ══════════════════════════════════
   v0.7.0 — Environment switcher (Studio / Outdoor / Dark) + Exposure slider.
   Кнопки соединены в segmented control. Слайдер — в стиле существующих ctrl-кнопок.
   Все цвета через токены (--color-divider, --color-primary, --color-ctrl-bg).
   ══════════════════════════════════ */

/* Группа Studio/Outdoor/Dark — соединены без gap, как segmented control */
.case-3d__env-group,
.case-3d__mat-group {
  display: inline-flex;
  border: 1px solid var(--color-divider);
  border-radius: 3px;
  background: var(--color-ctrl-bg);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  overflow: hidden;
}

/* Внутри группы — снимаем индивидуальные рамки и LED-точки */
.case-3d__ctrl--env,
.case-3d__ctrl--mat {
  border: none;
  border-radius: 0;
  background: transparent;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  padding: 5px 10px;
}
.case-3d__ctrl--env::before,
.case-3d__ctrl--mat::before { display: none; }
.case-3d__ctrl--env + .case-3d__ctrl--env,
.case-3d__ctrl--mat + .case-3d__ctrl--mat {
  border-left: 1px solid var(--color-divider);
}
.case-3d__ctrl--env.is-on,
.case-3d__ctrl--mat.is-on {
  background: var(--color-primary-highlight);
  color: var(--color-primary);
  border-color: transparent; /* перекрыто bg, отдельной рамки на active не нужно */
}
.case-3d__ctrl--env:focus-visible,
.case-3d__ctrl--mat:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: -2px;
}

/* Exposure slider — лейбл + range-input в обёртке */
.case-3d__expo {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 5px 10px;
  border: 1px solid var(--color-divider);
  border-radius: 3px;
  background: var(--color-ctrl-bg);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}
.case-3d__expo-label {
  font-family: var(--font-body);
  font-size: 10px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--color-text-muted);
  user-select: none;
}
.case-3d__expo-input {
  -webkit-appearance: none;
  appearance: none;
  width: 80px;
  height: 4px;
  background: var(--color-divider);
  border-radius: 2px;
  outline: none;
  cursor: pointer;
}
.case-3d__expo-input::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--color-primary);
  cursor: grab;
  border: none;
  transition: transform 160ms ease;
}
.case-3d__expo-input::-webkit-slider-thumb:active {
  cursor: grabbing;
  transform: scale(1.1);
}
.case-3d__expo-input::-moz-range-thumb {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--color-primary);
  cursor: grab;
  border: none;
}
.case-3d__expo-input:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}

/* ══════════════════════════════════
   v0.7.3 — Mobile/tablet light-dropdown.
   На ≤1023px envGroup + expoWrap скрываются, lightDd видим.
   На ≥1024px (desktop) — обратная ситуация: lightDd скрыт, envGroup + expoWrap видны.
   Pattern референс: tags-dropdown__trigger из shared.css.
   ══════════════════════════════════ */
.case-3d__light-dd {
  position: relative;
  display: none; /* По умолчанию скрыто (показывается только на ≤1023px через media query ниже) */
}

/* Trigger переиспользует .case-3d__ctrl + .case-3d__ctrl--icon — отдельных стилей не нужно */

/* Active state — когда dropdown открыт */
.case-3d__light-dd[data-open="true"] .case-3d__light-dd__trigger {
  background: var(--color-primary-highlight);
  color: var(--color-primary);
  border-color: var(--color-primary);
}

/* Panel — выпадающая панель снизу-справа от trigger */
.case-3d__light-dd__panel {
  position: absolute;
  bottom: calc(100% + 8px);
  right: 0;
  min-width: 200px;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-3);
  background: var(--color-ctrl-bg);
  border: 1px solid var(--color-divider);
  border-radius: var(--radius-md);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  box-shadow: var(--shadow-lg);
  z-index: 10;
  /* Защита от слишком широкой панели на маленьких экранах */
  max-width: calc(100vw - 32px);
  box-sizing: border-box;
}
.case-3d__light-dd__panel[hidden] {
  display: none;
}

/* Section labels — Environment / Exposure */
.case-3d__light-dd__section-label {
  font-family: var(--font-body);
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--color-text-muted);
  user-select: none;
}

/* Vertical list of env buttons */
.case-3d__light-dd__env-list {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

/* Каждая кнопка env в dropdown — занимает всю ширину панели */
.case-3d__light-dd__env-btn {
  display: block;
  width: 100%;
  padding: 10px 12px;
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  text-align: left;
  color: var(--color-text-muted);
  background: transparent;
  border: 1px solid var(--color-divider);
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: color 160ms var(--ease-out, ease-out),
              background 160ms var(--ease-out, ease-out),
              border-color 160ms var(--ease-out, ease-out);
}
.case-3d__light-dd__env-btn:hover {
  color: var(--color-text);
  border-color: var(--color-text-muted);
}
.case-3d__light-dd__env-btn.is-on {
  color: var(--color-primary);
  background: var(--color-primary-highlight);
  border-color: var(--color-primary);
}
.case-3d__light-dd__env-btn:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}

/* Exposure slider в dropdown — те же стили что у desktop, но без обёртки .case-3d__expo */
.case-3d__light-dd__expo-input {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  height: 4px;
  background: var(--color-divider);
  border-radius: 2px;
  outline: none;
  cursor: pointer;
  margin: 0;
  padding: 0;
}
.case-3d__light-dd__expo-input::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--color-primary);
  cursor: grab;
  border: none;
  transition: transform 160ms ease;
}
.case-3d__light-dd__expo-input::-webkit-slider-thumb:active {
  cursor: grabbing;
  transform: scale(1.1);
}
.case-3d__light-dd__expo-input::-moz-range-thumb {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--color-primary);
  cursor: grab;
  border: none;
}
.case-3d__light-dd__expo-input:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}

/* ══════════════════════════════════
   v0.7.3 — Responsive switch: ≤1199px — light-dropdown UI
   На mobile/tablet portrait скрываем "толстый" desktop UI (env-group + expoWrap),
   показываем компактный dropdown.
   ══════════════════════════════════ */
@media (max-width: 1199px) {
  .case-3d__env-group { display: none; }
  .case-3d__mat-group { display: none; }
  .case-3d__expo { display: none; }
  .case-3d__light-dd { display: inline-flex; }

  /* v0.7.3 — controls на planshet: выравнивание с правого края.
     По ТЗ — на iPad Air (820×1180) controls должны прижиматься к right edge,
     чтобы не упираться в info-panel и не плыть к левому краю при малой ширине. */
  .case-3d__controls {
    justify-content: flex-end;
  }

  /* v0.7.3 — header overflow fix на tablet portrait.
     На iPad Air 820px при раскрытом sidebar правая колонка теряет ширину
     и title переносится буквами вертикально (см. screenshot 3 → "ReconDrone"
     становится столбиком). Решение: переводим header в column flow начиная с
     ≤1199px (раньше это работало только ≤767px), уменьшаем title до --text-xl. */
  .case-view__header {
    flex-direction: column;
    align-items: stretch;
    justify-content: flex-start;
    gap: var(--space-3);
    flex-wrap: nowrap;
  }
  .case-view__left {
    flex: 0 0 auto;
    min-width: 0;
    width: 100%;
  }
  .case-view__title {
    /* Fluid: на 768–1023px — clamp от 1.25 до 2rem (между --text-xl и --text-2xl) */
    font-size: clamp(1.25rem, 0.8rem + 2vw, 2rem);
  }

  /* v0.7.3 — actions (2D/3D/Blueprints + COPY LINK + nav arrows) на tablet
     тоже растягиваются на полную ширину под header в одну строку, как на mobile.
     Иначе на iPad Air они блокируют title-колонку и провоцируют buchstabenleiter. */
  .case-view__actions {
    flex-direction: row;
    align-items: center;
    justify-content: flex-start;
    width: 100%;
    max-width: none;
    gap: var(--space-2);
    flex-wrap: nowrap;
    flex: 0 0 auto;
  }
}

/* ══════════════════════════════════════════════════════════════════════════
   v0.7.7 [planshet-fix] — точечная адаптация case-view для planshet 768-1199.
   ──────────────────────────────────────────────────────────────────────────
   Контекст: на iPad Air portrait (820×1180) с открытым sidebar главная зона
   сжимается до ~480px. Фиксим три источника overflow в этом range:

   1. AUTO ROTATION / MODEL INFO — длинные тексты (~110px каждая pill) → AUTO/INFO
   2. COPY LINK — text label скрыт, остаётся icon-only (~36px вместо ~110px)
   3. case-3d__hint--desktop "RIGHT MOUSE · ROTATE" — overlap с controls →
      показываем mobile-hint "DRAG · ZOOM" (актуальнее для touch input)

   Range НЕ затрагивает mobile (≤767, есть свои rules) и desktop baseline (≥1200, full UI).
   ══════════════════════════════════════════════════════════════════════════ */
@media (min-width: 768px) and (max-width: 1199px) {
  /* 1. Pills text swap — dual-span паттерн.
     JS рендерит обе версии в spans (см. main.js:1921, 1927). CSS показывает
     нужную в зависимости от viewport — без resize-listener'а. */
  .case-3d__ctrl__txt-full { display: none; }
  .case-3d__ctrl__txt-short { display: inline; }

  /* 2. COPY LINK — icon-only паттерн, идентичный case-share--mobile в
     shared.css:1321. Label остаётся в DOM для screen reader (a11y) и для
     JS-swap "COPIED ✓" feedback. */
  .case-share--desktop .case-share__label {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
  }
  .case-share--desktop {
    /* Симметричный padding — квадратный icon-only вид (без margin-left:auto,
       кнопка остаётся в естественном flex-order после case-nav). */
    padding: 0 var(--space-2);
  }
  .case-share--desktop.case-share--copied {
    /* При успешном копировании — расширяем для COPIED ✓ как на mobile */
    padding: 0 var(--space-3);
  }
  .case-share--desktop.case-share--copied .case-share__label {
    position: static;
    width: auto;
    height: auto;
    margin: 0;
    overflow: visible;
    clip: auto;
    white-space: normal;
  }

  /* 3. Hint vs controls collision: оба позиционированы bottom:12px, на узкой
     main-area пересекались (видно как обрезанное "RI..." под AUTO ROTATION).
     На touch-устройстве hint "RIGHT MOUSE" вообще неактуален — показываем
     mobile-hint "DRAG · ZOOM". Существующий @media (max-width: 640px) делает
     то же самое для mobile, мы расширяем поведение на planshet. */
  .case-3d__hint--desktop { display: none; }
  .case-3d__hint--mobile { display: block; }
}

/* ══════════════════════════════════════════════════════════════════════════
   v0.7.8 [planshet-case-row-fix] — case-row stack на planshet sidebar-open.
   ──────────────────────────────────────────────────────────────────────────
   Контекст: на iPad portrait (820×1180) с открытым sidebar главная зона
   ~480px. .case-row--tall-2 (две vertical иллюстрации 50/50) даёт по ~216px
   каждая — нечитаемо мелко. .case-row--tall-text сжимает caption до ~200px.

   Решение: при sidebar OPEN на planshet (body:not(.cards-collapsed)) — все
   case-row становятся вертикальные columns, items full-width. При sidebar
   COLLAPSED поведение default (multi-col) preserved.

   Range НЕ затрагивает:
   - mobile (≤767, есть свои rules в @media max-width:767px:1563)
   - desktop (≥1024, full multi-col layout)
   - planshet collapsed (через :not(.cards-collapsed) selector)

   Specificity:
   - body:not(.cards-collapsed) .case-row → (0, 2, 1)
   - default .case-row → (0, 1, 0) → корректно перебивается
   ══════════════════════════════════════════════════════════════════════════ */
@media (min-width: 768px) and (max-width: 1023px) {
  body:not(.cards-collapsed) .case-row {
    flex-direction: column;
    gap: var(--space-6);
  }
  body:not(.cards-collapsed) .case-row > .case-item,
  body:not(.cards-collapsed) .case-row--tall-1 > .case-item--tall,
  body:not(.cards-collapsed) .case-row--tall-2 > .case-item--tall,
  body:not(.cards-collapsed) .case-row--tall-text > .case-item--tall,
  body:not(.cards-collapsed) .case-row--tall-text > .case-item--text-inline {
    flex: 1 1 100%;
    width: 100%;
  }
  /* Tall media: aspect-ratio 4/5 + max-height по viewport — идентично mobile
     rule (line 1571), но scoped только на sidebar-open. object-fit:cover на
     .case-item__img (line 607) гарантирует корректный crop при срабатывании
     max-height на iPad landscape. */
  body:not(.cards-collapsed) .case-item--tall .case-item__media {
    aspect-ratio: 4 / 5;
    width: 100%;
    max-width: 100%;
    height: auto;
    max-height: calc(100vh - 180px);
  }
}

/* v0.11.1 — info-панель со статистикой модели (правый верхний угол)
   v0.11.2 — читаемый тип: белые подзаголовки, верста как у .tag, фон как у текстовых карточек */
.case-3d__info-panel {
  position: absolute;
  top: 12px;
  right: 12px;
  min-width: 188px;
  padding: 14px 16px 14px;
  border: 1px solid var(--color-divider);
  border-radius: var(--radius-card);
  background: var(--color-surface);
  opacity: 0;
  transform: translateY(-8px);
  pointer-events: none;
  transition: opacity 240ms ease, transform 240ms ease;
  z-index: 2;
}
.case-3d__info-panel.is-visible {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}
.case-3d__info-title {
  margin: 0 0 10px;
  padding: 0 0 8px;
  border-bottom: 1px solid var(--color-divider);
  font-family: var(--font-body);
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-text);
}
.case-3d__info-table {
  width: 100%;
  border-collapse: collapse;
}
.case-3d__info-table tr + tr td { padding-top: 7px; }
.case-3d__info-label {
  font-family: var(--font-body);
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-text);
  text-align: left;
  padding-right: 14px;
  white-space: nowrap;
}
.case-3d__info-value {
  font-family: var(--font-body);
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: 0.18em;
  color: var(--color-text);
  text-align: right;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* ═══════════════════════════════════
   MOBILE — case-view тоже вертикальный скролл, но tall → full width
═══════════════════════════════════ */
@media (max-width: 767px) {
  .case-view {
    padding: 0 var(--space-4) 0;  /* top отступ даёт sticky .case-mobile-bar */
    gap: var(--space-3);
  }
  /* v0.15.5 [П1] — mobile: header в column. Title/meta (слева) в первой строке,
     tabs + case-nav под заголовком во всю ширину. */
  .case-view__header {
    flex-direction: column;
    align-items: stretch;
    justify-content: flex-start;
    gap: var(--space-3);
    flex-wrap: nowrap;
  }
  .case-view__left {
    flex: 0 0 auto;
    min-width: 0;
    width: 100%;
  }
  .case-view__title { font-size: var(--text-xl); }

  /* Mobile (v0.22): Blueprints — вертикальная лента SVG (все страницы кейса
     друг под другом). Верхний тулбар скрыт (Export/FS живут per-page внизу
     каждого SVG). Pager-overlay тоже скрыт — листание = native scroll. */
  .case-blueprints { padding: 8px 0 16px; }
  .case-blueprints__toolbar { display: none; }
  .case-blueprints__canvas {
    flex: 1;
    min-height: 0;
    width: 100%;
    /* v0.22.2 — explicit overflow-y:auto + overscroll-behavior, чтобы touch-
       scroll работал стабильно на iOS Safari и не передавался Lenis-у
       (контейнер также помечен data-lenis-prevent в index.html). */
    overflow-x: hidden;
    overflow-y: auto;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 16px;
  }
  .case-blueprints__page {
    display: flex;          /* все страницы видны на mobile */
    flex: 0 0 auto;
    height: auto;
    gap: 8px;
  }
  .case-blueprints__page.is-current { display: flex; }
  .case-blueprints__page-canvas {
    flex: 0 0 auto;
    width: 100%;
    aspect-ratio: 3 / 2;
    min-height: 240px;
    /* border + bg-grid наследуются из base .case-blueprints__page-canvas (v0.22.2). */
  }
  .case-blueprints__page-toolbar {
    display: flex;
    align-items: stretch;        /* v0.22.2 — равная высота Export и FS */
    gap: 10px;
  }
  /* v0.22.2 — Export заполняет ширину от левого края до FS-кнопки, обе одной высоты (36px). */
  .case-blueprints__page-export {
    flex: 1 1 auto;
    min-height: 36px;
    padding: 8px 14px;
    justify-content: center;
  }
  .case-blueprints__page-toolbar .case-blueprints__fs-btn {
    position: static;
    right: auto;
    bottom: auto;
    flex: 0 0 36px;
    width: 36px;
    height: 36px;
  }
  /* Pager-overlay на mobile не нужен — заменяет native scroll */
  .case-blueprints__pager { display: none; }

  /* v0.22.4 — mobile: title-block ~2.5× меньше (плашка с инфо не должна
     перекрывать половину канваса). Сохраняем визуальный язык, режем
     шрифты/паддинги/ширину пропорционально. */
  .case-blueprints__title-block {
    right: 8px;
    bottom: 8px;
    width: 132px;
  }
  .case-blueprints__title-block-top   { padding: 4px 6px; }
  .case-blueprints__title-block-cell  { padding: 3px 6px; }
  .case-blueprints__title-block-key {
    font-size: 6px;
    letter-spacing: 0.1em;
  }
  .case-blueprints__title-block-project {
    font-size: 9px;
    letter-spacing: 0.06em;
    margin-top: 2px;
  }
  .case-blueprints__title-block-val {
    font-size: 7px;
    margin-top: 2px;
  }

  /* Mobile (v0.11): 3D canvas — зеркальная логика с Blueprints */
  .case-3d { padding: 8px 0 16px; }
  .case-3d__canvas {
    flex: 0 0 auto;
    width: 100%;
    aspect-ratio: 3 / 2;
    min-height: 280px;
  }

  /* v0.21.1 — Pills text swap для mobile: full "AUTO ROTATION"/"MODEL INFO"
     переносятся по space на 2 строки и ломают layout. Используем short
     варианты "Auto-R" / "Info" (CSS text-transform: uppercase делает их
     "AUTO-R" / "INFO" визуально). Раньше swap применялся только к tablet
     range (768-1023px) — теперь и mobile тоже. */
  .case-3d__ctrl__txt-full  { display: none; }
  .case-3d__ctrl__txt-short { display: inline; }

  /* v0.11.1 mobile — тогглы крупнее для touch + компактная info-панель */
  .case-3d__ctrl {
    min-height: 36px;
    padding: 8px 10px;
    font-size: 9px;
  }
  .case-3d__ctrl--icon {
    width: 36px;
    height: 36px;
    padding: 0;
  }
  .case-3d__ctrl-icon { width: 16px; height: 16px; }
  .case-3d__info-panel {
    min-width: 164px;
    padding: 12px 14px;
  }

  /* v0.7.3 — env-группа и expo на mobile скрыты (см. @media max-width:1023px выше),
     контент перенесён в .case-3d__light-dd. Controls в одну линию: AUTO, INFO, RESET, FS, ⚙ light-dd. */
  .case-3d__controls {
    gap: 6px;
    max-width: calc(100% - 24px);
    /* nowrap: всё помещается в одну линию благодаря замене 2 элементов на 1 trigger */
    flex-wrap: nowrap;
  }

  /* Mobile v0.15.5 [П1]: вся группа tabs + case-nav под заголовком во всю ширину.
     Порядок: [2D 36×36] [3D 36×36] [BP ~108×36] [case-nav растянут до правого края].
     2D/3D — fix 36×36, Blueprints — fix height 36 + padding 0 16 (ширина по контенту). */
  .case-view__actions {
    flex-direction: row;
    align-items: center;
    justify-content: flex-start;
    width: 100%;
    max-width: none;
    gap: var(--space-2);
    flex-wrap: nowrap;
    flex: 0 0 auto;
  }
  .case-view__tabs {
    width: 100%;
    gap: 8px;
    flex-wrap: nowrap;
    justify-content: flex-start;
    align-items: center;
  }
  .case-view__tablist {
    flex: 0 0 auto;
    gap: 8px;
    flex-wrap: nowrap;
  }
  .case-view__tablist > .case-tab {
    flex: 0 0 auto;
    min-width: 0;
    justify-content: center;
  }
  /* v0.15.3 [П2] — 2D / 3D: fix 36×36 квадрат. Override .case-tab min-height:44px. */
  .case-view__tablist > #case-tab-2d,
  .case-view__tablist > #case-tab-3d {
    width: 36px;
    height: 36px;
    min-height: 36px;
    padding: 0;
  }
  /* v0.15.3 [П2] — Blueprints: height 36, padding 16/16, width by content. */
  .case-view__tablist > #case-tab-bp {
    height: 36px;
    min-height: 36px;
    padding: 0 16px;
  }
  /* v0.15.5 [П1] — case-nav: растянут на оставшееся место до правого края.
     justify-content: space-between — prev к левому краю блока, next к правому, counter по центру. */
  .case-view__tabs > .case-nav {
    flex: 1 1 auto;
    min-width: 0;
    justify-content: space-between;
    height: 36px;
    min-height: 36px;
    flex-basis: auto;
    margin-left: 0;
  }
  /* v0.15.3 [П2] — case-nav__btn на mobile: в компактном 36-px наве, кнопки без увеличения.
     (в секции mobile выше глобально min-width/min-height:44px для .case-nav__btn). */
  .case-view__tabs > .case-nav > .case-nav__btn {
    min-width: 30px;
    min-height: 30px;
    width: 30px;
    height: 30px;
  }
  .case-nav__counter {
    min-width: 40px;
    font-size: 10px;
  }

  .case-scroll__track {
    gap: var(--space-8);
    padding-top: var(--space-4);
    padding-bottom: var(--space-6);
  }

  /* На мобильном все rows — вертикальные столбцы, каждый item full-width */
  .case-row { flex-direction: column; gap: var(--space-6); }
  .case-row > .case-item,
  .case-row--tall-1 > .case-item--tall,
  .case-row--tall-2 > .case-item--tall,
  .case-row--tall-text > .case-item--tall,
  .case-row--tall-text > .case-item--text-inline { flex: 1 1 100%; width: 100%; }

  /* Mobile — возвращаем aspect-ratio для tall и отменяем жёсткую высоту 1100px (слишком высоко для 375×812). */
  .case-item--tall .case-item__media {
    aspect-ratio: 4 / 5;
    width: 100%;
    max-width: 100%;
    height: auto;
    max-height: calc(100vh - 180px);
  }
  .case-item--wide .case-item__media {
    aspect-ratio: 16 / 9;
    height: auto;
    max-height: none;
  }
  /* Текст-блок на мобильном — компактнее */
  .case-text { padding: var(--space-4) 0; }
  .case-text__title { font-size: var(--text-xl); }
  .case-text__body  { font-size: var(--text-sm); }
  .case-text__header {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space-2);
  }
  .case-text__header-left {
    gap: var(--space-2);
  }
  .case-text__meta-item {
    font-size: 10px;
    padding: 3px 8px;
  }
  /* v0.13.8 — external btn touch target ≥ 44px на мобильном.
     v0.13.8.1 — на мобильном отступ 64px не нужен (ширина экрана маленькая) */
  .case-text__external-btn {
    min-height: 44px;
    padding: 0 16px;
    margin-right: 0;
  }
}

/* ═══════════════════════════════════════════════════════════════════════
   v0.15.1 [2.1/2.2/2.3] — FULLSCREEN OVERLAY (media-fs)
   Общая overlay для 3D (model-viewer) и Blueprints (SVG).
   Variant B: отдельный fixed-контейнер, который показывает клон контента.
   v0.15.2 [B3] — правила для .case-media-fs-btn удалены (кнопка 2D ушла).
   ─── Floating кнопка (expand) ──────────────────────────────────────── */
/* v0.15.3 [П5] [П6] — fs-btn 32×32 → 36×36 (BP + 3D). */
.case-3d__fs-btn,
.case-blueprints__fs-btn {
  position: absolute;
  right: 16px;
  bottom: 16px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  padding: 0;
  background: var(--color-ctrl-bg);
  border: 1px solid var(--color-divider);
  border-radius: 3px;
  color: var(--color-text-muted);
  cursor: pointer;
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  z-index: 5;
  transition: color 160ms var(--ease-out), border-color 160ms var(--ease-out);
}
@media (hover: hover) and (pointer: fine) {
  .case-3d__fs-btn:hover,
  .case-blueprints__fs-btn:hover {
    color: var(--color-text);
    border-color: var(--color-text-muted);
  }
}
.case-3d__fs-btn:focus-visible,
.case-blueprints__fs-btn:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}
.case-3d__fs-btn__icon,
.case-blueprints__fs-btn__icon {
  width: 16px;
  height: 16px;
  display: block;
}
/* v0.7.12 [UX] — case-blueprints__fs-btn accent (одинокая кнопка в углу canvas,
   нужна повышенная discoverability). v0.7.13: только border в --color-primary,
   icon оставлен в --color-text (наследует от parent) — согласовано с другими
   accent-кнопками. 3D fs-btn остаётся neutral — он живёт в ряду controls. */
.case-blueprints__fs-btn {
  border-color: var(--color-primary);
  color: var(--color-text);
}
@media (hover: hover) and (pointer: fine) {
  .case-blueprints__fs-btn:hover {
    border-color: var(--color-primary-hover);
    background: var(--color-primary-highlight);
  }
}
/* В 3D controls и BP toolbar кнопка встроена в row, сбрасываем absolute */
.case-3d__controls .case-3d__fs-btn,
.case-blueprints__toolbar .case-blueprints__fs-btn {
  position: static;
  right: auto;
  bottom: auto;
}

/* ─── Overlay ───────────────────────────────────────────────────────── */
/* v0.15.2 [B4] — фон overlay приведён к токену страницы (--color-bg):
   dark: #212121, light: #f5f5f5. Системный курсор сброшен на auto (чтобы
   был виден над overlay, пока cursor-fine скрывает его глобально);
   кастомный .cursor поднят на z-index:10001 > media-fs (9999). */
.media-fs {
  position: fixed;
  inset: 0;
  z-index: 9999;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--color-bg);
  opacity: 0;
  pointer-events: none;
  transition: opacity 200ms var(--ease-out);
}
.media-fs.is-open {
  opacity: 1;
  pointer-events: auto;
}
.media-fs__stage {
  position: relative;
  width: 100%;
  height: 100%;
}
/* v0.20.3 — Stage children теперь absolutely-centered (inset+margin auto)
   вместо flex layout. Раньше при swap'е flex клал old+new рядом,
   layout прыгал, и pin-old-absolute трюк имел edge cases (lazy-img
   с null rect, transform-остатки от FLIP). Теперь old+new естественно
   stack по центру → pure opacity crossfade без layout intervention. */
.media-fs__stage > img,
.media-fs__stage > video,
.media-fs__stage > svg {
  position: absolute;
  inset: 48px;
  margin: auto;
  width: auto;
  height: auto;
  max-width: calc(100% - 96px);
  max-height: calc(100% - 96px);
  object-fit: contain;
  display: block;
}
.media-fs__stage > model-viewer,
.media-fs__stage > .media-fs__three {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}
.media-fs__three .case-3d__three-canvas {
  display: block;
  width: 100%;
  height: 100%;
  touch-action: none;
}
@media (max-width: 640px) {
  .media-fs__stage > img,
  .media-fs__stage > video,
  .media-fs__stage > svg {
    inset: 24px;
    max-width: calc(100% - 48px);
    max-height: calc(100% - 48px);
  }
}
/* Close кнопка (contract icon) — правый верх. v0.7.11 [P2 #12]: цвета из --color-fs-close-* токенов */
.media-fs__close {
  position: absolute;
  top: 16px;
  right: 16px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  padding: 0;
  background: var(--color-fs-close-bg);
  border: 1px solid var(--color-fs-close-border);
  border-radius: 3px;
  color: var(--color-fs-close-text);
  cursor: pointer;
  z-index: 2;
  transition: color 160ms var(--ease-out), border-color 160ms var(--ease-out);
}
@media (hover: hover) and (pointer: fine) {
  .media-fs__close:hover {
    color: var(--color-fs-close-text-hover);
    border-color: var(--color-fs-close-border-hover);
  }
}
.media-fs__close:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}
.media-fs__close-icon {
  width: 16px;
  height: 16px;
  display: block;
}

/* ─── Gallery navigation (v0.20.0) ───────────────────────────────────
   Активируется когда .media-fs открыт в режиме gallery (data-gallery scope).
   Кнопки скрыты [hidden] до открытия, чтобы не перекрывать 3D/BP fs-режим. */
.media-fs__prev,
.media-fs__next {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  padding: 0;
  background: var(--color-fs-close-bg);
  border: 1px solid var(--color-fs-close-border);
  border-radius: 3px;
  color: var(--color-fs-close-text);
  cursor: pointer;
  z-index: 3;
  transition:
    color 160ms var(--ease-out),
    border-color 160ms var(--ease-out),
    opacity 200ms var(--ease-out);
}
.media-fs__prev { left: 16px; }
.media-fs__next { right: 16px; }
.media-fs__prev[hidden],
.media-fs__next[hidden] { display: none; }

@media (hover: hover) and (pointer: fine) {
  .media-fs__prev:hover,
  .media-fs__next:hover {
    color: var(--color-fs-close-text-hover);
    border-color: var(--color-fs-close-border-hover);
  }
}
.media-fs__prev:focus-visible,
.media-fs__next:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}
.media-fs__nav-icon {
  width: 16px;
  height: 16px;
  display: block;
}
@media (max-width: 640px) {
  .media-fs__prev { left: 8px; }
  .media-fs__next { right: 8px; }
}

.media-fs__counter {
  position: absolute;
  top: 16px;
  left: 16px;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: 0.1em;
  color: var(--color-text);
  opacity: 0.6;
  z-index: 2;
  pointer-events: none;
  user-select: none;
  font-variant-numeric: tabular-nums;
  transform-origin: left center;
}
.media-fs__counter[hidden] { display: none; }

.media-fs__zoom {
  position: absolute;
  left: 50%;
  bottom: 16px;
  z-index: 3;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px;
  border: 1px solid var(--color-fs-close-border);
  border-radius: 4px;
  background: var(--color-fs-close-bg);
  color: var(--color-fs-close-text);
  transform: translateX(-50%);
}
.media-fs__zoom[hidden] { display: none; }
.media-fs__zoom-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  padding: 0;
  border: 1px solid transparent;
  border-radius: 3px;
  background: transparent;
  color: currentColor;
  cursor: pointer;
  transition:
    color 160ms var(--ease-out),
    border-color 160ms var(--ease-out),
    opacity 160ms var(--ease-out);
}
.media-fs__zoom-btn:disabled {
  cursor: default;
  opacity: 0.35;
}
@media (hover: hover) and (pointer: fine) {
  .media-fs__zoom-btn:not(:disabled):hover {
    color: var(--color-fs-close-text-hover);
    border-color: var(--color-fs-close-border-hover);
  }
}
.media-fs__zoom-btn:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}
.media-fs__zoom-icon {
  width: 18px;
  height: 18px;
  display: block;
}
.media-fs.is-gallery .media-fs__stage > img {
  cursor: zoom-in;
  transform-origin: center center;
  touch-action: none;
  will-change: transform;
}
.media-fs.is-gallery.is-zoomed .media-fs__stage > img { cursor: grab; }
.media-fs.is-gallery.is-panning .media-fs__stage > img { cursor: grabbing; }
@media (max-width: 640px) {
  .media-fs__zoom {
    bottom: 12px;
    gap: 4px;
  }
  .media-fs__zoom-btn {
    width: 34px;
    height: 34px;
  }
}

/* visually hidden live-region для скринридеров */
.media-fs__announcer {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  border: 0;
}

/* Click-affordance внутри case-item__media — курсор pointer
   (cursor-fine скрывает native, но для touch/no-cursor устройств это нужно). */
.case-item__media img {
  cursor: pointer;
}

@media (prefers-reduced-motion: reduce) {
  .media-fs { transition: none; }
  /* v0.7.0 — отключаем transform-анимацию у thumb exposure-слайдера.
     Это единственное место в проекте, где !important разрешён —
     внутри prefers-reduced-motion (см. build_rules.md). */
  .case-3d__expo-input::-webkit-slider-thumb { transition: none !important; }
}

