/* Шрифты подключаются <link>-ом в base.html, а не @import отсюда:
   @import заставляет браузер ждать загрузки этого файла, прежде чем он вообще
   узнает о шрифтах. Список семейств — там же. */

/* Нейтральная бумажная основа для текста. Тёмные полноэкранные сцены остаются
   только там, где показываем железо, трансляцию или видео. */
:root {
  /* Примитивы — сырые значения, в компонентах не используются напрямую */
  --color-white: #ffffff;
  --color-ink: #1d1d1f;
  --color-ink-dim: #62666d;
  /* Тёплая основа из DESIGN_HITMAN: чистый белый на весь экран выглядит
     стерильно, слоновая кость даёт дороже при том же контрасте. Карточка
     остаётся белой — так она отделяется от полотна без обводки. */
  --color-paper: #f3f4f6;
  --color-paper-white: #ffffff;
  --color-paper-muted: #e7e9ed;
  --color-line: #d4d7dc;
  --color-black: #000000;
  --color-red-600: #dc2626;
  --color-red-800: #b91c1c;

  /* Семантика */
  --color-bg: var(--color-paper);
  --color-surface: var(--color-paper-white);
  --color-surface-muted: var(--color-paper-muted);
  --color-border: var(--color-line);
  --color-border-accent: rgba(220,38,38,0.35);
  --color-heading: var(--color-ink);
  --color-text: var(--color-ink);
  --color-text-muted: var(--color-ink-dim);
  --color-inverse-bg: var(--color-black);
  --color-inverse-text: var(--color-white);
  /* Акцент один и он красный: правило «один акцент на композицию» взято у
     Apple, сам цвет — нет, красный это узнаваемость Hitman IT. */
  --color-accent: var(--color-red-600);
  --color-accent-hover: var(--color-red-800);
  --color-accent-soft: var(--color-red-800);
  --color-focus-ring: var(--color-red-600);

  /* Алиасы, на которых держатся компоненты и тона полос */
  --bg: var(--color-bg);
  --card: var(--color-surface);
  --card-alt: var(--color-surface-muted);
  --border: var(--color-border);
  --border-red: var(--color-border-accent);
  --red: var(--color-accent);
  --red-dark: var(--color-accent-hover);
  --text: var(--color-text);
  --text-dim: var(--color-text-muted);
  --heading: var(--color-heading);
  --black: var(--color-inverse-bg);
  --white: var(--color-inverse-text);

  /* Гарнитуры. Файлов SF Pro в репозитории нет и быть не может — гарнитура
     лицензирована Apple под их платформы. Системный стек даёт настоящий SF на
     macOS и iOS и ближайший аналог на остальных системах, без внешних
     запросов к чужому CDN. */
  --font-text: -apple-system, BlinkMacSystemFont, "SF Pro Display", "Segoe UI",
               Inter, Roboto, "Helvetica Neue", sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;

  /* Кегль: коэффициент ~1.333, крупные ступени зажаты clamp — заголовок обязан
     быть крупным на десктопе и не разваливать телефон. */
  --text-2xs: 0.75rem;                                    /* 12 — подписи */
  --text-xs:  0.875rem;                                   /* 14 — кнопки */
  --text-sm:  0.9375rem;                                  /* 15 */
  --text-base: clamp(1rem, 0.9rem + 0.4vw, 1.3125rem);    /* 16 → 21 */
  --text-lg:  clamp(1.125rem, 1rem + 0.5vw, 1.5rem);      /* 18 → 24 */
  --text-xl:  clamp(1.25rem, 1.05rem + 0.9vw, 1.75rem);   /* 20 → 28 */
  --text-2xl: clamp(1.5rem, 1.1rem + 1.6vw, 2.5rem);      /* 24 → 40 */
  --text-3xl: clamp(2rem, 1.3rem + 2.8vw, 3.5rem);        /* 32 → 56 */
  --text-4xl: clamp(2.5rem, 1.6rem + 4vw, 5rem);          /* 40 → 80 */

  --leading-heading: 1.07;
  --leading-body: 1.29;
  --tracking-heading: -0.02em;   /* плотный набор заголовков */

  /* Сетка: базовый шаг 4px, все отступы кратны ему */
  --space-1: 4px;   --space-2: 8px;   --space-3: 12px;  --space-4: 16px;
  --space-6: 24px;  --space-8: 32px;  --space-12: 48px; --space-16: 64px;
  --space-24: 96px; --space-32: 128px;

  --container: 1020px;

  /* Скругления: 8px поверхностям, пилюля кнопкам */
  /* Скругления из DESIGN_HITMAN: мягкий прямоугольник вместо пилюли.
     Пилюля — почерк Apple, здесь она спорит с общей сдержанностью. */
  --radius-surface: 12px;
  --radius-button: 16px;
  --radius-lg: 20px;
  --radius-pill: 980px;   /* остаётся у чипов-ярлыков и круглых элементов */

  /* Глубина: один уровень, мягкий и далёкий */
  /* Двухслойная тень: близкая даёт край, дальняя — объём. Одиночная
     размытая выглядит грязным пятном под карточкой. */
  --shadow-card: 0 8px 22px rgba(18,24,32,0.08);
  --shadow-card-hover: 0 16px 34px rgba(18,24,32,0.14);

  /* Движение: одна кривая, три длительности */
  --ease-standard: cubic-bezier(0.4, 0, 0.22, 1);
  --ease-out: cubic-bezier(0.4, 0, 0.22, 1);
  --ease-in-out: cubic-bezier(0.4, 0, 0.22, 1);
  /* Кривая с лёгким перелётом: элемент чуть проскакивает конечную точку и
     возвращается — так движение читается как предмет с массой, а не как
     линейная интерполяция числа. Для мелкой моторики (подчёркивания,
     иконки в кнопках), не для больших перестроений. */
  --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
  --dur-fast: 250ms;
  --dur-base: 320ms;
  --dur-slow: 400ms;

  color-scheme: light;
}

/* --- Тёмная тема ------------------------------------------------------------
   Две одинаковые карты токенов — это не копипаста по недосмотру: селекторы
   должны сработать в двух разных случаях (системная настройка и явный выбор
   пользователя), а средства «применить один набор объявлений к двум
   селекторам» в CSS нет. Меняем только семантический слой: примитивы и
   компоненты не знают, какая тема активна.

   Отдельно про --color-inverse-bg: это не «чёрный», а «панель, которая всегда
   темнее полотна» — навбар, футер, хиро, смета. В тёмной теме она обязана
   стать светлее фона страницы, иначе панели просто исчезнут. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --color-bg: #0b0b0d;
    --color-surface: #141519;
    --color-surface-muted: #1b1d22;
    --color-border: #2b2e36;
    --color-border-accent: rgba(248,113,113,0.4);
    --color-heading: #f5f5f7;
    --color-text: #d4d4d8;
    --color-text-muted: #8b8b93;
    --color-inverse-bg: #17181d;
    --color-inverse-text: #f5f5f7;
    --color-accent: #f05252;
    --color-accent-hover: #f87171;
    --color-accent-soft: #fca5a5;
    --color-focus-ring: #f87171;
    --shadow-card: 0 2px 10px rgba(0,0,0,0.5);
    /* Алиасы обязаны переопределяться здесь же. var() внутри значения кастомного
    свойства подставляется один раз — там, где свойство объявлено. Объявленный
    в :root --heading уже «запёкся» в цвет активной темы страницы, и смена
    --color-heading на секции его не трогает: в светлой полосе оставался
    светлый текст на светлом фоне. */
    --bg: var(--color-bg);
    --card: var(--color-surface);
    --card-alt: var(--color-surface-muted);
    --border: var(--color-border);
    --border-red: var(--color-border-accent);
    --red: var(--color-accent);
    --red-dark: var(--color-accent-hover);
    --text: var(--color-text);
    --text-dim: var(--color-text-muted);
    --heading: var(--color-heading);
    --black: var(--color-inverse-bg);
    --white: var(--color-inverse-text);
    --shadow-card-hover: 0 14px 32px rgba(0,0,0,0.65);
    color-scheme: dark;
  }
}
:root[data-theme="dark"] {
  --color-bg: #0b0b0d;
  --color-surface: #141519;
  --color-surface-muted: #1b1d22;
  --color-border: #2b2e36;
  --color-border-accent: rgba(248,113,113,0.4);
  --color-heading: #f5f5f7;
  --color-text: #d4d4d8;
  --color-text-muted: #8b8b93;
  --color-inverse-bg: #17181d;
  --color-inverse-text: #f5f5f7;
  --color-accent: #f05252;
  --color-accent-hover: #f87171;
  --color-accent-soft: #fca5a5;
  --color-focus-ring: #f87171;
  --shadow-card: 0 2px 10px rgba(0,0,0,0.5);
  /* Алиасы обязаны переопределяться здесь же. var() внутри значения кастомного
  свойства подставляется один раз — там, где свойство объявлено. Объявленный
  в :root --heading уже «запёкся» в цвет активной темы страницы, и смена
  --color-heading на секции его не трогает: в светлой полосе оставался
  светлый текст на светлом фоне. */
  --bg: var(--color-bg);
  --card: var(--color-surface);
  --card-alt: var(--color-surface-muted);
  --border: var(--color-border);
  --border-red: var(--color-border-accent);
  --red: var(--color-accent);
  --red-dark: var(--color-accent-hover);
  --text: var(--color-text);
  --text-dim: var(--color-text-muted);
  --heading: var(--color-heading);
  --black: var(--color-inverse-bg);
  --white: var(--color-inverse-text);
  --shadow-card-hover: 0 14px 32px rgba(0,0,0,0.65);
  color-scheme: dark;
}

* { box-sizing: border-box; }

/* Accessibility: visible focus ring on every interactive element (ui-ux-pro-max §1 CRITICAL) */
a:focus-visible, button:focus-visible, input:focus-visible, select:focus-visible,
textarea:focus-visible, [tabindex]:focus-visible {
  outline: 2px solid var(--color-focus-ring);
  outline-offset: 2px;
  border-radius: 2px;
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-text);
  font-size: var(--text-base);
  line-height: var(--leading-body);
  -webkit-font-smoothing: antialiased;
}

/* Display type — geometric sans for headings and stat numbers. */
.font-display {
  font-family: var(--font-text);
  font-weight: 600;
  letter-spacing: var(--tracking-heading);
  line-height: var(--leading-heading);
}
.font-tracked {
  font-family: var(--font-text);
  font-weight: 500;
  letter-spacing: 0;
}

/* Logo lockup — white box, dark condensed caps. */
.logo-lockup {
  display: inline-block; background: var(--white); color: var(--black);
  padding: var(--space-2) var(--space-4); font-family: var(--font-text); font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.02em; line-height: 1;
}

a { color: inherit; text-decoration: none; }
img, video { max-width: 100%; height: auto; }

.container { max-width: var(--container); margin: 0 auto; padding: 0 var(--space-6); }

/* Navbar: stays dark navy on every page, regardless of section theme. */
.navbar {
  position: sticky; top: 0; z-index: 50;
  background: rgba(7,8,11,0.78);
  backdrop-filter: saturate(180%) blur(20px);
  -webkit-backdrop-filter: saturate(180%) blur(20px);
  border-bottom: 1px solid var(--border);
}
.navbar-inner { display: flex; justify-content: space-between; align-items: center; padding-block: 0.75rem; gap: 1rem; flex-wrap: wrap; }
.navbar-brand { display: flex; align-items: center; gap: var(--space-3); font-weight: 600; color: var(--color-heading); }
.navbar-links { display: flex; flex-wrap: wrap; gap: var(--space-6); font-family: var(--font-text); font-size: var(--text-xs); font-weight: 400; letter-spacing: 0; }
.navbar-links a { color: rgba(255,255,255,0.78); transition: color var(--dur-fast) var(--ease-standard); }
.navbar-links a:hover, .navbar-links a.active { color: var(--red); }

/* Burger toggle — hidden on desktop, shown only under the collapse breakpoint below. */
.navbar-burger {
  display: none; flex-direction: column; justify-content: center; gap: 5px;
  width: 2.25rem; height: 2.25rem; padding: 0; border: none; background: transparent; cursor: pointer;
}
.navbar-burger .bar { width: 100%; height: 2px; background: var(--color-heading); transition: transform 0.2s ease, opacity 0.2s ease; }
.navbar-burger[aria-expanded="true"] .bar:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.navbar-burger[aria-expanded="true"] .bar:nth-child(2) { opacity: 0; }
.navbar-burger[aria-expanded="true"] .bar:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

@media (max-width: 768px) {
  .navbar-burger { display: flex; }
  /* Collapsed by default: 0-height, clipped, not just visually hidden — so
     it's out of the tab order and doesn't reserve empty space above the
     fold like the old wrapping layout did. */
  .navbar-links {
    order: 99;
    flex-direction: column; align-items: stretch; gap: 0;
    width: 100%; max-height: 0; overflow: hidden;
    transition: max-height 0.25s ease;
  }
  .navbar-links.is-open { max-height: 28rem; }
  .navbar-links a { padding: var(--space-3) 0; border-top: 1px solid var(--border); }
}

/* Hero: deliberate dark statement panel (Exaggerated Minimalism hero-as-thesis) */
.hero {
  position: relative; overflow: hidden; color: var(--white);
  background:
    repeating-linear-gradient(115deg, rgba(255,255,255,0.03) 0px, rgba(255,255,255,0.03) 1px, transparent 1px, transparent 14px),
    linear-gradient(135deg, #000 0%, #06181b 45%, #000 100%);
  border-radius: 0;
  padding: var(--space-24) 0;
  border-bottom: 4px solid var(--red);
}
.hero .kicker { font-family: var(--font-text); font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.04em; color: var(--red); font-weight: 600; margin-bottom: 0.75rem; }
.hero h1 { font-size: clamp(2.5rem, 7vw, 4.5rem); margin: 0 0 1rem; }
.hero .lead { font-family: var(--font-text); font-size: 1.35rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.02em; color: var(--white); max-width: 40rem; }

/* Radial "scan / target" glow — recurring motif behind hero key art */
.hero::before {
  content: ''; position: absolute; top: 50%; right: -10%; width: 55rem; height: 55rem;
  transform: translateY(-50%);
  background: radial-gradient(circle, rgba(220,38,38,0.35) 0%, rgba(220,38,38,0.12) 35%, transparent 68%);
  border-radius: 50%; pointer-events: none;
}
.hero::after {
  content: ''; position: absolute; top: 50%; right: -6%; width: 34rem; height: 34rem;
  transform: translateY(-50%); border: 1px solid rgba(220,38,38,0.25); border-radius: 50%; pointer-events: none;
}
.hero .container { position: relative; z-index: 1; }

/* Hero slider — full-bleed photo slides replacing the old static text+portrait hero */
.hero-slider { padding: 0; }
.hero-slider::before, .hero-slider::after { display: none; }
.hero-slider .slider-track { transition: transform 0.45s var(--ease-in-out); }
.hero-slider .slider-slide { transition: opacity 0.45s var(--ease-in-out), visibility 0s linear 0.45s; }
.hero-slider .slider-slide.is-active { transition: opacity 0.6s ease; }
.hero-slide {
  position: relative; display: flex; align-items: center;
  min-height: min(38rem, 82vh);
  background-size: cover; background-position: center;
}
.hero-slide::before {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(100deg, rgba(6,6,8,0.95) 0%, rgba(6,6,8,0.82) 38%, rgba(6,6,8,0.35) 72%, rgba(6,6,8,0.6) 100%);
}
.hero-slide-inner { position: relative; z-index: 1; max-width: 36rem; padding: 3.5rem 0 5rem; }
.hero-slide-title { font-size: clamp(2.1rem, 5.5vw, 3.5rem); line-height: 1.05; margin: 0 0 1rem; color: var(--white); }
/* Always on a dark photo overlay (.hero-slide::before) regardless of page
   theme, so these stay light-on-dark rather than following var(--text). */
.hero-slide-lead { max-width: 34rem; color: #e4e4e7; font-size: 1.05rem; margin: 0 0 0.75rem; }
.hero-slide-stats { max-width: 34rem; color: #a1a1aa; font-size: 0.8rem; letter-spacing: 0.02em; margin: 0 0 1.75rem; }
.hero-slide-cta { display: flex; flex-wrap: wrap; gap: 0.75rem; }
.hero-slider .slider-controls { position: absolute; left: 0; right: 0; bottom: 1.25rem; z-index: 2; margin-top: 0; }
.hero-slider .slider-arrow { background: rgba(9,11,16,0.55); border-color: rgba(255,255,255,0.3); color: #fff; backdrop-filter: blur(4px); }
.hero-slider .slider-arrow:hover { background: var(--red); border-color: var(--red); color: #fff; }

@media (max-width: 640px) {
  .hero-slide-inner { padding: 2.5rem 0 4rem; }
}

/* Buttons */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 0.5rem;
  padding: 14px 24px; border-radius: var(--radius-button); font-family: var(--font-text);
  font-weight: 400; font-size: 17px; letter-spacing: 0;
  border: 1px solid transparent; cursor: pointer;
  transition: background 0.15s var(--ease-out), border-color 0.15s var(--ease-out),
              color 0.15s var(--ease-out), transform 0.15s var(--ease-out),
              box-shadow 0.2s var(--ease-out);
}
@media (hover: hover) and (pointer: fine) {
  .btn:hover { transform: translateY(-2px); }
}
/* Отклик на нажатие: палец/курсор должен чувствовать, что его услышали. */
.btn:active { transform: scale(0.97); }
.btn-primary { background: var(--red); color: white; border-color: var(--red); }
.btn-primary:hover { background: var(--red-dark); border-color: var(--red-dark); box-shadow: 0 10px 24px -6px rgba(220,38,38,0.55); }
/* Default: ghost button on the white page/card body. Dark surfaces
   (navbar, hero panels) need the light-on-dark variant below. */
/* Цвета от полотна страницы, а не литеральный чёрный: на тёмной теме
   --black это цвет тёмной панели, и кнопка на нём просто исчезала. */
.btn-ghost { background: transparent; border-color: var(--border); color: var(--heading); }
.btn-ghost:hover { background: var(--card-alt); }
.hero .btn-ghost, .gpu-page .btn-ghost, .tone-dark .btn-ghost {
  border-color: rgba(255,255,255,0.35); color: #fff;
}
.hero .btn-ghost:hover, .gpu-page .btn-ghost:hover,
.tone-dark .btn-ghost:hover { background: rgba(255,255,255,0.12); }
.btn-outline-dark { background: transparent; border-color: var(--heading); color: var(--heading); }
.btn-outline-dark:hover { background: var(--heading); color: var(--bg); }

/* Cards: white surface, dark text, red as the only accent. Sharp corners. */
.card {
  background: var(--color-surface-muted);
  /* Прозрачная рамка задумывалась «плоской по умолчанию», но на светлой теме
     фон карточки (--color-surface-muted) почти не отличим от фона полосы
     (--color-bg) — без видимой границы карточки сливаются в одно пятно.
     Граница цветом --color-border остаётся тонкой и плоской, просто видимой. */
  border: 1px solid var(--color-border); border-radius: var(--radius-surface);
  padding: var(--space-8); box-shadow: none;
  transition: border-color 0.15s var(--ease-out), box-shadow 0.2s var(--ease-out),
              transform 0.2s var(--ease-out);
}
@media (hover: hover) and (pointer: fine) {
  /* Тень — на любой карточке, не только на ссылке: кейсы <article> некликабельны,
     но тоже плоско сливались бы с фоном при наведении. Красная рамка и подъём
     остаются только у a.card — это подсказка «сюда можно нажать», и на
     некликабельной карточке она была бы враньём. */
  .card:hover { box-shadow: var(--shadow-card-hover); }
  a.card:hover { border-color: var(--red); transform: translateY(-3px); }
}
.card-accent-bar { height: 3px; background: var(--red); margin: -1.5rem -1.5rem 1.25rem; }
.card h2, .card h3 { color: var(--heading); }
/* Flat tile — for content nested inside a card/section (no card-in-card) */
.tile {
  background: var(--card-alt); border-left: 3px solid var(--red);
  padding: var(--space-6);
}
/* Tinted-background modifier for a nested .card (e.g. a card-in-card row) —
   was repeated as inline background:var(--card-alt) in several templates. */
.card-alt { background: var(--card-alt); }
.mt-0 { margin-top: 0; }
/* Soft red notice box — access-restriction hints and form errors on the login page */
.alert-red { background: rgba(220,38,38,0.12); border: 1px solid var(--border-red); color: var(--color-accent-soft); padding: var(--space-2) var(--space-4); }
/* Stat pair (big number + small label) — repeated 4x on the login page */
.stat-num { font-size: 1.75rem; color: var(--heading); }
.stat-label { font-size: 0.8rem; }
.form-label { display: block; font-size: 0.8rem; color: var(--text-dim); }
/* Flat list row — item card with title/meta on the left, status/action on
   the right; repeated across planner and my_orders. */
.list-row { padding: var(--space-4) 1.25rem; display: flex; justify-content: space-between; align-items: center; gap: 1rem; flex-wrap: wrap; }
/* Simple centered modal — dark overlay + card, toggled via style.display in JS */
.modal-overlay { display: none; position: fixed; inset: 0; background: rgba(0,0,0,0.8); z-index: 100; align-items: center; justify-content: center; padding: var(--space-4); }
.modal-card {
  max-width: 28rem; width: 100%;
  animation: modal-in 0.2s var(--ease-out) both;
}
/* Из scale(0.96), а не из нуля: в природе ничто не возникает из ничего,
   и появление «из точки» читается как сбой. Модалка не привязана к
   триггеру, поэтому origin остаётся по центру. */
@keyframes modal-in {
  from { opacity: 0; transform: scale(0.96); }
  to   { opacity: 1; transform: scale(1); }
}
/* Group header strip inside the infra-map diagram cards, repeated 3x */
.group-head { font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.02em; padding: var(--space-3) var(--space-4); background: var(--card-alt); border-bottom: 1px solid var(--border); }
/* Сервисы на карте инфраструктуры: домен — данные, поэтому он обязан
   сжиматься и переноситься внутри своей ячейки, а не растягивать карточку. */
.grid.infra-service-groups { grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr)); }
.infra-service-list { padding: 0 var(--space-4); }
.infra-service-row {
  display: grid;
  grid-template-columns: minmax(6.5rem, auto) minmax(0, 1fr);
  align-items: start;
  gap: var(--space-3);
  padding: 0.65rem 0;
  border-bottom: 1px solid var(--border);
  font-size: var(--text-base);
}
.infra-service-row:last-child { border-bottom: 0; }
.infra-service-host {
  min-width: 0;
  overflow-wrap: anywhere;
  text-align: right;
  font-size: 0.72rem;
  line-height: 1.35;
}
@media (max-width: 480px) {
  .infra-service-row { grid-template-columns: 1fr; gap: 0.22rem; }
  .infra-service-host { text-align: left; }
}
.icon-badge {
  width: 3rem; height: 3rem; display: flex; align-items: center; justify-content: center;
  background: var(--card-alt); border: 1px solid var(--border); margin-bottom: 0.75rem;
  transition: background 0.15s, border-color 0.15s, transform 0.15s;
}
.icon-badge img { width: 1.5rem; height: 1.5rem; display: block; }
.icon-badge svg { width: 1.5rem; height: 1.5rem; display: block; fill: var(--red); }
/* Outline icon set (inline SVG, stroke="currentColor") — separate from the
   filled social-media logos above, which stay on the fill rule. */
.icon-badge svg.icon-stroke, .title-icon svg { fill: none; stroke: var(--red); }
.title-icon svg { width: 1.5rem; height: 1.5rem; flex: none; margin-top: 0.15rem; display: block; }
@media (hover: hover) and (pointer: fine) {
  a.card:hover .icon-badge, .tile-btn:hover .icon-badge {
    background: var(--red); border-color: var(--red); transform: scale(1.08);
  }
}
a.card:hover .icon-badge svg { fill: #fff; }
a.card:hover .icon-badge svg.icon-stroke { fill: none; stroke: #fff; }
.grid { display: grid; gap: 1.5rem; }
.grid-2 { grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }
.grid-3 { grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); }
.grid-4 { grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }

/* Chips as dossier file-tags: square, condensed caps */
.chip { display: inline-flex; align-items: center; gap: var(--space-1); padding: 6px 12px; border-radius: var(--radius-pill); font-family: var(--font-text); font-size: var(--text-2xs); font-weight: 400; letter-spacing: 0; background: var(--card-alt); border: 1px solid var(--border); color: var(--text); }
.chip-red { background: rgba(220,38,38,0.12); border-color: var(--border-red); color: var(--color-accent-soft); }

.section-kicker { font-family: var(--font-mono); font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.04em; color: var(--red); font-weight: 700; margin: 0 0 0.4rem; }
.section-title { font-family: var(--font-text); font-weight: 600; letter-spacing: var(--tracking-heading); font-size: var(--text-2xl); line-height: var(--leading-heading); color: var(--heading); margin: 0 0 var(--space-2); }
.title-bar { width: 64px; height: 3px; background: var(--red); border: none; margin: 0.65rem 0 1rem; }
.section-block { border-top: 1px solid var(--border); padding-top: 1.5rem; margin-bottom: 2.5rem; }

/* Page header — kicker + H1.page-title + .title-bar + lead paragraph, the
   same four-part opener repeated at the top of every top-level page. */
.page-main { padding-top: 2rem; padding-bottom: 3rem; }
.page-title { color: var(--heading); margin: 0; }
.page-lead { max-width: 42rem; }

/* Closing CTA — the "one more nudge" block repeated at the bottom of
   services/cases/gallery: centered heading, optional lead, button row. */
.cta-block { text-align: center; margin-top: 3rem; }
.cta-lead { max-width: 32rem; margin: 0 auto 1.5rem; }
.cta-actions { display: flex; gap: 0.75rem; justify-content: center; flex-wrap: wrap; }

/* Case card — task/done/result columns, repeated per case. Specificity note:
   `.card h2, .card h3 { color: var(--heading) }` above outweighs a plain
   `.text-red` class on these h3s (0,1,1 beats 0,1,0) — pre-existing bug, the
   red label color never actually applied. Scope through .card to win. */
.case-label { font-size: 0.68rem; letter-spacing: 0.04em; text-transform: uppercase; margin: 0 0 0.4rem; }
.card .case-label { color: var(--red); }
.case-text { font-size: 0.88rem; margin: 0; }

/* Кейсы шли одним столбцом: у .case-list не было ни одного правила про
   раскладку (band-grid задаёт только отступ сверху), поэтому карточки просто
   стекали блоками во всю ширину. Реальная сетка + растяжка по высоте строки —
   разная длина описаний не рвёт ряд неровными краями. */
.case-list { grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); align-items: stretch; }
.case-list .card { display: flex; flex-direction: column; }

.case-head {
  display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-3);
  padding-bottom: var(--space-4); margin-bottom: var(--space-4);
  border-bottom: 1px solid var(--color-border);
}
/* min-width:0 позволяет flex-элементу сжаться меньше своего содержимого —
   без этого длинное имя клиента (nowrap) раздвигало .case-head и уводило
   документ в горизонтальный скролл на узких экранах. */
.case-client { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }

/* «Результат» — то, ради чего вообще читают карточку; тот же серый вес, что
   у «Задачи» и «Что сделано», топит главное в списке. Левая полоса выделяет
   его без лишнего веса — просто взгляд сам туда идёт. */
/* У кейса одно направление чтения: проблема → работа → итог. Три равные
   колонки выглядели как мелкий текст, а не как рассказ о результате. */
.case-flow {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 0;
  margin-top: var(--space-6); border: 1px solid var(--border);
}
.case-step {
  display: grid; grid-template-columns: auto 1fr; gap: var(--space-3);
  align-content: start; padding: var(--space-5); min-height: 11rem;
  border-right: 1px solid var(--border); background: rgba(255,255,255,0.025);
}
.case-step:last-child { border-right: 0; }
.case-step-num {
  font-family: var(--font-mono); font-size: var(--text-2xs); line-height: 1;
  color: var(--red); padding-top: 0.2rem;
}
.case-step .case-label { color: var(--text-dim); margin: 0 0 var(--space-3); }
.case-step .case-text { color: var(--text); font-size: var(--text-sm); line-height: 1.6; }
.case-step-result {
  background: linear-gradient(145deg, rgba(220,38,38,0.2), rgba(220,38,38,0.045));
  border-right: 0;
}
/* Колонка «Результат» красилась в --white — а этот токен светлый всегда,
   в обеих темах. Секция кейсов светлая, карточка белая, и главный текст
   карточки становился белым по белому. Берём --heading: он тон-зависимый,
   тёмный на светлом и светлый на тёмном. Акцент держится подложкой и
   насыщенностью номера, а не выворотом текста. */
.case-step-result .case-label { color: var(--red); }
.case-step-result .case-text { color: var(--heading); font-weight: 500; }
.case-step-result .case-step-num { color: var(--red); }
@media (max-width: 760px) {
  .case-flow { grid-template-columns: 1fr; }
  .case-step { min-height: 0; border-right: 0; border-bottom: 1px solid var(--border); padding: var(--space-4); }
  .case-step:last-child { border-bottom: 0; }
}
.text-red { color: var(--red); }
.text-dim { color: var(--text-dim); }

footer.site-footer { text-align: center; padding: 2.5rem 0; border-top: 1px solid var(--border); color: var(--text-dim); font-size: 0.875rem; background: var(--black); }
footer.site-footer p { color: #e4e4e7; }

/* Footer social icon row — links out to real profiles from pages.data.CONTACTS */
.social-icons { display: flex; flex-wrap: wrap; gap: 0.6rem; margin-top: 1.25rem; }
.social-icons a {
  width: 2.5rem; height: 2.5rem; display: flex; align-items: center; justify-content: center;
  background: var(--card-alt); border: 1px solid var(--border); color: var(--text-dim);
  transition: color 0.15s, border-color 0.15s;
}
.social-icons a:hover, .social-icons a:focus-visible { color: var(--red); border-color: var(--red); }
.social-icons svg { width: 1.15rem; height: 1.15rem; fill: currentColor; }

/* Order constructor */
.stepper { display: flex; justify-content: center; gap: 0.5rem; margin-bottom: 2rem; }
.step-dot { width: 2.75rem; height: 2.75rem; border-radius: 999px; display: flex; align-items: center; justify-content: center; font-weight: 700; font-size: 0.75rem; border: 2px solid var(--border); color: var(--text-dim); }
.step-dot.active { background: var(--red); border-color: var(--red); color: white; }
.step-panel { display: none; }
.step-panel.active {
  display: block;
  animation: step-in 0.22s var(--ease-out) both;
}
/* Шаг въезжает справа: без этого переход 1->2->3 читается как подмена
   страницы. Смещение маленькое (12px) — это подсказка о направлении,
   а не поездка. */
@keyframes step-in {
  from { opacity: 0; transform: translateX(12px); }
  to   { opacity: 1; transform: translateX(0); }
}
/* Подтверждение заявки — редкий и эмоциональный момент, единственное
   место, где уместно чуть больше времени. */
#order-success { animation: success-in 0.32s var(--ease-out) both; }
@keyframes success-in {
  from { opacity: 0; transform: scale(0.97); }
  to   { opacity: 1; transform: scale(1); }
}
/* Ошибка контакта: короткое проявление сверху. Намеренно без тряски —
   человек уже ошибся, добивать его дёрганьем незачем. */
#contact-error { animation: error-in 0.16s var(--ease-out) both; }
@keyframes error-in {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: translateY(0); }
}
input[type="radio"], input[type="checkbox"] { accent-color: var(--red); }
select, input[type="text"], input[type="password"], input[type="date"], textarea {
  background: var(--card-alt); border: 1px solid var(--border); color: var(--text);
  border-radius: var(--radius-surface); padding: var(--space-3) var(--space-4);
  width: 100%; font-family: inherit; font-size: var(--text-base);
}
.total-price { font-size: 2rem; font-weight: 800; color: var(--red); }
/* position:relative anchors the visually-hidden input inside (see below). */
.tile-btn { display: block; position: relative; text-align: center; padding: var(--space-2); border-radius: var(--radius-surface); border: 1px solid var(--border); background: var(--card-alt); cursor: pointer; font-size: var(--text-sm); color: var(--text); transition: border-color 0.15s, transform 0.15s; }
@media (hover: hover) and (pointer: fine) {
  .tile-btn:hover { border-color: var(--red); transform: translateY(-2px); }
}
.tile-btn.selected { background: var(--red); border-color: var(--red); color: white; }
@media (hover: hover) and (pointer: fine) {
  .tile-btn.selected:hover { transform: none; }
}
/* Input stays in the tab/a11y tree (unlike display:none) — only visually hidden. */
.tile-btn input { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0; }
.tile-btn:has(input:focus-visible) { outline: 2px solid var(--color-focus-ring); outline-offset: 2px; }

/* --- Конструктор: строки техники со степпером -------------------------------
   Было по выпадающему списку на каждую позицию — 20 полей «0..4» подряд, и
   невыбранная позиция занимала столько же места, сколько выбранная. Строка со
   степпером короче, значение видно без раскрытия, а выбранное сразу читается
   по красной планке слева. */
.field-group { margin-bottom: 1.75rem; }
.field-label {
  font-family: var(--font-mono); font-size: 0.7rem; text-transform: uppercase;
  letter-spacing: 0.04em; color: var(--red); font-weight: 700;
  display: flex; align-items: baseline; gap: 0.5rem; margin: 0 0 0.6rem;
}
.field-label .field-hint {
  font-family: var(--font-text); letter-spacing: 0; text-transform: none;
  color: var(--text-dim); font-weight: 400; font-size: 0.75rem;
}
.gear-list { border: 1px solid var(--border); background: var(--card); }
.gear-row {
  display: grid; grid-template-columns: 1fr auto auto; align-items: center; gap: 0.75rem;
  padding: var(--space-2) var(--space-3); border-bottom: 1px solid var(--border);
  border-left: 3px solid transparent; transition: border-color 0.15s, background 0.15s;
}
.gear-row:last-child { border-bottom: none; }
.gear-row.is-picked { border-left-color: var(--red); background: var(--card-alt); }
.gear-name { font-size: 0.9rem; color: var(--text); }
.gear-price { font-family: var(--font-mono); font-size: 0.72rem; color: var(--text-dim); white-space: nowrap; }
.qty-stepper { display: inline-flex; border: 1px solid var(--border); background: var(--card); }
.qty-stepper button {
  width: 2.1rem; height: 2.1rem; border: none; background: transparent; cursor: pointer;
  font-size: 1.05rem; line-height: 1; color: var(--text); font-family: inherit;
}
.qty-stepper button { transition: background 0.12s var(--ease-out), color 0.12s var(--ease-out), transform 0.12s var(--ease-out); }
@media (hover: hover) and (pointer: fine) {
  .qty-stepper button:hover { background: var(--red); color: #fff; }
}
/* Цель маленькая, поэтому сжатие заметнее, чем у обычной кнопки. */
.qty-stepper button:active { transform: scale(0.94); }
.qty-stepper input[type="number"] {
  width: 2.4rem; height: 2.1rem; text-align: center; padding: 0; background: transparent;
  border: none; border-left: 1px solid var(--border); border-right: 1px solid var(--border);
  font-family: var(--font-mono); font-size: 0.85rem; -moz-appearance: textfield;
}
.qty-stepper input::-webkit-outer-spin-button,
.qty-stepper input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.gear-row.is-picked .qty-stepper input { color: var(--red); font-weight: 700; }

/* --- Конструктор: панель сметы ----------------------------------------------
   Тёмная, как остальные «кинематографичные» блоки сайта: на светлой карточке
   итог терялся среди позиций, а сумма — то, ради чего эту страницу открывают. */
.estimate { background: var(--black); color: #e4e4e7; padding: var(--space-6); position: sticky; top: 5rem; }
/* Reusable dark card — the same "black card on a white page" idiom used ad
   hoc in a couple of places (e.g. the infra-map diagram card); one class
   instead of each spot re-declaring background/border-color inline. */
.panel-dark { background: var(--black); border-color: #232733; color: #e4e4e7; }
.estimate-head {
  font-family: var(--font-mono); font-size: 0.68rem; text-transform: uppercase;
  letter-spacing: 0.04em; color: #71717a; margin: 0 0 0.75rem;
}
.estimate-group + .estimate-group { margin-top: 1.1rem; }
.estimate-group-head {
  display: flex; justify-content: space-between; align-items: baseline; gap: 0.75rem;
  font-family: var(--font-mono); font-size: 0.66rem; text-transform: uppercase;
  letter-spacing: 0.02em; color: var(--red); font-weight: 700;
  border-bottom: 1px solid rgba(255,255,255,0.12); padding-bottom: 0.3rem; margin-bottom: 0.35rem;
}
.estimate-line { display: grid; grid-template-columns: 1fr auto; gap: 0.75rem; padding: var(--space-1) 0; font-size: 0.82rem; }
.estimate-line .amount { font-family: var(--font-mono); white-space: nowrap; color: var(--white); }
.estimate-line small { display: block; color: #71717a; font-size: 0.72rem; margin-top: 0.1rem; }
.estimate-total {
  display: flex; justify-content: space-between; align-items: baseline; gap: 1rem;
  border-top: 2px solid rgba(255,255,255,0.2); margin-top: 1.1rem; padding-top: 0.75rem;
}
.estimate-total span { font-family: var(--font-mono); font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.02em; color: #a1a1aa; }
.estimate-total b { font-family: var(--font-text); font-size: 1.9rem; font-weight: 800; color: var(--red); }
.estimate-empty { color: #71717a; font-size: 0.85rem; }

@media (max-width: 860px) {
  .estimate { position: static; }
}

/* Slider / carousel (testimonials, media gallery) */
.slider { position: relative; overflow: hidden; }
.slider-track { display: flex; transition: transform 0.5s ease; }
.slider-slide { flex: 0 0 100%; padding: 0 0.5rem; }
/* Belt-and-suspenders on top of the transform-based positioning above: an
   inactive slide is never just "off to the side", it's explicitly hidden.
   Fading out keeps visibility:hidden until the opacity transition finishes
   (transition-delay on visibility) so it never sits half-transparent on top
   of the incoming slide; the active slide flips back to visible instantly. */
.slider-slide { opacity: 0; visibility: hidden; transition: opacity 0.5s ease, visibility 0s linear 0.5s; }
.slider-slide.is-active { opacity: 1; visibility: visible; transition: opacity 0.5s ease; }
.slider-controls { display: flex; justify-content: center; align-items: center; gap: 1rem; margin-top: 1rem; }
.slider-dots { display: flex; gap: 0.4rem; }
.slider-dot {
  width: 2.75rem; height: 2.75rem; padding: 0; border: none; background: transparent; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
}
.slider-dot::before {
  content: ''; width: 0.65rem; height: 4px; background: #4a515a; transition: background 0.15s, width 0.2s;
}
.slider-dot.active::before { background: var(--red); width: 1.6rem; }
.slider-arrow {
  width: 44px; height: 44px; border-radius: var(--radius-pill); border: 1px solid var(--border);
  background: var(--card-alt); color: var(--heading); display: flex; align-items: center; justify-content: center;
  cursor: pointer; font-weight: 700; font-size: 1rem;
}
.slider-arrow:hover { border-color: var(--red); color: var(--red); }

/* Media grid — streaming/photo/video-related content */
.media-tile {
  position: relative; border-radius: var(--radius-surface); overflow: hidden; aspect-ratio: 4/3;
  display: flex; align-items: flex-end; padding: var(--space-4); color: white; font-weight: 700;
  background: linear-gradient(160deg, var(--black) 0%, var(--red-dark) 120%);
  transition: transform 0.25s ease, box-shadow 0.25s ease;
}
@media (hover: hover) and (pointer: fine) {
  .media-tile:hover { transform: translateY(-3px) scale(1.015); box-shadow: 0 16px 36px rgba(0,0,0,0.22); }
}
.media-tile span.tag { font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.1em; color: #f2b8b8; display: block; margin-bottom: 0.25rem; font-weight: 700; }
/* Photo variant — same dark-fade overlay + cover/center on every tile;
   only the photo itself (--tile-img) differs per instance. */
.media-tile-photo {
  background-image: linear-gradient(180deg, rgba(10,10,10,0.1) 0%, rgba(10,10,10,0.85) 100%), var(--tile-img);
  background-size: cover; background-position: center;
}

@media (max-width: 640px) {
  .hero .lead { font-size: 1.15rem; }
}

@media (max-width: 860px) {
  .login-grid { grid-template-columns: 1fr !important; gap: 2.5rem !important; }
  #footer-grid { grid-template-columns: 1fr 1fr !important; }
  .hide-mobile { display: none; }
}


.mono { font-family: var(--font-mono); }

/* Top status bar */
.statusbar {
  background: var(--black); border-bottom: 1px solid rgba(220,38,38,0.55);
  font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.04em;
  color: var(--text-dim); text-transform: uppercase;
}
.statusbar-inner { display: flex; justify-content: space-between; align-items: center; gap: 1rem; padding-block: 0.45rem; }
.statusbar .pulse-dot { width: 8px; height: 8px; border-radius: 999px; background: var(--red); display: inline-block; margin-right: 0.6rem; animation: pulse 2s ease-in-out infinite; }
@keyframes pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.3; } }

/* Outline badge — soft accent-tinted pill for short status text */
.badge-outline {
  display: inline-block; padding: var(--space-1) var(--space-3);
  background: rgba(220,38,38,0.1); border: 1px solid rgba(220,38,38,0.5); color: var(--color-accent-soft);
  font-family: var(--font-mono); font-size: 0.65rem; font-weight: 700;
  letter-spacing: 0.04em; text-transform: uppercase;
}

.btn-outline-red { background: transparent; border-color: var(--red); color: var(--red); }
.btn-outline-red:hover { background: var(--red); color: #fff; }

/* Stats strip under hero */
.stats-strip {
  background: var(--black); border-top: 1px solid rgba(220,38,38,0.5); border-bottom: 1px solid rgba(255,255,255,0.08);
  padding: var(--space-8) 0;
}
.stats-strip .stats-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 1rem; text-align: center; }
.stats-strip .num { font-family: var(--font-text); font-weight: 700; font-size: 2rem; color: var(--white); }
.stats-strip .num.red { color: var(--red); }
.stats-strip .cap { font-family: var(--font-mono); font-size: 0.65rem; letter-spacing: 0.04em; text-transform: uppercase; color: var(--text-dim); margin-top: 0.35rem; }

/* Footer status indicators */
.status-dot { width: 8px; height: 8px; border-radius: 999px; display: inline-block; margin-right: 0.55rem; flex: none; }
.status-ok { background: #5fd38a; }
.status-warn { background: #e6a417; }
.status-bad { background: var(--red); }

/* ==== Gallery ==== */
.gallery-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 0.75rem;
}
.gallery-item {
  all: unset; cursor: zoom-in; position: relative; display: block;
  aspect-ratio: 4 / 3; overflow: hidden; background: var(--card-alt);
  border: 1px solid var(--border); border-radius: 8px; transform: translateZ(0);
  transition: border-color 0.14s var(--ease-out), transform 0.16s var(--ease-out), box-shadow 0.16s var(--ease-out);
}
@media (hover: hover) and (pointer: fine) {
  .gallery-item:hover { border-color: var(--red); transform: translateY(-2px); box-shadow: 0 0.75rem 1.6rem rgba(0,0,0,0.3); }
}
.gallery-item:focus-visible { border-color: var(--red); }
.gallery-item img {
  width: 100%; height: 100%; object-fit: cover; display: block;
  transition: transform 0.22s var(--ease-out), opacity 0.14s var(--ease-out);
}
@media (hover: hover) and (pointer: fine) {
  .gallery-item:hover img { transform: scale(1.025); }
}
.gallery-caption {
  position: absolute; left: 0; right: 0; bottom: 0; padding: var(--space-6) var(--space-3) var(--space-2);
  font-family: var(--font-text); font-size: 0.72rem; letter-spacing: 0.02em;
  text-transform: uppercase; color: #fff;
  background: linear-gradient(180deg, transparent, rgba(10,10,12,0.9));
}

/* Lightbox — native <dialog>, so Esc and focus trapping come for free. */
#lightbox {
  border: none; padding: 0; background: transparent; max-width: 96vw; max-height: 96vh;
  color: var(--text); overflow: visible;
}
#lightbox {
  opacity: 1; transform: scale(1);
  transition: opacity 0.2s var(--ease-out), transform 0.2s var(--ease-out);
}
/* Открытие из scale(0.97), а не из нуля. Лайтбокс не привязан к триггеру
   как поповер, поэтому origin остаётся по центру. */
@starting-style {
  #lightbox[open] { opacity: 0; transform: scale(0.97); }
}
#lightbox::backdrop { background: rgba(5,5,7,0.94); }
#lightbox img {
  display: block; max-width: 90vw; max-height: 82vh; object-fit: contain;
  border: 1px solid var(--border);
}
#lightbox p {
  margin: 0.75rem 0 0; text-align: center; font-family: var(--font-text);
  font-size: 0.8rem; letter-spacing: 0.02em; text-transform: uppercase; color: var(--text-dim);
}
#lightbox button {
  position: fixed; background: rgba(10,10,12,0.85); color: #fff; border: 1px solid var(--border);
  width: 2.75rem; height: 2.75rem; cursor: pointer; font-size: 1.25rem; line-height: 1;
  display: flex; align-items: center; justify-content: center;
}
#lightbox button:hover { border-color: var(--red); color: var(--red); }
#lb-close { top: 1.25rem; right: 1.25rem; }
#lb-prev { left: 1.25rem; top: 50%; transform: translateY(-50%); }
#lb-next { right: 1.25rem; top: 50%; transform: translateY(-50%); }

@media (max-width: 640px) {
  .gallery-grid { grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 0.5rem; }
  #lb-prev { left: 0.5rem; }
  #lb-next { right: 0.5rem; }
}

/* Scroll-reveal: sections/cards fade+rise into place as they enter the
   viewport (see static/js/reveal.js). Starts pre-hidden only once JS has
   confirmed it'll flip .is-visible — the .js-ready gate on <html> means a
   no-JS visitor (or a failed script load) always sees full content. */
.js-ready .reveal {
  opacity: 0; transform: translateY(18px);
  transition: opacity 0.6s ease, transform 0.6s ease;
}
.js-ready .reveal.is-visible { opacity: 1; transform: translateY(0); }

/* --- Переключатель темы ------------------------------------------------------
   Живёт в тёмной шапке на обеих темах, поэтому цвета взяты от шапки, а не от
   полотна страницы. Показываем только ту иконку, которая соответствует
   действию: в светлой теме — луну (включить тёмную), в тёмной — солнце. */
.theme-toggle {
  display: flex; align-items: center; justify-content: center;
  width: 2.25rem; height: 2.25rem; padding: 0;
  background: transparent; border: 1px solid rgba(255,255,255,0.22);
  color: #e4e4e7; cursor: pointer;
  transition: border-color 0.15s var(--ease-out), color 0.15s var(--ease-out),
              transform 0.12s var(--ease-out);
}
@media (hover: hover) and (pointer: fine) {
  .theme-toggle:hover { border-color: var(--red); color: var(--red); }
}
.theme-toggle:active { transform: scale(0.94); }
.theme-toggle svg { width: 1.05rem; height: 1.05rem; display: block; }
/* Значок показывает выбранный вариант: экран — «как на устройстве». */
.theme-toggle svg { display: none; }
.theme-toggle[data-choice="auto"] .icon-auto,
.theme-toggle:not([data-choice]) .icon-auto,
.theme-toggle[data-choice="light"] .icon-sun,
.theme-toggle[data-choice="dark"] .icon-moon { display: block; }

.theme-picker { position: relative; }
.theme-menu {
  position: absolute; top: calc(100% + 0.5rem); right: 0; z-index: 60;
  display: flex; flex-direction: column; gap: 2px; min-width: 13rem; padding: 0.35rem;
  background: var(--card); border: 1px solid var(--border); border-radius: 12px;
  box-shadow: var(--shadow-card-hover);
}
.theme-menu[hidden] { display: none; }
.theme-menu button {
  display: flex; align-items: center; gap: 0.6rem; width: 100%; padding: 0.55rem 0.7rem;
  background: transparent; border: 0; border-radius: 8px; cursor: pointer;
  font: inherit; font-size: var(--text-xs); color: var(--text); text-align: left;
}
.theme-menu button::before {
  content: ""; width: 0.95rem; flex: 0 0 0.95rem; text-align: center; color: var(--red); font-weight: 700;
}
.theme-menu button[aria-checked="true"]::before { content: "✓"; }
.theme-menu button:hover, .theme-menu button:focus-visible { background: var(--card-alt); outline: none; }

/* --- Тон секции -------------------------------------------------------------
   Главное отличие от «темы страницы»: тон задаётся не на всём документе, а на
   каждой секции отдельно. Секция переопределяет семантические токены у себя —
   и всё, что внутри (карточки, кнопки, чипы, текст), перекрашивается само,
   без единой дополнительной строчки на компонент.

   Именно так устроена «то тёмное, то светлое» подача: пользователь ничего не
   переключает, полосы чередуются по мере прокрутки. */
.tone-dark {
  --color-bg: #000;
  --color-surface: #111214;
  --color-surface-muted: #17181c;
  --color-border: #2b2e36;
  --color-heading: #f5f5f7;
  --color-text: #d4d4d8;
  --color-text-muted: #8b8b93;
  --color-inverse-bg: #17181d;
  --color-inverse-text: #f5f5f7;
  --shadow-card: 0 2px 10px rgba(0,0,0,0.5);
  --shadow-card-hover: 0 14px 32px rgba(0,0,0,0.65);

  /* Алиасы обязаны переопределяться здесь же. var() внутри значения кастомного
     свойства подставляется один раз — там, где свойство объявлено. Объявленный
     в :root --heading уже «запёкся» в цвет активной темы страницы, и смена
     --color-heading на секции его не трогает: в светлой полосе оставался
     светлый текст на светлом фоне. */
  --bg: var(--color-bg);
  --card: var(--color-surface);
  --card-alt: var(--color-surface-muted);
  --border: var(--color-border);
  --border-red: var(--color-border-accent);
  --red: var(--color-accent);
  --red-dark: var(--color-accent-hover);
  --text: var(--color-text);
  --text-dim: var(--color-text-muted);
  --heading: var(--color-heading);
  --black: var(--color-inverse-bg);
  --white: var(--color-inverse-text);
  color-scheme: dark;
  background: var(--color-bg);
  color: var(--color-text);
}
/* Светлая полоса — не белая карточка: серо-бумажная подложка и тёмный текст.
   На ней читается смысл, после чего тёмная сцена показывает реальное железо. */
.landing-surface {
  background: radial-gradient(70% 70% at 88% 12%, rgba(220,38,38,0.07), transparent 62%), #f3f4f6;
}
.service-chapter { background: #f3f4f6; border-top: 1px solid #d4d7dc; }
.service-chapter > .band { background: transparent; }
.tone-light {
  --color-bg: #f8f8f5;
  --color-surface: #ffffff;
  --color-surface-muted: #edeceb;
  --color-border: #e4e2df;
  --color-heading: #161616;
  --color-text: #2b2b2b;
  --color-text-muted: #6b7280;
  --color-inverse-bg: #0d0d0e;
  --color-inverse-text: #fff;
  --shadow-card: 0 2px 10px rgba(0,0,0,0.05);
  --shadow-card-hover: 0 12px 20px -6px rgba(0,0,0,0.18), 0 6px 8px -6px rgba(0,0,0,0.14);

  /* Алиасы обязаны переопределяться здесь же. var() внутри значения кастомного
     свойства подставляется один раз — там, где свойство объявлено. Объявленный
     в :root --heading уже «запёкся» в цвет активной темы страницы, и смена
     --color-heading на секции его не трогает: в светлой полосе оставался
     светлый текст на светлом фоне. */
  --bg: var(--color-bg);
  --card: var(--color-surface);
  --card-alt: var(--color-surface-muted);
  --border: var(--color-border);
  --border-red: var(--color-border-accent);
  --red: var(--color-accent);
  --red-dark: var(--color-accent-hover);
  --text: var(--color-text);
  --text-dim: var(--color-text-muted);
  --heading: var(--color-heading);
  --black: var(--color-inverse-bg);
  --white: var(--color-inverse-text);
  color-scheme: light;
  background: var(--color-bg);
  color: var(--color-text);
}

/* Полоса во всю высоту экрана: секция — это экран, а не абзац. */
.band {
  min-height: 100svh;
  display: flex; flex-direction: column; justify-content: center;
  padding: var(--space-24) 0;
  position: relative;
}
.band-inner { max-width: var(--container); margin: 0 auto; padding: 0 var(--space-6); width: 100%; }
/* Секции, которым высота экрана ни к чему (контакты, подвал истории). */
.band-auto { min-height: 0; padding: var(--space-24) 0; }

.band-kicker {
  font-family: var(--font-mono); font-size: var(--text-2xs);
  letter-spacing: 0.04em; text-transform: uppercase; color: var(--red);
  margin: 0 0 var(--space-4);
}
.band-title {
  font-family: var(--font-text); font-weight: 600;
  font-size: var(--text-3xl); line-height: var(--leading-heading);
  letter-spacing: var(--tracking-heading);
  color: var(--color-heading); margin: 0;
}
.band-lead {
  font-size: var(--text-lg); color: var(--color-text-muted);
  max-width: 38rem; margin: var(--space-6) 0 0; line-height: 1.5;
}

/* --- Одностраничник: элементы полос ----------------------------------------- */
.band-title-xl { font-size: var(--text-4xl); }
.band-lead-center { margin-left: auto; margin-right: auto; }
.band-center { text-align: center; }
.band-center .band-lead { margin-left: auto; margin-right: auto; }
.band-actions { margin-top: var(--space-8); }
.band-grid { margin-top: var(--space-12); }
.band-split {
  display: grid; grid-template-columns: 1.2fr 1fr;
  gap: var(--space-16); align-items: center;
}
.training-split {
  display: grid; grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
  gap: var(--space-12); align-items: center;
}
.training-band {
  min-height: min(46rem, 88svh);
  background:
    radial-gradient(52% 70% at 80% 50%, rgba(220,38,38,0.12), transparent 68%),
    #08090c;
}
.training-illustration { width: min(100%, 36rem); margin: 0 0 0 auto; position: relative; }
.training-illustration::before {
  content: ''; position: absolute; inset: 16% 12%; z-index: 0;
  background: radial-gradient(circle, rgba(220,38,38,0.2), transparent 68%);
  filter: blur(2rem);
}
.training-illustration img {
  position: relative; z-index: 1; display: block; width: 100%; height: auto;
  filter: saturate(0.86) brightness(0.85) contrast(1.06) drop-shadow(0 1.5rem 2.4rem rgba(0,0,0,0.5));
}

/* Первый экран: фото уходит в затемнение, чтобы текст читался на любой картинке */
.hero-band { justify-content: center; overflow: hidden; background: #030405; isolation: isolate; }
.hero-band .band-visual { z-index: 0; background: #030405; }
/* Отдельная «плёнка» именно между роликом и интерфейсом. Она не является
   частью видео: текст остаётся идеально читаемым на любом его кадре. */
.hero-band .band-visual::after {
  z-index: 3;
  background:
    linear-gradient(90deg, rgba(4,5,7,0.92) 0%, rgba(4,5,7,0.76) 42%, rgba(4,5,7,0.36) 75%, rgba(4,5,7,0.58) 100%),
    linear-gradient(180deg, rgba(0,0,0,0.18), rgba(0,0,0,0.36));
  backdrop-filter: blur(1.5px);
  -webkit-backdrop-filter: blur(1.5px);
}
.hero-band-photo {
  position: absolute; inset: 0;
  background-size: cover; background-position: center;
  opacity: 0.45;
}
.hero-band::after {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(100deg, #000 8%, rgba(0,0,0,0.72) 45%, rgba(0,0,0,0.35) 100%);
}
.hero-band-text { position: relative; z-index: 4; }
.band-scroll {
  position: absolute; left: 0; right: 0; bottom: var(--space-8); z-index: 1;
  text-align: center; margin: 0;
  font-family: var(--font-mono); font-size: var(--text-2xs);
  letter-spacing: 0.04em; text-transform: uppercase; color: var(--color-text-muted); z-index: 4;
}

/* Крупные числа — общий элемент цифр, кейсов и характеристик */
.figure-row { display: flex; flex-wrap: wrap; gap: var(--space-16); }
.figure-row-stack { flex-direction: column; gap: var(--space-8); }
.figure-row-tight { gap: var(--space-8); margin: var(--space-4) 0; }
.figure-num {
  font-family: var(--font-text); font-weight: 700;
  font-size: var(--text-3xl); line-height: 1; color: var(--color-heading);
  letter-spacing: -0.02em;
}
.figure-num-sm { font-size: var(--text-xl); }
.figure-cap {
  font-family: var(--font-mono); font-size: var(--text-2xs);
  letter-spacing: 0.04em; text-transform: uppercase; color: var(--color-text-muted);
  margin-top: var(--space-2);
}

.card-title { font-size: var(--text-lg); margin: var(--space-3) 0 0; color: var(--color-heading); }
.card-title-sm { font-size: var(--text-base); }
.card-price { font-size: var(--text-xs); letter-spacing: 0.02em; text-transform: uppercase; margin: var(--space-2) 0 0; color: var(--color-text-muted); }
.card-desc { font-size: var(--text-sm); margin: var(--space-2) 0 0; }

.quote { margin: 0; padding: var(--space-6); border-left: 3px solid var(--red); background: var(--color-surface-muted); }
.quote-text { font-size: var(--text-base); color: var(--color-text); margin: 0 0 var(--space-4); }
.quote-author { font-weight: 700; color: var(--color-heading); font-size: var(--text-sm); }

/* Раньше блок был искусственно сжат до 52rem (832px), пока вся остальная
   лента идёт на всю ширину контейнера (--container) — контакты выглядели
   куце по сравнению с соседними секциями. Ширина колонки увеличена до 260px:
   на семи карточках это даёт более ровную сетку 4+3 вместо мельтешения. */
.contacts-grid { grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }
.contacts-badge { margin: 0 auto var(--space-2); }
.contact-cta {
  display: grid; grid-template-columns: minmax(0, 0.9fr) minmax(20rem, 1.1fr);
  gap: var(--space-16); align-items: center;
}
.contact-cta-links { gap: var(--space-3); }
.contact-cta-links .card { min-height: 9rem; display: flex; flex-direction: column; justify-content: center; }
.contact-cta-links .contacts-badge { margin: 0 0 var(--space-3); }

@media (max-width: 900px) {
  .band-split { grid-template-columns: 1fr; gap: var(--space-12); }
  .training-split { grid-template-columns: 1fr; gap: var(--space-8); }
  .training-illustration { max-width: 32rem; margin-inline: auto; }
  .contact-cta { grid-template-columns: 1fr; gap: var(--space-8); }
  .contact-cta-links { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .contact-cta-links .card { min-height: 0; padding: var(--space-5); }
  .figure-row { gap: var(--space-8); }
  .band { min-height: 0; padding: var(--space-16) 0; }
  .hero-band { min-height: 100svh; }
}

/* --- Полноэкранный визуал полосы --------------------------------------------
   Фото лежит под содержимым во всю полосу и медленно плывёт по мере
   прокрутки. Плывёт не сам фон, а слой с картинкой: анимировать
   background-position дорого (перерисовка на каждый кадр), transform —
   бесплатно, он считается на композиции. */
.band-visual { position: absolute; inset: 0; overflow: hidden; pointer-events: none; }
.band-visual::after { content: ''; position: absolute; inset: 0; z-index: 2; }
.band-visual img,
.band-visual video,
.band-visual .band-visual-img {
  position: absolute; inset: -8% 0; width: 100%; height: 116%;
  object-fit: cover;
  background-size: cover; background-position: center;
}
/* Видео лежит под заранее загруженным кадром. Смена начинается только после
   canplay, поэтому нет чёрного мигания и нет скачка первого экрана. */
.band-visual-video { z-index: 0; opacity: 0; transition: opacity var(--dur-base) var(--ease-out); }
.band-visual-poster { z-index: 1; transition: opacity var(--dur-base) var(--ease-out); }
.hero-band.is-video-ready .band-visual-video { opacity: 1; }
.hero-band.is-video-ready .band-visual-poster { opacity: 0; }
/* Затемнение/засветление под тон полосы: текст обязан читаться поверх любой
   фотографии, а не «обычно читается». */
.tone-dark .band-visual::after {
  background: linear-gradient(100deg, #000 6%, rgba(0,0,0,0.82) 42%, rgba(0,0,0,0.45) 100%);
}
.tone-light .band-visual::after {
  background: linear-gradient(100deg, #fbfbfd 6%, rgba(251,251,253,0.9) 45%, rgba(251,251,253,0.6) 100%);
}
.tone-light .band-visual .band-visual-img { opacity: 0.5; }
.band > .band-inner { position: relative; z-index: 1; }

/* --- Разбор по прокрутке ----------------------------------------------------
   Содержимое полосы въезжает ступенями, пока полоса пересекает экран.
   Всё внутри @supports: без поддержки scroll-driven анимаций содержимое
   просто на месте — страница остаётся читаемой, а не пустой. */
@supports (animation-timeline: view()) {
  .band-visual .band-visual-img,
  .band-visual video,
  .band-visual img {
    animation: visual-drift linear both;
    animation-timeline: view();
    animation-range: cover 0% cover 100%;
  }
  @keyframes visual-drift {
    from { transform: translateY(-4%) scale(1.06); }
    to   { transform: translateY(4%) scale(1.06); }
  }

  /* Диапазон держится целиком внутри фазы entry (0% — низ элемента коснулся
     низа экрана, 100% — элемент весь вошёл в экран). У фазы cover для
     элемента короче экрана «100%» наступает только когда он почти весь
     проскроллил мимо — на карточках это тянулось на сотни лишних пикселей
     полупрозрачности уже после того, как текст читаем. entry гарантированно
     завершается к моменту, когда карточка целиком на экране, независимо от
     её высоты. */
  .band-reveal > * {
    animation: band-rise linear both;
    animation-timeline: view();
    animation-range: entry 0% entry 45%;
  }
  /* Ступени задаются сдвигом диапазона, а не animation-delay: у прокрутки нет
     «через N секунд», её шкала — положение полосы на экране. */
  .band-reveal > *:nth-child(2) { animation-range: entry 6% entry 51%; }
  .band-reveal > *:nth-child(3) { animation-range: entry 12% entry 57%; }
  .band-reveal > *:nth-child(4) { animation-range: entry 18% entry 63%; }
  .band-reveal > *:nth-child(5) { animation-range: entry 22% entry 67%; }
  .band-reveal > *:nth-child(6) { animation-range: entry 26% entry 71%; }

  @keyframes band-rise {
    from { opacity: 0; transform: translateY(24px); }
    to   { opacity: 1; transform: translateY(0); }
  }

  /* Плитки и карточки внутри сетки въезжают своей волной. */
  .band-grid > * {
    animation: band-rise linear both;
    animation-timeline: view();
    animation-range: entry 0% entry 50%;
  }
  .band-grid > *:nth-child(2) { animation-range: entry 6% entry 56%; }
  .band-grid > *:nth-child(3) { animation-range: entry 12% entry 62%; }
  .band-grid > *:nth-child(4) { animation-range: entry 18% entry 68%; }
  .band-grid > *:nth-child(5) { animation-range: entry 22% entry 72%; }
  .band-grid > *:nth-child(6) { animation-range: entry 26% entry 76%; }

  /* Первый экран: текст уходит, пока полоса покидает экран — так следующая
     полоса не «наезжает» на ещё живой заголовок. */
  .hero-band-text {
    animation: hero-part linear both;
    animation-timeline: view();
    animation-range: exit 0% exit 90%;
  }
  @keyframes hero-part {
    from { opacity: 1; transform: translateY(0); }
    to   { opacity: 0; transform: translateY(-40px); }
  }
}

@media (prefers-reduced-motion: reduce) {
  .band-reveal > *, .band-grid > *, .hero-band-text,
  .band-visual img, .band-visual video, .band-visual .band-visual-img {
    animation: none !important; opacity: 1 !important; transform: none !important;
  }
  .band-visual-video { display: none; }
}

/* --- Полоса услуги ---------------------------------------------------------- */
.service-meta { display: flex; align-items: baseline; gap: var(--space-3); flex-wrap: wrap; margin-top: var(--space-6); }
.service-price { font-size: var(--text-xs); letter-spacing: 0.02em; text-transform: uppercase; color: var(--color-text-muted); }
.service-price b { font-size: var(--text-lg); }
.service-groups { display: grid; gap: var(--space-6); margin-top: 0; }
.service-group-title {
  font-family: var(--font-mono); font-size: var(--text-2xs);
  letter-spacing: 0.04em; text-transform: uppercase; color: var(--color-text-muted);
  margin: 0 0 var(--space-2); font-weight: 600;
}
.chip-row { display: flex; flex-wrap: wrap; gap: var(--space-2); }

.price-table { width: 100%; border-collapse: collapse; font-size: var(--text-sm); }
.price-table tr { border-bottom: 1px solid var(--border); }
.price-table td { padding: var(--space-2) 0; color: var(--color-text); }
.price-amount { text-align: right; white-space: nowrap; color: var(--color-heading); font-weight: 600; }

/* Подвал сцены: та же типографика, что и у шапки, но без верхнего отступа —
   иначе на липкой сцене он отъезжает от изделия. */
.scene-foot { padding-top: 0; padding-bottom: var(--space-8); }

/* --- Галерея на ленте: полоса на направление -------------------------------
   Восемь десятков кадров подряд не читаются: непонятно, что именно показано.
   Каждая полоса подписана направлением и прокручивается вбок — глазу есть за
   что зацепиться, а высота секции остаётся вменяемой. */
/* Мозаика галереи.
   Сетка на фиксированных рядах, а не на auto-rows: карточка «крупная» тогда
   занимает ровно два ряда и два столбца, и dense-упаковка затягивает дыры
   следующим подходящим кадром. Без dense каждая крупная карточка оставляла
   бы за собой пустой прямоугольник. */
.photo-mosaic {
  display: grid; gap: var(--space-3);
  grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr));
  grid-auto-rows: 7rem; grid-auto-flow: dense;
  margin-top: var(--space-6);
}
.photo-mosaic .gallery-item { aspect-ratio: auto; grid-row: span 2; }
/* Каждый пятый — во всю ширину двух колонок. Ритм задан вёрсткой, а не
   разметкой: подпись «крупный кадр» в имени файла попросила бы редактора
   думать о сетке. */
.photo-mosaic .gallery-item:nth-child(5n + 1) { grid-column: span 2; grid-row: span 3; }
.photo-mosaic .gallery-item[hidden] { display: none; }

/* Подпись — только под курсором: на полусотне кадров постоянные плашки
   складываются в сплошную серую полосу и читать их никто не станет.
   Текст при этом остаётся в DOM и в aria-label, так что скринридер и
   лайтбокс видят его всегда. */
@media (hover: hover) and (pointer: fine) {
  .photo-mosaic .gallery-caption {
    opacity: 0; transform: translateY(0.5rem);
    transition: opacity var(--dur-base) var(--ease-out), transform var(--dur-base) var(--ease-out);
  }
  .photo-mosaic .gallery-item:hover .gallery-caption,
  .photo-mosaic .gallery-item:focus-visible .gallery-caption { opacity: 1; transform: none; }
}

.photo-more { display: block; margin: var(--space-6) auto 0; }
.photo-more[hidden] { display: none; }

.photo-filters { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-top: var(--space-6); }
.chip-filter {
  cursor: pointer; display: inline-flex; align-items: center; gap: 0.5rem;
  font: inherit; font-size: var(--text-sm);
  transition: background var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out),
              border-color var(--dur-fast) var(--ease-out);
}
.chip-filter .mono { font-size: var(--text-2xs); opacity: 0.6; }
.chip-filter.is-active {
  background: var(--red); border-color: var(--red); color: #fff;
}
.chip-filter.is-active .mono { opacity: 0.8; }

@media (max-width: 700px) {
  .photo-mosaic { grid-template-columns: repeat(auto-fill, minmax(8rem, 1fr)); grid-auto-rows: 5rem; }
  .photo-mosaic .gallery-caption { opacity: 1; }
}

.video-card { padding: 0; overflow: hidden; }
.video-facade {
  all: unset; cursor: pointer; display: block; position: relative; width: 100%;
  aspect-ratio: 16 / 9; background: #000;
}
.video-facade img { width: 100%; height: 100%; object-fit: cover; opacity: 0.75; }
.video-play {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  font-size: 2rem; color: #fff;
}
.video-card figcaption { padding: var(--space-3) var(--space-4); }

/* Компактная кнопка — в шапке, где высота полосы ограничена. Раньше кегль и
   отступы задавались инлайном и спорили с системой: кнопка была 12.8px при
   заявленных 17px. */
.btn-compact { padding: var(--space-2) var(--space-4); font-size: var(--text-xs); }

/* --- Стекло и градиенты -----------------------------------------------------
   Тот же приём, что продают в стоковых «3D tech» шаблонах: матовая панель с
   бликом по верхней кромке и градиентная подсветка. Здесь он собран на CSS —
   без покупки лицензии, в нашей палитре и с нашими числами вместо lorem ipsum.
   Матовое стекло уже работает в шапке сайта, это то же самое семейство. */
.glass {
  position: relative;
  background: linear-gradient(160deg, rgba(255,255,255,0.10), rgba(255,255,255,0.02));
  backdrop-filter: saturate(160%) blur(18px);
  -webkit-backdrop-filter: saturate(160%) blur(18px);
  border: 1px solid rgba(255,255,255,0.14);
  border-radius: var(--radius-surface);
  overflow: hidden;
}
/* Блик по верхней кромке — то, что делает панель «стеклянной», а не серой. */
.glass::before {
  content: ''; position: absolute; inset: 0 0 auto 0; height: 1px;
  background: linear-gradient(90deg, transparent, rgba(255,255,255,0.55), transparent);
}
/* На светлой полосе стекло берётся от тёмного, иначе панель растворяется. */
.tone-light .glass {
  background: linear-gradient(160deg, rgba(0,0,0,0.05), rgba(0,0,0,0.01));
  border-color: rgba(0,0,0,0.10);
}
.tone-light .glass::before { background: linear-gradient(90deg, transparent, rgba(255,255,255,0.9), transparent); }

/* Число с градиентной заливкой — акцент на цифре, а не на подложке. */
.figure-num-grad {
  background: linear-gradient(150deg, var(--color-heading) 10%, var(--red) 120%);
  -webkit-background-clip: text; background-clip: text; color: transparent;
}

/* Полоса метрик стеклянными плитками */
.figure-grid {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--space-4);
}
.figure-grid .figure { padding: var(--space-8) var(--space-6); text-align: left; }
.figure-grid .figure-num { font-size: var(--text-3xl); }

@media (max-width: 833px) {
  .figure-grid { grid-template-columns: repeat(2, 1fr); }
}

/* --- Изометрическая сетка узла ---------------------------------------------
   Схема из стоковых шаблонов («кубы блокчейна»), но собранная из обычных
   элементов и подписанная нашими цифрами. Наклон делает CSS-трансформация —
   отдельная картинка не нужна, и на любом экране остаётся резкой. */
.iso-grid {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--space-3);
  /* Наклон визуально увеличивает след сетки примерно в полтора раза, поэтому
     ширина берётся с запасом и добавляется масштаб — иначе крайние ячейки
     уезжают за край экрана. */
  /* Ширина задаётся явно, а не через max-width: во флекс-контейнере колонки
     1fr без содержимого сжимаются в ноль, и сетка схлопывается в точку. */
  width: min(22rem, 74vw); flex: 0 0 auto; margin-inline: auto;
  transform: rotateX(54deg) rotateZ(-45deg) scale(0.92);
  transform-style: preserve-3d;
}
.iso-cell {
  aspect-ratio: 1; border-radius: 6px;
  background: linear-gradient(160deg, rgba(255,255,255,0.12), rgba(255,255,255,0.02));
  border: 1px solid rgba(255,255,255,0.16);
  box-shadow: 0 12px 24px rgba(0,0,0,0.35);
}
/* Ускорители — акцентные ячейки; их восемь, как в узле. */
.iso-cell-gpu {
  background: linear-gradient(160deg, rgba(220,38,38,0.85), rgba(220,38,38,0.35));
  border-color: rgba(255,255,255,0.28);
}
.iso-wrap {
  perspective: 1200px;
  padding: var(--space-24) 0;
  display: flex; align-items: center; justify-content: center;
  min-height: 26rem;
}
.iso-legend {
  display: flex; gap: var(--space-6); justify-content: center; flex-wrap: wrap;
  margin-top: var(--space-12);
}
.iso-legend span { display: inline-flex; align-items: center; gap: var(--space-2); font-size: var(--text-xs); color: var(--color-text-muted); }
.iso-legend i { width: 12px; height: 12px; border-radius: 3px; display: inline-block; }

@supports (animation-timeline: view()) {
  .iso-cell {
    animation: iso-rise linear both;
    animation-timeline: view();
    animation-range: entry 20% cover 55%;
  }
  .iso-cell:nth-child(4n+2) { animation-range: entry 26% cover 60%; }
  .iso-cell:nth-child(4n+3) { animation-range: entry 32% cover 65%; }
  .iso-cell:nth-child(4n)   { animation-range: entry 38% cover 70%; }
  @keyframes iso-rise {
    from { opacity: 0; transform: translateZ(-60px); }
    to   { opacity: 1; transform: translateZ(0); }
  }
}
@media (prefers-reduced-motion: reduce) { .iso-cell { animation: none !important; opacity: 1; } }
@media (max-width: 833px) {
  .iso-grid { width: min(15rem, 68vw); transform: rotateX(50deg) rotateZ(-45deg) scale(0.9); }
  .iso-wrap { min-height: 20rem; }
}

/* --- Поля ввода по DESIGN_HITMAN --------------------------------------------
   Обводка 2px и белая заливка: поле должно читаться как поле даже на тёплом
   полотне, где мягкая рамка в 1px теряется. */
input[type="text"], input[type="email"], input[type="tel"], input[type="password"],
input[type="number"], select, textarea {
  background: var(--color-surface);
  color: var(--color-heading);
  border: 2px solid var(--color-surface-muted);
  border-radius: var(--radius-surface);
  padding: 12px 16px;
  font-family: var(--font-text);
  font-size: var(--text-sm);
  transition: border-color 0.2s var(--ease-out), box-shadow 0.2s var(--ease-out);
}
input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--red);
  box-shadow: 0 0 0 3px rgba(220, 38, 38, 0.15);
}

/* --- Переход-«портал» между первым экраном и историей услуг ----------------
   Это не декоративная анимация: она связывает обещание на первом экране с
   тем, как проект последовательно раскрывается ниже. Базовое состояние —
   полноценное видео, поэтому браузеры без Scroll Timeline не получают
   пустую или сломанную сцену. */
.scroll-portal {
  position: relative;
  height: 240svh;
  background: #030405;
  color: #f5f5f7;
}
.scroll-portal-sticky {
  position: sticky;
  top: 0;
  display: grid;
  place-items: center;
  height: 100svh;
  overflow: hidden;
  isolation: isolate;
  background: #030405;
}
.scroll-portal-video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transform: scale(1.02);
  clip-path: circle(100% at 50% 52%);
  -webkit-clip-path: circle(100% at 50% 52%);
  will-change: transform, clip-path;
}
.scroll-portal-shade {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background:
    linear-gradient(90deg, rgba(3,4,5,0.72), rgba(3,4,5,0.2) 55%, rgba(3,4,5,0.58)),
    linear-gradient(0deg, rgba(3,4,5,0.66), transparent 42%, rgba(3,4,5,0.4));
}
.scroll-portal-copy {
  position: relative;
  z-index: 2;
  width: min(100% - 2.5rem, 52rem);
  text-align: center;
  text-wrap: balance;
}
.scroll-portal-copy .band-kicker { color: rgba(255,255,255,0.72); }
.scroll-portal-copy h2 {
  margin: var(--space-5) 0;
  color: #fff;
  font-family: var(--font-display);
  font-size: clamp(2.5rem, 7vw, 6.75rem);
  line-height: 0.94;
  letter-spacing: -0.065em;
}
.scroll-portal-copy p:last-child {
  max-width: 37rem;
  margin: 0 auto;
  color: rgba(255,255,255,0.82);
  font-size: clamp(1rem, 1.8vw, 1.25rem);
}
.scroll-portal-hint {
  position: absolute;
  right: var(--space-6);
  bottom: var(--space-6);
  z-index: 2;
  margin: 0;
  color: rgba(255,255,255,0.62);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
@supports (animation-timeline: view()) {
  .scroll-portal { view-timeline-name: --portal; view-timeline-axis: block; }
  .scroll-portal-video {
    clip-path: circle(12% at 50% 52%);
    -webkit-clip-path: circle(12% at 50% 52%);
    animation: portal-open linear both;
    animation-timeline: --portal;
    animation-range: cover 8% cover 88%;
  }
  .scroll-portal-copy {
    animation: portal-copy linear both;
    animation-timeline: --portal;
    animation-range: cover 8% cover 78%;
  }
  .scroll-portal-hint {
    animation: portal-hint linear both;
    animation-timeline: --portal;
    animation-range: cover 8% cover 42%;
  }
  @keyframes portal-open {
    from { transform: scale(1.1); clip-path: circle(12% at 50% 52%); -webkit-clip-path: circle(12% at 50% 52%); }
    to { transform: scale(1); clip-path: circle(150% at 50% 52%); -webkit-clip-path: circle(150% at 50% 52%); }
  }
  @keyframes portal-copy {
    0%, 38% { opacity: 1; transform: translateY(0); }
    72%, 100% { opacity: 0; transform: translateY(-1rem); }
  }
  @keyframes portal-hint {
    0%, 45% { opacity: 1; }
    100% { opacity: 0; }
  }
}
@media (prefers-reduced-motion: reduce) {
  .scroll-portal { height: 100svh; }
  .scroll-portal-video { transform: none; }
  .scroll-portal-hint { display: none; }
}
@media (max-width: 833px) {
  .scroll-portal { height: 185svh; }
  .scroll-portal-copy { width: min(100% - 2rem, 30rem); }
  .scroll-portal-copy h2 { font-size: clamp(2.3rem, 13vw, 4.25rem); }
  .scroll-portal-hint { right: var(--space-4); bottom: var(--space-4); }
}

/* --- Taste pass 2026 -------------------------------------------------------
   Targeted evolution: one cold-neutral page language, one red accent and
   real media as the visual focus. Routes, copy structure and Django forms
   stay intact. */
html:root,
html:root:not([data-theme]) {
  --color-bg: #f2f3f5;
  --color-surface: #ffffff;
  --color-surface-muted: #e8eaed;
  --color-border: #d6d9de;
  --color-heading: #17191d;
  --color-text: #24272d;
  --color-text-muted: #666b74;
  --color-inverse-bg: #111318;
  --color-inverse-text: #ffffff;
  --bg: var(--color-bg);
  --card: var(--color-surface);
  --card-alt: var(--color-surface-muted);
  --border: var(--color-border);
  --heading: var(--color-heading);
  --text: var(--color-text);
  --text-dim: var(--color-text-muted);
  --black: var(--color-inverse-bg);
  --white: var(--color-inverse-text);
  --font-text: "Avenir Next", Avenir, -apple-system, BlinkMacSystemFont,
               "Segoe UI", Roboto, "Helvetica Neue", sans-serif;
  --font-display: "Avenir Next", Avenir, -apple-system, BlinkMacSystemFont,
                  "Segoe UI", Roboto, sans-serif;
  --container: 1180px;
  --radius-surface: 16px;
  --radius-button: 12px;
  --radius-lg: 24px;
  --shadow-card: 0 12px 34px rgba(25, 30, 38, 0.07);
  --shadow-card-hover: 0 22px 54px rgba(25, 30, 38, 0.12);
  color-scheme: light;
}

html { scroll-padding-top: 5rem; }
body { overflow-x: clip; }
h1, h2, h3 { text-wrap: balance; }
p { text-wrap: pretty; }

.skip-link {
  position: fixed; top: 0.75rem; left: 0.75rem; z-index: 100;
  padding: 0.7rem 1rem; border-radius: var(--radius-button);
  background: var(--red); color: #fff; transform: translateY(-150%);
  transition: transform var(--dur-fast) var(--ease-out);
}
.skip-link:focus { transform: translateY(0); }

.navbar {
  background: rgba(242, 243, 245, 0.88);
  border-bottom-color: rgba(23, 25, 29, 0.1);
  color: var(--heading);
}
.navbar-inner { min-height: 4.5rem; padding-block: 0.55rem; }
.navbar-brand { color: var(--heading); flex: 0 0 auto; }
/* nowrap on the links themselves: if the bar is too narrow, the whole
   account row wraps below (via .navbar-inner's own flex-wrap) instead of
   individual links breaking mid-list and inflating the bar unpredictably. */
/* Восемь пунктов вместе с «Платформой»: при прежнем зазоре до 1.4rem строка
   не помещалась в контейнер, и «Войти» уезжал на вторую строку. */
.navbar-links { flex-wrap: nowrap; gap: clamp(0.7rem, 1vw, 0.9rem); white-space: nowrap; }
.navbar-links a { color: #484d56; }
.navbar-links a:hover,
.navbar-links a.active { color: var(--red); }
.navbar-account { display: flex; align-items: center; justify-content: flex-end; gap: 0.5rem; }
.navbar-user { max-width: 10rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text-dim); font-size: var(--text-xs); }
.navbar-account .chip { padding: 0.35rem 0.55rem; }
.navbar-burger .bar { background: var(--heading); }
/* Auto-hide on scroll down (see nav.js) so the fixed bar doesn't cover
   content on long pages; any upward scroll brings it straight back. */
.navbar { transition: transform 0.25s var(--ease-standard, ease); }
/* Шапка центрируется через left: 50% + translateX(-50%) (см. «остров» ниже),
   поэтому сдвиг по X сохраняем, а вверх уводим на высоту плюс отступ сверху
   и тень — иначе край шапки оставался торчать над страницей. */
.navbar.is-hidden { transform: translate(-50%, calc(-100% - var(--space-3) - 24px)); }
.navbar-admin-dropdown { position: relative; }
.navbar-admin-toggle { cursor: pointer; }
.navbar-admin-menu {
  position: absolute;
  top: calc(100% + 0.5rem);
  right: 0;
  display: none;
  flex-direction: column;
  gap: 0.4rem;
  background: var(--card-alt);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 0.5rem;
  min-width: 10rem;
  z-index: 50;
}
.navbar-admin-menu.is-open { display: flex; }
.navbar-admin-menu .chip { justify-content: flex-start; }
.navbar-admin-toggle { display: inline-flex; align-items: center; gap: 0.35rem; }
.navbar-user-label { max-width: 9rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.navbar-menu-sep { display: block; height: 1px; background: var(--border); margin: 0.15rem 0; }

.hero-band { min-height: calc(100dvh - 4.5rem); }
.hero-band .band-inner { max-width: var(--container); }
.hero-band-text { justify-self: stretch; }
.hero-band .band-title-xl { max-width: 20ch; font-size: clamp(3rem, 6vw, 5.6rem); }
.hero-band .band-lead { max-width: 43rem; }

.tone-light,
.landing-surface {
  --bg: var(--color-bg);
  --card: var(--color-surface);
  --card-alt: var(--color-surface-muted);
  --border: var(--color-border);
  --heading: var(--color-heading);
  --text: var(--color-text);
  --text-dim: var(--color-text-muted);
  background: var(--color-bg);
  color: var(--color-text);
}

.band { min-height: min(46rem, 90dvh); }
.band-auto { padding-block: clamp(5rem, 9vw, 8rem); }
.band-title { max-width: 15ch; letter-spacing: -0.045em; }
.band-lead { max-width: 61ch; line-height: 1.55; }
.service-label {
  margin: 0 0 var(--space-4); color: var(--red); font-size: var(--text-xs);
  font-weight: 600; letter-spacing: 0.04em;
}
.service-chapter > .band { min-height: auto; padding-block: clamp(5rem, 8vw, 7rem); }
.service-chapter + .service-chapter { border-top: 1px solid var(--border); }
.service-groups { border-top: 1px solid var(--border); padding-top: var(--space-8); }

.metric-panel {
  position: relative; padding: var(--space-8) var(--space-6); text-align: left;
  border-top: 2px solid var(--heading);
}
.metric-panel::after {
  content: ""; position: absolute; top: -2px; left: 0; width: 2.5rem;
  height: 2px; background: var(--red);
}

.card {
  background: var(--card); border-color: rgba(23, 25, 29, 0.1);
  box-shadow: var(--shadow-card);
}
.chip { border-radius: 8px; }

.site-footer {
  padding: 4.5rem 0 0; text-align: left; background: #111318; color: #f6f7f8;
}
.footer-grid { display: grid; grid-template-columns: 1.4fr 1fr 1fr 1.1fr; gap: 3rem; }
.footer-brand { display: flex; align-items: center; gap: 0.7rem; margin-bottom: 0.5rem; }
.footer-summary { margin: 0.9rem 0 1.2rem; max-width: 34ch; color: #aeb3bc; font-size: var(--text-xs); line-height: 1.55; }
.footer-heading { margin: 0 0 1rem; color: #fff; font-weight: 600; font-size: var(--text-sm); }
.footer-links { display: grid; gap: 0.7rem; color: #aeb3bc; font-size: var(--text-xs); }
.footer-links a { transition: color var(--dur-fast) var(--ease-standard); }
.footer-links a:hover { color: #fff; }
.footer-bottom {
  display: flex; justify-content: space-between; gap: 1rem; flex-wrap: wrap;
  margin-top: 3rem; padding-block: 1.25rem; border-top: 1px solid rgba(255,255,255,0.1);
  color: #7f858f; font-size: var(--text-2xs);
}

@media (max-width: 1350px) {
  .navbar-links { display: none; }
  .navbar-burger { display: flex; }
  .navbar-links.is-open {
    display: flex; position: absolute; top: 100%; left: 0; right: 0;
    max-height: 32rem; padding: 0.75rem 1.5rem 1.25rem;
    background: rgba(242,243,245,0.98); border-bottom: 1px solid var(--border);
  }
}

@media (max-width: 768px) {
  .navbar-inner { flex-wrap: wrap; }
  .navbar-account .chip,
  .navbar-user { display: none; }
  .hero-band .band-title-xl { max-width: 12ch; font-size: clamp(2.65rem, 12vw, 4.25rem); }
  .band { min-height: auto; }
  .band-inner { padding-inline: var(--space-4); }
  .footer-grid { grid-template-columns: 1fr 1fr; gap: 2.5rem 1.5rem; }
}

@media (max-width: 520px) {
  .footer-grid { grid-template-columns: 1fr; }
  .footer-bottom { flex-direction: column; }
}

/* Shared internal-page composition. */
.page-main,
.login-page,
.about-content {
  padding-top: clamp(3rem, 7vw, 6rem);
  padding-bottom: clamp(4rem, 8vw, 7rem);
}
.article-page { max-width: 50rem; }
.article-page > .card { padding: clamp(1.5rem, 5vw, 3.5rem); }
.article-page p { max-width: 65ch; line-height: 1.7; }
.article-page h1 { max-width: 18ch; letter-spacing: -0.045em; }
.about-content { margin-top: 0; }
.login-page { padding-inline: var(--space-4); }
.login-page .card { background: #fff; }
.page-main > .card:first-child,
.about-content > .grid > div > .card:first-child { border-top: 3px solid var(--red); }

form input,
form select,
form textarea { width: 100%; }
details > summary { color: var(--heading); }

@media (max-width: 900px) {
  .login-grid { grid-template-columns: 1fr !important; gap: 2.5rem !important; }
  .login-grid > div:first-child { text-align: center; }
  .login-grid > div:first-child p { margin-inline: auto !important; }
  .login-grid > div:first-child > div { justify-content: center; }
}

/* Clear customer journey: choose a solution, understand the process, then inspect details. */
.solutions-band .band-inner { padding-top: clamp(3.5rem, 7vw, 6rem); padding-bottom: clamp(3rem, 6vw, 5rem); }
.solutions-band .band-title-xl { font-size: clamp(3rem, 6vw, 5.75rem); }
.solution-map {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1px;
  margin-top: clamp(2rem, 4vw, 3.5rem);
  overflow: hidden;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--border);
}
.solution-link {
  display: grid;
  grid-template-columns: 2.25rem 1fr auto;
  gap: 1rem;
  align-items: start;
  min-height: 8.5rem;
  padding: 1.5rem;
  color: var(--heading);
  background: var(--surface);
  transition: background .25s ease, color .25s ease;
}
.solution-link strong { display: block; font-size: clamp(1.1rem, 2vw, 1.45rem); line-height: 1.15; }
.solution-link small { display: block; max-width: 34ch; margin-top: .65rem; color: var(--muted); line-height: 1.45; }
.solution-index { color: var(--red); font-size: .75rem; }
.solution-arrow { font-size: 1.35rem; transition: transform .25s ease; }
.solution-link:hover { color: #fff; background: var(--ink); }
.solution-link:hover small { color: rgba(255,255,255,.68); }
.solution-link:hover .solution-arrow { transform: translate(3px, 3px); }

.workflow-band { padding-top: 0; }
.workflow-head { display: flex; justify-content: space-between; align-items: end; gap: 2rem; }
.workflow-list {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  margin: 3rem 0 0;
  padding: 0;
  list-style: none;
  border-top: 1px solid var(--border);
}
.workflow-list li { padding: 1.5rem 1.5rem 0 0; }
.workflow-list li + li { padding-left: 1.5rem; border-left: 1px solid var(--border); }
.workflow-list span { display: block; margin-bottom: 2rem; color: var(--red); font-size: .75rem; }
.workflow-list strong { display: block; color: var(--heading); font-size: 1.05rem; }
.workflow-list p { margin: .65rem 0 0; color: var(--muted); line-height: 1.55; }
.nav-primary { color: #fff !important; background: var(--red); padding: .72rem 1rem !important; border-radius: .6rem; }
.nav-primary:hover { background: var(--red-dark); }

@media (max-width: 760px) {
  .solution-map { grid-template-columns: 1fr; }
  .solution-link { min-height: 7rem; }
  .workflow-head { align-items: start; flex-direction: column; }
  .workflow-list { grid-template-columns: 1fr; }
  .workflow-list li { padding: 1.25rem 0; border-bottom: 1px solid var(--border); }
  .workflow-list li + li { padding-left: 0; border-left: 0; }
  .workflow-list span { margin-bottom: .75rem; }
}

/* ============================================================================
   ПРЕМИАЛЬНЫЙ СЛОЙ
   Правки поверх готовой системы токенов: ничего не переписывается с нуля,
   меняется характер поверхностей, навигации и движения.
   ========================================================================= */

/* --- 1. Зерно ---------------------------------------------------------------
   Идеально ровная заливка читается как «цифровая пустота». Плёночное зерно
   поверх всего убирает эту стерильность — тот же приём, что в печати.
   Слой фиксированный и не ловит события: он не должен ни скроллиться
   (иначе GPU перерисовывает его постоянно), ни перехватывать клики. */
body::after {
  content: '';
  position: fixed; inset: 0; z-index: 60; pointer-events: none;
  opacity: 0.035;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
}
@media (prefers-reduced-motion: reduce) { body::after { opacity: 0.02; } }

/* --- 2. Плавающая навигация -------------------------------------------------
   Шапка во всю ширину, приклеенная к нулю — самый узнаваемый признак
   шаблона. Отделяем её от края: остров из матового стекла, который висит
   над содержимым. Стекло здесь допустимо — элемент фиксированный, а не
   прокручиваемый, значит перерисовки постоянной не будет. */
.navbar {
  /* fixed, а не sticky: липкий элемент занимает место в потоке и отжимал
     сверху полосу фона — остров висел не над первым экраном, а под ним.
     Фиксированный ничего не занимает и ложится поверх кадра. */
  position: fixed; top: var(--space-3); left: 50%; transform: translateX(-50%);
  /* На 60px шире контента: восемь пунктов меню плюс две кнопки иначе не
     помещаются в одну строку на широких экранах. */
  width: min(calc(var(--container) + 60px), calc(100vw - var(--space-8)));
  /* Плотная тёмная панель вместо полупрозрачного стекла. Стекло подстраивалось
     под то, что под ним: над светлой полосой оно светлело, текст сливался, и
     меню читалось через раз. Непрозрачная подложка даёт один и тот же контраст
     на всей ленте — и над чёрным первым экраном, и над кремовыми секциями. */
  border-radius: 18px;
  background: #101319;
  border: 1px solid rgba(255,255,255,0.09);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.07),
    0 20px 44px -22px rgba(6,8,12,0.75);
}
/* Всё содержимое панели — светлое, независимо от тона секции под ней. */
.navbar,
.navbar .navbar-brand,
.navbar .navbar-brand span { color: #f4f5f7; }
.navbar .navbar-links a { color: rgba(244,245,247,0.72); font-size: 0.9rem; }
.navbar .navbar-links a:hover,
.navbar .navbar-links a.active { color: #fff; }
.navbar .navbar-burger .bar { background: #f4f5f7; }
/* Выпадающее меню — та же панель, а не светлая плашка от прежнего варианта. */
@media (max-width: 1350px) {
  .navbar .navbar-links.is-open {
    background: #101319;
    border: 1px solid rgba(255,255,255,0.09);
    border-radius: 18px;
    margin-top: var(--space-2);
    box-shadow: 0 24px 48px -24px rgba(6,8,12,0.8);
  }
}
.navbar-inner { padding-block: var(--space-2); padding-inline: var(--space-4); }
/* Внутри острова .container не нужен как ограничитель: ширину уже задаёт
   сама .navbar. Иначе содержимое упиралось в 1180px, а шрифт растёт вместе
   с корневым (--text-base в vw) — и «Войти» съезжал на вторую строку. */
.navbar .navbar-inner { max-width: none; }
.navbar-links a { position: relative; }
/* Подчёркивание вырастает из центра, а не появляется целиком. */
.navbar-links a::after {
  content: ''; position: absolute; left: 50%; right: 50%; bottom: -6px; height: 1.5px;
  background: var(--red); border-radius: 2px;
  transition: left var(--dur-fast) var(--ease-spring), right var(--dur-fast) var(--ease-spring);
}
@media (hover: hover) and (pointer: fine) {
  .navbar-links a:hover::after { left: 0; right: 0; }
}
.navbar-links a.active::after { left: 0; right: 0; }

/* --- 3. Двойная обечайка ----------------------------------------------------
   Карточка, положенная прямо на фон, выглядит наклейкой. Приём «оправа +
   вставка»: внешняя рамка чуть светлее фона, внутренняя поверхность своя,
   радиусы концентрические (внутренний = внешний минус отступ) — иначе углы
   выглядят вложенными неточно, глаз это ловит даже без линейки. */
.case-list .card,
#contacts .card,
#blog .card {
  padding: var(--space-2);
  background: var(--color-border);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
}
.case-list .card > *,
#contacts .card > *,
#blog .card > * { position: relative; z-index: 1; }
/* Вставка рисуется псевдоэлементом: не трогаем разметку, а внутренняя
   поверхность получает свой цвет, блик и радиус. */
.case-list .card::before,
#contacts .card::before,
#blog .card::before {
  content: ''; position: absolute; inset: var(--space-2); z-index: 0;
  background: var(--color-surface);
  border-radius: calc(var(--radius-lg) - var(--space-2));
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.55);
}
.tone-dark .case-list .card::before,
.tone-dark #contacts .card::before,
.tone-dark #blog .card::before { box-shadow: inset 0 1px 0 rgba(255,255,255,0.08); }
.case-list .card, #contacts .card, #blog .card { position: relative; }
/* Содержимое отодвигается от кромки оправы. */
.case-list .card > *:first-child { padding-top: var(--space-6); }
.case-list .card,
#contacts .card,
#blog .card { padding: var(--space-2) var(--space-8) var(--space-8); }

/* --- 4. Кнопка с вложенной иконкой ------------------------------------------
   Стрелка рядом с текстом выглядит приклеенной. Она получает свой круг,
   прижатый к правому внутреннему краю кнопки, и на наведении уходит по
   диагонали — внутри кнопки возникает собственное движение. */
.btn-primary { padding-right: var(--space-2); }
.btn-primary::after {
  content: '↗';
  display: inline-flex; align-items: center; justify-content: center;
  width: 2rem; height: 2rem; margin-left: var(--space-2);
  border-radius: var(--radius-pill);
  background: rgba(255,255,255,0.16);
  font-size: 0.8em; line-height: 1;
  transition: transform var(--dur-fast) var(--ease-spring), background var(--dur-fast) var(--ease-out);
}
@media (hover: hover) and (pointer: fine) {
  .btn-primary:hover::after { transform: translate(2px, -2px) scale(1.06); background: rgba(255,255,255,0.26); }
}
/* Кнопки-иконки и компактные вариации стрелку не получают: там она мешает. */
.btn-primary.btn-compact::after, .btn-icon.btn-primary::after { content: none; }
@media (prefers-reduced-motion: reduce) { .btn-primary::after { transition: none; } }

/* Навбар вынут из потока, поэтому содержимое страниц надо опустить под него.
   Исключение — лендинг: там первый экран во всю высоту и остров ложится
   прямо на кадр, как и задумано. */
main { padding-top: var(--navbar-h, 5rem); }
body:has(.hero-band) main { padding-top: 0; }

/* Первый экран лежит под плавающей навигацией, поэтому его содержимое
   обязано начинаться ниже острова — иначе надстрочная подпись уезжает
   под стекло и читается наполовину. Высота острова + отступ сверху. */
.hero-band .band-inner { padding-top: calc(4.5rem + var(--space-6)); }
@media (min-width: 769px) {
  .hero-band .band-inner { padding-top: calc(4.5rem + var(--space-3)); }
}

/* --- Доказательство под цифрами ---------------------------------------------
   Ролик стойки рядом с метриками. Не во всю ширину: широкое видео на светлой
   полосе перетягивает внимание с самих цифр, а оно здесь на вторых ролях —
   иллюстрирует, а не солирует. */
.metric-proof {
  display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr);
  gap: var(--space-8); align-items: center;
  margin: var(--space-16) 0 0;
}
/* Оправа и вставка — тот же приём, что у карточек кейсов. */
.metric-proof-frame {
  padding: var(--space-2); border-radius: var(--radius-lg);
  background: var(--color-border); border: 1px solid var(--color-border);
}
.metric-proof-video {
  display: block; width: 100%; aspect-ratio: 16 / 10; object-fit: cover;
  border-radius: calc(var(--radius-lg) - var(--space-2));
  background: #0b0c10;
}
.metric-proof-cap { display: grid; gap: var(--space-2); }
.metric-proof-cap strong { font-size: var(--text-lg); color: var(--color-heading); }
.metric-proof-cap > span:last-child { color: var(--color-text-muted); font-size: var(--text-sm); line-height: 1.5; }

@media (max-width: 860px) {
  .metric-proof { grid-template-columns: 1fr; gap: var(--space-6); margin-top: var(--space-12); }
}

/* ============================================================================
   СТРАНИЦА «ОБО МНЕ»
   Прежняя версия была карточками внутри карточек внутри карточек: глубина
   вложенности заменяла иерархию, и глаз не находил, что читать первым.
   Здесь иерархию держат размер, воздух и тон полосы, а рамок почти нет.
   ========================================================================= */

.about-hero { min-height: auto; padding-top: calc(4.5rem + var(--space-16)); padding-bottom: var(--space-24); }
.about-hero-grid {
  display: grid; grid-template-columns: minmax(0, 1.35fr) minmax(0, 0.65fr);
  gap: var(--space-16); align-items: center;
}
.about-roles {
  font-size: var(--text-lg); color: var(--red); font-weight: 500;
  margin: var(--space-4) 0 var(--space-2); line-height: 1.35;
}

/* Контакты — строка фактов, а не список ссылок мелким кеглем. */
.about-contacts {
  display: flex; flex-wrap: wrap; gap: var(--space-8);
  margin-top: var(--space-8); padding-top: var(--space-6);
  border-top: 1px solid var(--color-border);
}
.about-contact { display: grid; gap: 2px; text-decoration: none; }
.about-contact .mono {
  font-size: var(--text-2xs); letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--color-text-muted);
}
.about-contact strong { color: var(--color-heading); font-weight: 500; font-size: var(--text-sm); }
a.about-contact:hover strong { color: var(--red); }

/* Портрет: оправа и вставка, как у карточек — один язык на весь сайт. */
.about-portrait {
  margin: 0; padding: var(--space-2); border-radius: var(--radius-lg);
  background: rgba(255,255,255,0.06); border: 1px solid rgba(255,255,255,0.10);
}
.about-portrait img {
  display: block; width: 100%; height: auto; aspect-ratio: 4 / 5;
  object-fit: cover; object-position: top;
  border-radius: calc(var(--radius-lg) - var(--space-2));
}

/* Вступление: заголовок слева, текст справа — читается как разворот. */
.about-intro {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr);
  gap: var(--space-16); align-items: start;
}
.about-description { font-size: var(--text-base); line-height: 1.6; color: var(--color-text); margin: 0; }

.about-domains { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: var(--space-8); }
.about-domain { display: grid; gap: var(--space-2); align-content: start; }
.about-domain-index { color: var(--red); font-size: var(--text-2xs); letter-spacing: 0.08em; }
.about-domain h3 { margin: 0; font-size: var(--text-lg); color: var(--color-heading); }
.about-domain p { margin: 0; color: var(--color-text-muted); font-size: var(--text-sm); line-height: 1.55; }

/* --- Опыт: одна вертикальная линия времени -------------------------------- */
.timeline { list-style: none; margin: var(--space-12) 0 0; padding: 0; display: grid; gap: 0; }
.timeline-item {
  display: grid; grid-template-columns: 10rem minmax(0, 1fr); gap: var(--space-8);
  padding: var(--space-8) 0; border-top: 1px solid var(--color-border);
}
.timeline-item:last-child { border-bottom: 1px solid var(--color-border); }
.timeline-period {
  font-size: var(--text-2xs); letter-spacing: 0.06em; color: var(--red);
  padding-top: 0.35rem; white-space: nowrap;
}
.timeline-body h3 { margin: 0 0 var(--space-2); font-size: var(--text-lg); color: var(--color-heading); }
.timeline-body p { margin: 0 0 var(--space-4); color: var(--color-text-muted); font-size: var(--text-sm); line-height: 1.55; }

.about-skills { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: var(--space-8); }
.about-skill-group { display: grid; gap: var(--space-3); align-content: start; }

/* --- Документы ------------------------------------------------------------- */
.cert-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap: var(--space-6); }
.cert-card {
  display: grid; gap: var(--space-4); align-content: start;
  padding: var(--space-2); border-radius: var(--radius-lg);
  background: rgba(255,255,255,0.05); border: 1px solid rgba(255,255,255,0.09);
}
.cert-scan {
  display: block; overflow: hidden; border-radius: calc(var(--radius-lg) - var(--space-2));
  background: #0b0c10;
}
.cert-scan img {
  display: block; width: 100%; height: auto; aspect-ratio: 3 / 2;
  /* contain, не cover: документ важнее ровной сетки. Сканы разной формы —
     альбомные, книжные — и обрезка по кадру срезала бы как раз шапку с
     названием курса, ради которой скан и выложен. */
  object-fit: contain; padding: var(--space-2);
  transition: transform var(--dur-base) var(--ease-out);
}
/* Карточка без скана (например, набор модулей одной программы) — верхнего
   отступа ей взять неоткуда, .cert-body рассчитан на соседство с рамкой. */
.cert-card > .cert-body:first-child { padding-top: var(--space-4); }
@media (hover: hover) and (pointer: fine) {
  .cert-scan:hover img { transform: scale(1.03); }
}
.cert-body { display: grid; gap: var(--space-2); padding: 0 var(--space-4) var(--space-4); }
.cert-date { font-size: var(--text-2xs); letter-spacing: 0.06em; color: var(--red); }
.cert-card h3 { margin: 0; font-size: var(--text-base); color: var(--color-heading); line-height: 1.3; }
.cert-issuer, .cert-note { margin: 0; font-size: var(--text-sm); color: var(--color-text-muted); line-height: 1.5; }
.cert-link { font-size: var(--text-sm); text-decoration: none; }
.cert-link:hover { text-decoration: underline; }

.about-footer-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap: var(--space-16);
}
.about-education { list-style: none; margin: var(--space-6) 0 var(--space-8); padding: 0; display: grid; gap: var(--space-3); }
.about-education li {
  padding-left: var(--space-4); border-left: 2px solid var(--red);
  font-size: var(--text-sm); color: var(--color-text); line-height: 1.5;
}

.about-projects { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: var(--space-8); }
.about-project { display: grid; gap: var(--space-2); align-content: start; }
.about-project h3 { margin: 0; font-size: var(--text-base); color: var(--color-heading); }
.about-project p { margin: 0; font-size: var(--text-sm); color: var(--color-text-muted); line-height: 1.55; }

@media (max-width: 900px) {
  .about-hero-grid { grid-template-columns: 1fr; gap: var(--space-8); }
  .about-portrait { max-width: 22rem; }
  .about-intro { grid-template-columns: 1fr; gap: var(--space-6); }
  .timeline-item { grid-template-columns: 1fr; gap: var(--space-3); }
  .about-contacts { gap: var(--space-6); }
}

/* --- Стек текущей должности -------------------------------------------------
   Не сетка одинаковых карточек: у стека есть порядок снизу вверх, и список с
   номерами читается как слои, а плитки — как случайный набор логотипов. */
.stack-head {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
  gap: var(--space-16); align-items: end; margin-bottom: var(--space-12);
}
.stack-layers { list-style: none; margin: 0; padding: 0; display: grid; gap: 0; }
.stack-layer {
  display: grid; grid-template-columns: 3rem minmax(0, 1fr) minmax(0, 0.9fr);
  gap: var(--space-8); align-items: start;
  padding: var(--space-8) 0; border-top: 1px solid var(--color-border);
}
.stack-layer:last-child { border-bottom: 1px solid var(--color-border); }
.stack-index { color: var(--red); font-size: var(--text-2xs); letter-spacing: 0.06em; padding-top: 0.35rem; }
.stack-body h3 { margin: 0 0 var(--space-2); font-size: var(--text-lg); color: var(--color-heading); }
.stack-body p { margin: 0; font-size: var(--text-sm); line-height: 1.55; color: var(--color-text-muted); }
.stack-tools { display: flex; flex-wrap: wrap; gap: var(--space-2); padding-top: 0.2rem; }
/* Инструменты — моноширинные: это имена из конфигов, а не проза. */
.chip-tool { font-family: var(--font-mono); font-size: var(--text-2xs); letter-spacing: 0.01em; }

@media (max-width: 900px) {
  .stack-head { grid-template-columns: 1fr; gap: var(--space-6); align-items: start; }
  .stack-layer { grid-template-columns: 2.5rem minmax(0, 1fr); gap: var(--space-4); }
  .stack-tools { grid-column: 2; padding-top: var(--space-3); }
}

/* Подпись места работы под заголовком стека: организация — факт, а не
   заголовок, поэтому спокойным кеглем, с выделенным названием компании. */
.stack-role {
  margin: var(--space-4) 0 0; font-size: var(--text-sm); line-height: 1.5;
  color: var(--color-text-muted);
}
.stack-role strong { display: block; color: var(--color-heading); font-weight: 600; }
/* --- Тёмная тема -----------------------------------------------------------
   Включается атрибутом data-theme="dark" на <html>: его ставит скрипт в <head>
   по настройке устройства или по явному выбору кнопкой в шапке. Стоит в конце файла
   и с селектором html:root, чтобы перебить светлую палитру из блока «Taste pass».
   Светлые полосы главной (.tone-light, .landing-surface, .service-chapter) в
   тёмной теме тоже темнеют: иначе выбравший тёмную видел бы белые экраны. */
html:root[data-theme="dark"],
html[data-theme="dark"] .tone-light,
html[data-theme="dark"] .landing-surface,
html[data-theme="dark"] .service-chapter {
  --color-bg: #0b0c0f;
  --color-surface: #15171c;
  --color-surface-muted: #1c1f25;
  --color-border: #2c3038;
  --color-border-accent: rgba(248,113,113,0.4);
  --color-heading: #f3f4f6;
  --color-text: #d4d6db;
  --color-text-muted: #8f949d;
  --color-inverse-bg: #181a20;
  --color-inverse-text: #f3f4f6;
  --color-accent: #f05252;
  --color-accent-hover: #f87171;
  --shadow-card: 0 2px 12px rgba(0,0,0,0.5);
  --shadow-card-hover: 0 18px 40px rgba(0,0,0,0.6);
  --bg: var(--color-bg);
  --card: var(--color-surface);
  --card-alt: var(--color-surface-muted);
  --border: var(--color-border);
  --border-red: var(--color-border-accent);
  --red: var(--color-accent);
  --red-dark: var(--color-accent-hover);
  --text: var(--color-text);
  --text-dim: var(--color-text-muted);
  --heading: var(--color-heading);
  --black: var(--color-inverse-bg);
  --white: var(--color-inverse-text);
  color-scheme: dark;
}
html[data-theme="dark"] body { background: var(--bg); color: var(--text); }
html[data-theme="dark"] .tone-light,
html[data-theme="dark"] .service-chapter { background: var(--color-bg); color: var(--color-text); }
html[data-theme="dark"] .landing-surface {
  background: radial-gradient(70% 70% at 88% 12%, rgba(240,82,82,0.08), transparent 62%), var(--color-bg);
}
html[data-theme="dark"] .service-chapter { border-top-color: var(--border); }
html[data-theme="dark"] .card { border-color: var(--border); }
html[data-theme="dark"] .login-page .card { background: var(--card); }

/* Обучение: ссылка на видеосвязь */
.training-meet { margin: 1rem 0 0; font-size: 0.9rem; line-height: 1.6; }
.training-meet a { color: var(--red); font-weight: 600; }
.training-next { font-size: 0.85rem; margin: 0.75rem 0 0; }
