/* ============================================================
   ЖК «ЗЭТА» — дизайн-система (тикет 05: адаптированный Bugatti;
   тикет 09: светлая палитра — см. spec.md «Поправка после сдачи
   (G14) — светлая палитра»). Форма и типографика тикета 05 (три
   шрифтовые роли, верхний регистр с трекингом, 0px-радиус кроме
   кнопок-пилюль) не изменились — тикет 09 развернул только цвет:
   белый/почти белый фон вместо тёмного графита/антрацита, графит/
   тёмный — теперь цвет текста, а не фон всего сайта. Золото — тот
   же редкий акцент (цена/CTA/активная вкладка/фокус), контраст
   пересчитан заново на светлом фоне (не унаследован от тёмной
   версии вслепую).

   Header/hero/мобильное меню/подвал остаются тёмными «зонами
   чтения» (фиксированная шапка поверх фото hero, сам hero, подвал)
   — для них сохранены отдельные «-on-dark» токены с прежними
   светлыми на тёмном значениями; все остальные разделы страницы —
   светлый фон с тёмным текстом.
   ============================================================ */

/* ---- Шрифты (Google Fonts, кириллица, font-display:swap) ----
   Две роли (тикет 49: EB Garamond/--font-serif удалён с сайта
   полностью): рубленый Oswald в верхнем регистре для заголовков
   разделов и крупных цифр, моноширинный JetBrains Mono для всего
   остального — кнопок/навигации/лейблов и основного текста.

   Решение по заголовочному шрифту (не тихая замена, фиксирую явно):
   в тикете и spec.md как аналог Bugatti Display назван Saira
   Condensed — проверка показала, что у Saira (в любом начертании:
   Condensed/SemiCondensed/обычная) на Google Fonts нет кириллицы
   вообще, только latin/latin-ext/vietnamese. Легального альтернативного
   файла с кириллицей для Saira нет. Заменено на Oswald — тоже
   рубленый уплотнённый шрифт того же визуального регистра (используется
   в премиум-автомобильной/индустриальной айдентике), с полной
   кириллицей на Google Fonts. Это решение, аналогичное найденному в
   тикете 01 для Forum — если нужен точнее Saira/Bugatti Display,
   нужен легальный файл шрифта с кириллицей от пользователя. */
@import url('https://fonts.googleapis.com/css2?family=Prata&family=Manrope:wght@400;500;700&family=JetBrains+Mono:wght@400;500&display=swap');

:root{
  /* палитра — светлая база (тикет 09) + редкое золото.
     --emerald/--turquoise из старой палитры (тикет 01) в этой системе
     не участвуют — не возвращались. */
  --dark:#1a1a1a;         /* текст на светлом фоне; фон тёмных зон (шапка/hero/подвал/моб.меню) */
  --graphite:#2a3d3d;     /* вторичный тёмный тон, зарезервирован, сейчас нигде не используется */
  --bg:#ffffff;           /* основной фон страницы и большинства секций */
  --bg-alt:#f4f1ea;       /* лёгкий тёплый тон для ритма чередования секций (замена .section-dark/.section-deep) */
  --gold:#83672c;         /* акцент на светлом фоне — цена/CTA/активная вкладка/фокус; ≥4.5:1 на --bg и --bg-alt */
  --gold-on-dark:#c9a96e; /* тот же акцент, но в тёмных зонах (шапка/hero/моб.меню/подвал) — прежнее значение, там уже держит контраст */
  --logo-gold:#c4a03c;    /* тикет 29: отдельный оттенок только для логотипа и полосок гамбургера (в паре с ним), не влияет на --gold */
  --cream-text:#e8dfc6;   /* текст в тёмных зонах (шапка/hero/моб.меню/подвал) — прежнее значение */
  --muted:rgba(26,26,26,.66);
  --hairline:rgba(26,26,26,.16);
  --hairline-strong:rgba(26,26,26,.3);
  /* обводка интерактивных элементов (pill-кнопки, вкладки) на светлом фоне —
     непрозрачность держит контраст >=3:1 (WCAG 1.4.11) на --bg и --bg-alt. */
  --hairline-interactive:rgba(26,26,26,.5);
  /* те же роли, но для тёмных зон (шапка/hero/моб.меню/подвал) — прежние
     светлые-на-тёмном значения, не трогались. */
  --hairline-on-dark:rgba(232,223,198,.16);
  --hairline-on-dark-strong:rgba(232,223,198,.3);
  --hairline-on-dark-interactive:rgba(232,223,198,.5);
  --danger:#b3261e; /* пересчитан для контраста на светлом фоне (было #f0a597 — держал контраст только на тёмном) */

  /* типографика — см. комментарий у @import про замену Saira → Oswald */
  --font-display:'Oswald', 'Arial Narrow', Impact, sans-serif;
  --font-body:'Manrope', 'Helvetica Neue', Arial, sans-serif;
  --font-mono:'JetBrains Mono', 'Courier New', Courier, monospace;

  --header-h:76px;
}

*, *::before, *::after{ box-sizing:border-box; }
html{
  scroll-behavior:smooth;
  scroll-padding-top:calc(var(--header-h) + 12px);
  /* Найдено при проверке тикета 16 на 375px, не тикет 16 внёс: у
     #planirovki (не в зоне этого тикета — «не трогай остальные 14
     разделов») есть контент шире 375px, который расширяет весь layout
     viewport на мобильном. overflow-x:hidden на body (было раньше) не
     ограничивает position:fixed-элементы (.site-header/.mobile-menu) —
     они позиционируются относительно viewport, а не body, и «утекали»
     за реальный край экрана вместе с #menuToggle. Добавлено сюда (не
     только на body) — так фикс работает и для fixed-позиционирования. */
  overflow-x:clip; /* clip, не hidden: hidden создаёт scroll-контейнер и ломает Lenis */
}
body{
  margin:0;
  background:var(--bg);
  color:var(--dark);
  font-family:var(--font-body);
  line-height:1.65;
  -webkit-font-smoothing:antialiased;
  overflow-x:clip; /* страховка от горизонтальной прокрутки; clip совместим с Lenis */
}
img, video{ max-width:100%; display:block; }
a{ color:inherit; text-decoration:none; }
button{ font-family:inherit; }
h1,h2,h3{
  font-family:var(--font-display); font-weight:400; color:var(--dark);
  text-transform:uppercase; letter-spacing:.05em; line-height:1.15; margin:0;
}

.wrap{ max-width:1240px; margin:0 auto; padding:0 24px; }
@media (max-width:600px){ .wrap{ padding:0 18px; } }

/* Отступы между блоками увеличены (ориентир 96–120px, см. spec.md) */
.section{ padding:clamp(72px,10vw,120px) 0; background:var(--bg); }
.section-dark{ background:var(--bg-alt); }
.section-card{ background:var(--bg); border-top:1px solid var(--hairline); border-bottom:1px solid var(--hairline); }

.eyebrow{
  display:block;
  font-family:var(--font-mono);
  font-size:12.5px;
  font-weight:400;
  letter-spacing:.14em;
  text-transform:uppercase;
  color:rgba(26,26,26,.72);
  margin:0 0 14px;
}
/* hero — единственное место, где .eyebrow сидит на тёмном фоне (фото + scrim) */
.hero .eyebrow{ color:rgba(255,255,255,.8); }

.section-title{
  font-family:var(--font-display);
  font-weight:400;
  text-transform:uppercase;
  letter-spacing:.07em;
  font-size:clamp(26px,3.2vw,40px);
  line-height:1.2;
  margin:0 0 16px;
}
.lead{ color:var(--muted); font-size:17px; max-width:60ch; margin:0; }

.btn{
  display:inline-flex; align-items:center; justify-content:center; gap:8px;
  padding:14px 30px; border-radius:9999px; border:1px solid currentColor;
  font-family:var(--font-mono); font-weight:400; font-size:13px;
  letter-spacing:.12em; text-transform:uppercase; cursor:pointer; white-space:nowrap;
  background:transparent;
  transition:transform .15s ease, background .2s ease, color .2s ease, border-color .2s ease;
}
.btn:active{ transform:scale(.97); }
.btn:focus-visible{ outline:2px solid var(--gold); outline-offset:2px; }
.btn-primary{ border-color:var(--gold); color:var(--gold); }
.btn-primary:hover{ background:rgba(131,103,44,.1); }
.btn-ghost{ border-color:var(--hairline-interactive); color:var(--dark); background:transparent; }
.btn-ghost:hover{ background:rgba(26,26,26,.06); border-color:var(--dark); }

/* Тикет 73 (G88): «жидкий металл» — канвас с WebGL-кольцом/заливкой,
   создаётся metal-fx.js (см. этот файл — документирующий комментарий в
   шапке). Только позиционирование канваса внутри существующих
   элементов — сама разметка кнопок/лого/гамбургера не менялась.
   `.metal-fx-canvas` — replaced-элемент: inset:-3px САМО ПО СЕБЕ не
   растягивает канвас на размер родителя, если у канваса заданы атрибуты
   width/height (свой intrinsic-размер побеждает) — обязательно нужен
   ЕЩЁ явный width/height:calc(...) рядом с inset (см. metal-fx.js). */
.metal-fx-canvas{
  position:absolute; inset:-3px; z-index:0; pointer-events:none;
  width:calc(100% + 6px); height:calc(100% + 6px);
}
.btn{ position:relative; isolation:isolate; }
/* Тикет 75 (G92): .logo-link остаётся position:relative — больше не для
   кольца вокруг лого (того эффекта больше нет), а как offsetParent для
   .metal-fx-canvas--logo, который metal-fx.js позиционирует через
   inline left/top/width/height относительно .logo-img (см. ниже). */
.logo-link{ position:relative; }
/* Гамбургер: канвас перекрывает ровно 40×40 кнопки (не кольцо вокруг
   края, а полная заливка внутренней области двумя полосками) — без
   отступа -3px базового правила выше. */
.menu-toggle .metal-fx-canvas{ inset:0; width:100%; height:100%; }
/* Тикет 75 (G92): лого — своя геометрия канваса, ЛОГО-канвас не кольцо
   вокруг элемента, а заливка формы самого <img> по alpha-маске.
   metal-fx.js уже выставляет left/top/width/height инлайново через
   canvas.style (см. initLogoLiquid()) — здесь только позиционирование,
   без inset/width:calc(...) базового `.metal-fx-canvas` (та геометрия
   тут не подходит). */
.metal-fx-canvas--logo{ position:absolute; z-index:0; pointer-events:none; }

/* Шапка/hero/мобильное меню — тёмные зоны (см. блоки ниже): те же кнопки
   там сидят на тёмном фоне, им нужен «-on-dark» вариант золота и, для
   ghost-кнопки в hero, «-on-dark» обводка/текст — переопределено в
   соответствующих блоках, а не здесь, чтобы не плодить исключения в
   базовом правиле .btn. */
.hero .btn-primary{
  border-color:var(--gold-on-dark); color:var(--gold-on-dark);
}
/* Тикет 21 (G31): собственная подложка кнопки (тикет 20) убрана — кнопка
   теперь получает контраст от единой постоянной подложки .site-header
   (см. блок ШАПКА ниже), как и весь остальной контент шапки. Отдельная
   заливка здесь снова превратила бы кнопку в «отличается от других»
   элемент — ровно то, что пользователь отвергла дважды. */
.hero .btn-primary:hover{
  background:var(--gold-on-dark); color:var(--dark);
}
/* Тикет 32 (G42): .mobile-menu .btn-primary больше не переопределяется
   здесь — светлое меню (см. блок ниже) наследует базовое .btn-primary/
   :hover (строки ~144-145), уже рассчитанное на светлый фон. */
/* Тикет 26 (G36): отдельное правило .site-header .btn-primary (тикет 25,
   держало цвет кнопки через --hdr-accent, когда у шапки было два
   состояния — прозрачное/белое) удалено — кнопка «Оставить заявку»
   больше не стоит в самой шапке, она переехала целиком в #mobileMenu
   (см. блок ШАПКА/НАВИГАЦИЯ ниже), который уже покрыт селектором
   .mobile-menu .btn-primary выше. --hdr-* переменных в проекте больше
   нет — развилка вместе с ними. */
.hero .btn-ghost{ border-color:var(--hairline-on-dark-interactive); color:var(--cream-text); }
.hero .btn-ghost:hover{ background:rgba(232,223,198,.08); border-color:var(--cream-text); }
/* Тикет 33 (G43): базовый .btn:focus-visible использует --gold (тёмный,
   рассчитан на светлый фон) — на тёмном фото hero недостаточно
   контрастен, как и .hero .btn-primary уже использует --gold-on-dark
   вместо --gold по той же причине. */
.hero .btn:focus-visible{ outline-color:var(--gold-on-dark); }

@media (prefers-reduced-motion: reduce){
  html{ scroll-behavior:auto; }
  *{ animation-duration:.01ms !important; animation-iteration-count:1 !important; transition-duration:.01ms !important; }
}

/* ---- утилита «проявления» при скролле (см. reveal.js) ----
   Подключение: добавить класс .reveal любому элементу — reveal.js
   сам поставит его в наблюдение. Задержку внутри группы можно
   выставить через data-reveal-index="0..n" (шаг 130ms, см. reveal.js).
   Тикет 11 (G20): амплитуда усилена — было translateY(24px) без
   масштаба, почти незаметно на реальном экране; теперь 56px сдвига
   + лёгкий scale, чтобы каждый раздел ощутимо «собирался» при
   подскролле. Механизм (IntersectionObserver/prefers-reduced-motion
   в reveal.js) не тронут — только эти визуальные константы. */
.reveal{
  opacity:0; transform:translateY(56px) scale(.96);
  transition:opacity .7s cubic-bezier(.16,.84,.44,1), transform .7s cubic-bezier(.16,.84,.44,1);
}
.reveal.is-visible{ opacity:1; transform:none; }

/* ---- индикатор прогресса прокрутки ---- */
.scroll-progress{
  position:fixed; top:0; left:0; height:3px; width:0%;
  background:var(--dark);
  z-index:1001; pointer-events:none;
}

/* ============ ШАПКА / НАВИГАЦИЯ ============
   Тикет 26 (G36): пересмотр по прямому слову пользователя — «шапка
   минимальная, белая, position:fixed, только лого + кнопка меню, не
   бывает тёмной ни в каком состоянии скролла». Это осознанно отменяет
   часть решений тикетов 15-25 (см. .autopilot/.../interfaces.md,
   раздел «Тикет 26» — не пересказ, там дословный контекст):
   — .main-nav (постоянная строка 7 категорий, тикет 16) и .nav-actions
     шапки (телефон/ВК/CTA, тикеты 16-18) убраны из .site-header целиком
     на любой ширине — раньше появлялись только на ≥1220px, весь этот
     контент (кроме кнопки меню) теперь живёт исключительно в
     #mobileMenu (см. index.html), где заодно оказалась иконка ВК —
     раньше она была только в постоянной шапке.
   — Тикеты 19-23 держали шапку прозрачной/полупрозрачной над фото hero
     и решали контраст текста над фото (text-shadow/filter/::after-слой
     затемнения/IntersectionObserver в nav.js по контенту hero) — раз
     шапка теперь ВСЕГДА непрозрачно-белая (background-color:var(--bg)
     с первого кадра, до любого скролла), эта задача перестаёт
     существовать: шапка физически перекрывает то, что под ней, нечему
     просвечивать. .site-header::after (тикет 22) и вся его логика в
     nav.js (тикет 23) удалены как мёртвый код, а не оставлены «на
     всякий случай» — держать код без назначения хуже, чем убрать его
     и восстановить, если понадобится снова.
   — --hdr-* переменные (тикет 25) держали переключение тёмный/светлый
     между двумя состояниями шапки — раз второго (тёмного) состояния
     больше нет, сама развилка убрана: элементы шапки читают токены
     напрямую (--dark/--gold), как остальные светлые секции сайта
     (тикет 09).
   .is-scrolled оставлен — не про цвет (был и до всей этой истории,
   тикет 01/04): уменьшает высоту шапки и добавляет тень при скролле,
   полезно само по себе, простое переключение по порогу (см. nav.js). */
.site-header{
  position:fixed; top:0; left:0; right:0; z-index:1000;
  height:var(--header-h);
  display:flex; align-items:center;
  background-color:var(--bg);
  transition:box-shadow .3s ease, height .3s ease;
}
.site-header.is-scrolled{
  box-shadow:0 4px 20px rgba(0,0,0,.18);
  height:64px;
}
.nav-inner{
  width:100%; max-width:1240px; margin:0 auto; padding:0 24px;
  display:flex; align-items:center; justify-content:space-between; gap:20px;
}
.logo-link{ display:flex; align-items:center; gap:10px; flex:0 0 auto; }
.logo-img{
  /* Тикет 26: сам логотип не редизайнился — уже золотой, уже читаем на
     белом (проверено тикетом 25/09). Жалоба «плохо смотрится лого»
     решается теснотой вокруг него (минимальная шапка, п.1 тикета), не
     переделкой знака. Размер/clamp не менялись с тикета 20. */
  height:clamp(52px, 6.4vw, 74px); width:auto; display:block;
  transform-origin:left center;
  transition:transform .3s ease;
}
.site-header.is-scrolled .logo-img{ transform:scale(.846); }

/* Тикет 15 (G25): гамбургер — 2 полоски вместо 3 (референс D&G Velvet
   Collection), обе абсолютно спозиционированы вокруг центра кнопки, чтобы
   схлопывание в крест при aria-expanded="true" было симметричным.
   Тикет 26 (G36): единственный интерактивный элемент постоянной шапки
   теперь (раньше был последним из .nav-actions, среди телефона/ВК/CTA).
   Цвет — прямой токен, не --hdr-accent: шапка больше не бывает тёмной,
   второго состояния не нужно (проверено на >=4.5:1 на --bg, тикет 09).
   Тикет 29: используется --logo-gold (в паре с логотипом), не --gold —
   отдельный, чуть более золотой оттенок только для этой пары элементов. */
.menu-toggle{
  position:relative;
  display:inline-flex; align-items:center; justify-content:center;
  width:40px; height:40px; padding:0; border:none; background:transparent; cursor:pointer;
}
.menu-toggle span{
  position:absolute; width:22px; height:2px; background:var(--logo-gold);
  transition:transform .25s ease;
}
.menu-toggle span:nth-child(1){ transform:translateY(-4px); }
.menu-toggle span:nth-child(2){ transform:translateY(4px); }
.menu-toggle[aria-expanded="true"] span:nth-child(1){ transform:translateY(0) rotate(45deg); }
.menu-toggle[aria-expanded="true"] span:nth-child(2){ transform:translateY(0) rotate(-45deg); }
#menuToggle:focus-visible{ outline:2px solid var(--gold); outline-offset:2px; }

/* Тикет 15 (G25): было — панель на весь экран, теперь узкий бокс с
   золотой hairline-рамкой, примыкающий к кнопке, которая его открывает.
   Позиционирование — не константа: правый край #menuToggle всегда
   совпадает с правым краем контента `.nav-inner` (flex
   justify-content:space-between, .menu-toggle — крайний правый элемент
   без своего margin теперь, когда .nav-right/.main-nav/.nav-actions
   шапки убраны тикетом 26), поэтому вместо константы считаем тот же
   отступ, что и у `.nav-inner`: половина остатка от max-width:1240px
   (0, если вьюпорт уже 1240px) плюс их padding 24px. Если
   `.nav-inner`/`.wrap` когда-нибудь поменяют max-width/padding —
   формулу нужно поправить вручную, автоматической синхронизации нет.
   Тикет 26 (G36): бокс больше не скрывается на широких экранах (было
   — @media (min-width:1220px){ display:none }, тикет 17, пока
   дублировал постоянную .main-nav) — теперь это ЕДИНСТВЕННОЕ место
   с полным списком разделов на любой ширине, поэтому видим и открываем
   его всегда, весь nav.js/aria-контракт (Esc/клик/фокус) не менялся. */
/* Тикет 74 (G90): стеклянный фон по образцу .calc (тикет 72) — тот же
   приём blur+saturate поверх полупрозрачного --bg-alt, с фолбэком для
   браузеров без backdrop-filter ниже. */
.mobile-menu{
  position:fixed; top:var(--header-h); z-index:999;
  right:calc(max(0px, (100vw - 1240px) / 2) + 24px);
  width:min(320px, calc(100vw - 32px));
  max-height:min(600px, calc(100vh - var(--header-h) - 24px));
  background:rgba(244,241,234,.65);
  -webkit-backdrop-filter:blur(20px) saturate(140%);
  backdrop-filter:blur(20px) saturate(140%);
  border:1px solid rgba(26,26,26,.08);
  border-radius:18px;
  box-shadow:0 12px 32px rgba(26,26,26,.16);
  overflow-y:auto;
  transform:translateY(-8px); opacity:0; visibility:hidden;
  transition:opacity .25s ease, transform .25s ease, visibility 0s linear .25s;
}
@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  .mobile-menu{ background:var(--bg-alt); }
}
.mobile-menu.is-open{
  opacity:1; transform:none; visibility:visible;
  transition:opacity .25s ease, transform .25s ease;
}
.mobile-menu ul{ list-style:none; margin:0; padding:14px 18px 4px; display:flex; flex-direction:column; }
.mobile-menu ul a{
  display:block; padding:11px 2px; font-family:var(--font-mono); font-size:13px;
  letter-spacing:.03em; text-transform:uppercase;
  color:var(--dark);
}
.mobile-menu ul a:focus-visible{ outline:2px solid var(--gold); outline-offset:-2px; }
.nav-actions{ display:flex; align-items:center; gap:16px; flex:0 0 auto; }
.mobile-menu .nav-actions{
  flex-direction:column; align-items:stretch; gap:12px;
  padding:18px; margin-top:4px;
}
.mobile-menu .nav-actions .btn{ width:100%; }
.nav-phone{
  font-family:var(--font-mono); font-size:14px; letter-spacing:.04em;
  color:var(--dark); white-space:nowrap;
}
.mobile-menu .nav-phone{ display:block; text-align:center; }

/* Тикет 17 (G27) → 26 (G36): иконка ВК переехала из постоянной шапки
   (убрана вместе с остальным .nav-actions шапки, см. блок выше) в
   #mobileMenu — она нигде не потерялась, просто сменила место. Тикет 32
   (G42): #mobileMenu переведён на светлую палитру (см. блок ниже), токены
   здесь пересчитаны на светлый фон — --hairline-interactive/--gold, а не
   через --hdr-* — той развилки между тёмным/светлым состоянием шапки нет
   (см. блок выше). */
.social-icon{
  display:inline-flex; align-items:center; justify-content:center;
  width:32px; height:32px; border-radius:50%; flex:0 0 auto;
  border:1px solid var(--hairline-interactive);
  font-family:var(--font-mono); font-size:11px; font-weight:700; letter-spacing:.02em;
  color:var(--gold); text-decoration:none;
  transition:border-color .2s ease, color .2s ease;
}
.social-icon:hover, .social-icon:focus-visible{
  border-color:var(--gold); color:var(--dark);
}
/* Тикет 33, Фикс 2: как и у #menuToggle, без явного outline браузер рисует
   свой дефолтный focus-ring (синий/оранжевый квадрат) поверх — hover не
   должен получить outline, поэтому отдельное правило, а не в общем блоке
   выше. */
.social-icon:focus-visible{
  outline:2px solid var(--gold); outline-offset:2px;
}
.mobile-menu .social-icon{ margin:0 auto; }

body.menu-open{ overflow:hidden; }

/* ============ HERO ============
   Остаётся тёмным по смыслу (фото + затемняющий scrim для читаемости
   заголовка) — так и на светлой базе, см. тикет 09/референс. */
.hero{
  position:relative; overflow:hidden;
  min-height:100svh; min-height:100vh;
  display:flex; align-items:flex-end;
  background:var(--dark); color:#fff;
  padding-top:var(--header-h);
}
.hero-media{
  position:absolute; inset:0; z-index:0;
  /* Тикет 13: aspect-ratio:16/9 убран — конфликтовал с inset:0 внутри
     .hero (min-height:100vh) и на вьюпортах не 16:9 (напр. 1440×900)
     давал контейнеру высоту меньше самой секции, из-за чего фото не
     докрывало низ hero независимо от scale/параллакса (баг был и при
     видео, просто не проявлялся на 1920×1080, где 16:9 совпадает с
     соотношением экрана). Резерв места не нужен — высота уже задаётся
     самой .hero. */
}
/* Статичное фото (тикет 13, G23) — вернулись с видео на фото
   (hero_terrace_hires.jpg, 2400×1792, та же сцена терраса/пара/закат/
   город, что была в видео, сжата под веб из исходника 4800×3584).
   video-специфичная логика (poster, autoplay/loop, мобильный фолбэк
   по ширине) больше не нужна — один <img> на всех экранах.
   Тикет 14 (G24): transform:scale(1.03) убран — пользователь увидела
   приближённый/обрезанный кадр и попросила показать фото как оно есть.
   object-fit:cover остаётся: он только вписывает фото в бокс по
   пропорциям (может кадрировать по краям при несовпадении aspect-ratio
   фото и .hero), но не увеличивает сам контент. Вертикальный
   сдвиг-параллакс при скролле, который раньше двигался в этом буфере,
   тоже снят в reveal.js (см. комментарий там) — без scale держать его
   безопасным на всех проверяемых ширинах было нечем. */
.hero-photo{
  position:absolute; inset:0; width:100%; height:100%;
  object-fit:cover;
}
/* Тикет 66 (G79): медленный непрерывный Ken Burns-зум по времени,
   не связанный со скроллом — «как будто движемся внутри террасы».
   Не повторяет отменённое тикетом 14 решение: анимация стартует ровно
   со scale(1) (кадр в момент загрузки идентичен нынешнему, ничего не
   обрезано в состоянии покоя), amplitude не опускается ниже 1 ни в
   одной фазе — object-fit:cover при scale>=1 продолжает полностью
   закрывать .hero-media (inset:0), поэтому оголения фона .hero по
   краю (причина отказа от скролл-параллакса) здесь не может быть.
   ease-in-out/alternate/infinite на 26s — кинематографично медленно,
   не «пульс». Обёрнуто в prefers-reduced-motion, как hover-zoom тикета
   64 выше. */
@media (prefers-reduced-motion: no-preference){
  .hero-photo{
    animation:hero-ken-burns 26s ease-in-out infinite alternate;
  }
  @keyframes hero-ken-burns{
    from{ transform:scale(1); }
    to{ transform:scale(1.08); }
  }
}
.hero-scrim{
  position:absolute; inset:0; z-index:1;
  /* Тикет 19 (G29): верхняя часть градиента (0%→32%) ослаблена почти до
     нуля — в состоянии покоя (без скролла) она темнила верх фото террасы
     ровно там, где вид на город/архитектуру, а .site-header прозрачна и
     весь этот верх виден без прокрутки. Легибельность навигации теперь
     держит text-shadow на самих элементах (.nav-phone/.main-nav a/
     .logo-word/.social-icon ниже), не затемнение фона. Нижняя часть
     (60%→100%, под заголовком/CTA/статистикой) не тронута — там
     легибельность уже нужна и работает, .site-header.is-scrolled после
     40px скролла тоже не задет этим тикетом. */
  background:linear-gradient(180deg, rgba(26,26,26,.06) 0%, rgba(26,26,26,.04) 32%, rgba(26,26,26,.25) 60%, rgba(26,26,26,.85) 100%);
  pointer-events:none;
}
.hero-inner{ position:relative; z-index:2; width:100%; padding-bottom:clamp(40px,6vw,72px); }
.hero h1{
  color:#fff; font-size:clamp(32px,5vw,56px);
  margin:0 0 18px; max-width:18ch;
  text-shadow:0 2px 14px rgba(0,0,0,.4);
}
/* Тикет 15 (G25): переливающийся золотой текст — переиспользуемый класс,
   не привязан к hero. Оттенки — только существующие токены --gold-on-dark
   и --cream-text (тот же дуэт, что уже держит текст/подписи в тёмных
   зонах), новая палитра не вводится. text-shadow наследуется от
   родителя (h1) даже при color:transparent — легибельность поверх фото
   не теряется. Глобальное reduced-motion-правило выше (animation-duration:
   .01ms !important) уже гасит анимацию, но требование тикета — явный
   статичный градиент без анимации, поэтому дублируем адресно. */
.text-shimmer{
  background:linear-gradient(100deg, var(--gold-on-dark) 30%, var(--cream-text) 50%, var(--gold-on-dark) 70%);
  background-size:250% auto;
  -webkit-background-clip:text; background-clip:text; color:transparent;
  animation:zeta-text-shimmer 5s linear infinite;
}
@keyframes zeta-text-shimmer{
  0%{ background-position:0% 50%; }
  100%{ background-position:-250% 50%; }
}
@media (prefers-reduced-motion: reduce){
  .text-shimmer{ animation:none; background-position:0 0; }
}

.hero-ctas{ display:flex; gap:14px; flex-wrap:wrap; margin-bottom:clamp(36px,5vw,56px); }

/* Тикет 15 (G25): было — 4 сплошные тёмные карточки с blur-подложкой и
   толстой (30%-альфа) рамкой вокруг всего блока — визуально тяжело для
   референса «минимализм люкс-премиум». Сами 4 факта — контент другого
   требования, не трогается; облегчена только подача: без заливки/blur,
   тонкая верхняя линия + тонкие вертикальные hairline-разделители. */
.hero-stats{
  display:grid; grid-template-columns:repeat(4,1fr);
  border-top:1px solid var(--hairline-on-dark); padding-top:18px;
}
.hero-stat{ padding:0 18px; border-left:1px solid var(--hairline-on-dark); }
.hero-stat:first-child{ border-left:none; }
.hero-stat .num{ font-family:var(--font-display); font-weight:400; font-size:22px; letter-spacing:.04em; color:var(--cream-text); }
.hero-stat .cap{ font-family:var(--font-mono); font-size:11.5px; letter-spacing:.06em; text-transform:uppercase; color:rgba(255,255,255,.68); margin-top:6px; }
@media (max-width:760px){
  .hero-stats{ grid-template-columns:repeat(2,1fr); row-gap:16px; }
  .hero-stat:nth-child(3), .hero-stat:nth-child(4){ border-top:1px solid var(--hairline-on-dark); padding-top:16px; }
  .hero-stat:nth-child(3){ border-left:none; }
}

/* ============ ПУСТОЙ КАРКАС 14 РАЗДЕЛОВ ============
   Заполняется тикетом 02 — здесь только структура и заголовок. */
.section-head{ max-width:680px; margin-bottom:clamp(32px,4vw,48px); }
.section-body-placeholder{ display:none; } /* якорь для будущего наполнения, ничего не выводит */

/* ============ ЗАЯВКА (пустой каркас, наполняет тикет 03) ============ */
#zayavka .section-head{ max-width:640px; }

/* ============ ПОДВАЛ ============
   Вторая (и последняя) деликатно тёмная зона сайта — те же
   «-on-dark»/--cream-text токены, что и в шапке. */
footer{ background:var(--dark); color:rgba(232,223,198,.62); padding:52px 0 26px; font-size:14px; border-top:1px solid var(--hairline-on-dark); }
.foot-top{
  display:flex; flex-wrap:wrap; justify-content:space-between; gap:28px;
  padding-bottom:28px; border-bottom:1px solid var(--hairline-on-dark);
}
.foot-brand{ font-family:var(--font-display); font-weight:400; font-size:22px; text-transform:uppercase; letter-spacing:.06em; color:var(--cream-text); }
.foot-brand-cap{ display:block; font-family:var(--font-mono); font-weight:400; font-size:11px; letter-spacing:.1em; text-transform:uppercase; color:rgba(232,223,198,.5); margin-top:4px; }
.foot-contact{ line-height:1.9; }
.foot-contact a{ color:rgba(232,223,198,.85); font-weight:500; }
.foot-nav{ display:flex; gap:10px 22px; flex-wrap:wrap; list-style:none; margin:0; padding:0; }
.foot-nav a{ font-family:var(--font-mono); font-size:12.5px; letter-spacing:.04em; text-transform:uppercase; color:rgba(232,223,198,.7); }
.foot-nav a:hover{ color:var(--gold-on-dark); }
.foot-legal{ font-size:12px; line-height:1.6; color:rgba(232,223,198,.4); margin:22px 0 0; max-width:860px; }
.foot-bottom{ display:flex; flex-wrap:wrap; justify-content:space-between; gap:10px; padding-top:18px; font-size:12px; color:rgba(232,223,198,.35); }
.foot-bottom a{ color:inherit; }

/* ============================================================
   Наполнение 14 разделов (тикет 02) — общие компоненты разметки
   ============================================================ */

/* ---- общие текстовые/медиа блоки ---- */
.section-note{ font-size:13.5px; color:var(--muted); margin:16px 0 0; max-width:64ch; }
figcaption{ font-size:13px; color:var(--muted); padding-top:10px; }

/* ---- Архитектура (тикет 39, заменяет стек тикета 38): full-bleed
   карусель фото фасада, край-в-край, вне .wrap — .arch-section сам не
   даёт горизонтальных отступов (как и .section), поэтому .arch-carousel
   занимает всю ширину вьюпорта. Один слайд видно за раз (абсолютное
   позиционирование внутри .arch-carousel-track, .is-active — opacity:1,
   остальные — 0), переключение стрелками — см. arch-carousel.js.
   Высота — clamp, не 100svh: полный экран на мобильных выглядел
   непропорционально (фото уходит далеко за первый экран), а clamp даёт
   «полноэкранный» вид без утраты соседнего контента из виду. Плавный
   переход между слайдами уважает prefers-reduced-motion через общее
   правило `*{transition-duration:.01ms!important}` (см. выше в файле) —
   отдельная переопределяющая медиа-выборка не нужна. ---- */
.arch-section{ padding-bottom:0; }
.arch-carousel{
  position:relative; width:100%;
  margin-top:clamp(32px,4vw,48px);
}
/* Тикет 47: фикс-высота/overflow фото-зоны переехали с .arch-carousel на
   .arch-carousel-track (у которой и так был свой position:relative, за
   счёт чего .arch-slide{position:absolute;inset:0} и раньше позиционировался
   именно относительно неё, а не .arch-carousel — переезд не меняет вид
   фото), чтобы .arch-carousel мог вместить под фото ещё и .arch-controls,
   не обрезая и не сжимая её. */
.arch-carousel-track{
  position:relative; width:100%; overflow:hidden;
  height:clamp(480px,85vw,900px);
}
.arch-slide{ position:absolute; inset:0; margin:0; opacity:0; transition:opacity .4s ease; }
.arch-slide.is-active{ opacity:1; }
.arch-photo{ width:100%; height:100%; object-fit:cover; display:block; }

/* Тикет 47 (G57): стрелки были полупрозрачным тёмным кругом поверх фото —
   плохо видно на светлых/контрастных кадрах, легко не заметить, что фото
   вообще листается. Теперь — отдельная полоса под фото, фон сцены здесь
   уже не фото, а страница, поэтому обычные светлые токены сайта
   (--gold/--hairline-interactive), как у соседних круглых кнопок
   (.gallery/.lightbox использует свою тёмную палитру намеренно — не тот
   случай). */
.arch-controls{
  display:flex; justify-content:center; align-items:center; gap:16px;
  padding:18px 0;
}
.arch-arrow{
  position:relative; z-index:2;
  border:1px solid var(--hairline-interactive); background:transparent; color:var(--gold);
  width:48px; height:48px; border-radius:50%; display:flex; align-items:center;
  justify-content:center; cursor:pointer; font-size:22px; line-height:1;
}
.arch-arrow:hover{ background:rgba(131,103,44,.1); }
.arch-arrow:focus-visible{ outline:2px solid var(--gold); outline-offset:2px; }
@media (max-width:600px){
  .arch-arrow{ width:40px; height:40px; font-size:18px; }
}

/* ---- Уникальные квартиры с террасами (тикет 43, G53) ----
   Раздел между «Архитектурой» и «Двором» — тикет 43 (G53), переработан
   тикетом 45 (G55): тёмный фон убран (решение пользователя после 43),
   раздел вернулся к обычному светлому фону сайта (.section по умолчанию,
   var(--bg) — явного background здесь больше нет). Стоит сразу под
   полноэкранной «Архитектурой» (карусель — край-в-край, без отступа
   снизу), поэтому padding-top увеличен относительно обычного .section —
   «воздух»-пауза после плотной тёмной карусели.
   Двухцветный заголовок — тот же приём span'ов, что .history-heading-
   accent/-base (тикет 36), теперь на обычной светлой паре --gold/--dark
   (не -on-dark — фон светлый).
   Композиция — метод тикета 42 («Лобби»): крупное доминирующее фото +
   текст рядом (.unique-terraces-feature, по образцу .lobby-feature),
   затем full-bleed лента фото снизу (.terrace-ribbon — тикет 46/G56).
   Подпись на крупном фото — прежний мелкий моноширинный текст с
   градиент-скримом поверх самого фото (у скрима свой тёмный фон только
   под текстом, к фону секции отношения не имеет — контраст не зависит
   от смены фона секции). */
.unique-terraces{ padding-top:clamp(130px,14vw,220px); }
.unique-terraces-title{ margin:0; }
.unique-terraces-title-accent{ color:var(--gold); }
.unique-terraces-title-base{ color:var(--dark); }
.unique-terraces-feature{
  display:grid; grid-template-columns:1.3fr 1fr; gap:44px; align-items:stretch;
  margin-top:40px;
}
.unique-terraces-feature-media{ position:relative; margin:0; overflow:hidden; height:100%; min-height:420px; border-radius:16px; }
.unique-terraces-feature-media img{ width:100%; height:100%; object-fit:cover; display:block; }
.unique-terraces-feature-text{ display:flex; flex-direction:column; justify-content:center; }
.unique-terraces-caption{
  position:absolute; right:0; bottom:0; left:0;
  padding:36px 20px 16px; text-align:right;
  background:linear-gradient(to top, rgba(0,0,0,.55), rgba(0,0,0,0));
  font-family:var(--font-mono); font-size:11.5px; font-weight:400;
  letter-spacing:.1em; text-transform:uppercase; color:rgba(232,223,198,.78);
}
@media (max-width:760px){
  .unique-terraces-feature{ grid-template-columns:1fr; gap:24px; margin-top:26px; }
  .unique-terraces-feature-media{ height:auto; min-height:0; aspect-ratio:4/3; }
  .unique-terraces-caption{ text-align:left; padding:28px 16px 14px; }
}

/* ---- лента фото «Уникальные квартиры с террасами» (тикет 46, G56) ----
   Бриф пользователя: «добавь еще фото в горизонтальный ряд фото терасс и
   сделай чтобы они как лента сами ехали а когда на них наводишь
   останавлиалсь». Стандартный бесшовный CSS-приём: .terrace-ribbon-track
   содержит 8 фото, продублированные подряд ещё раз (16 <img> — второй
   набор с aria-hidden для скринридеров), width:max-content, анимация
   translateX(0 → -50%) — уезжает ровно на ширину первого набора, и в
   этот момент на месте оказывается визуально идентичный второй набор,
   стыка не видно. Full-bleed, вне .wrap — по образцу .arch-carousel
   (тикет 39): .section сам не даёт горизонтальных отступов, только .wrap. */
.terrace-ribbon{ overflow:hidden; width:100%; margin-top:40px; }
.terrace-ribbon-track{
  display:flex; width:max-content; gap:20px;
  animation:terrace-ribbon-scroll 70s linear infinite;
}
.terrace-ribbon:hover .terrace-ribbon-track{ animation-play-state:paused; }
.terrace-ribbon-track figure{ flex:0 0 auto; width:300px; margin:0; overflow:hidden; border-radius:12px; }
.terrace-ribbon-track img{ width:100%; height:100%; aspect-ratio:4/3; object-fit:cover; display:block; cursor:pointer; }
@keyframes terrace-ribbon-scroll{
  from{ transform:translateX(0); }
  to{ transform:translateX(-50%); }
}
@media (max-width:760px){
  .terrace-ribbon{ margin-top:26px; }
  .terrace-ribbon-track{ gap:14px; }
  .terrace-ribbon-track figure{ width:230px; }
}
@media (prefers-reduced-motion:reduce){
  .terrace-ribbon-track{ animation:none; }
  .terrace-ribbon{ overflow-x:auto; -webkit-overflow-scrolling:touch; }
}

/* ---- История: статичная 2-колоночная редакционная вёрстка (тикет 36,
   полностью заменяет механизм «летящих» фото тикетов 30/31/34, включая
   @keyframes historyDrift* — удалены без остатка). #o-dome переопределяет
   фон общего .section-dark точечно на белый (var(--bg)) — сам
   .section-dark не трогаем, его используют другие разделы; этот блок его
   не меняет. .history-split — 2 колонки по образцу общего .split (см.
   «Двор»/«Лобби»), но со своим классом: align-items:start вместо center
   (заголовок и абзац должны стартовать на одной высоте, а не по центру
   разновысоких колонок). Слева — необязательные декоративные круглые
   архивные вставки, двухцветный заголовок (span'ы .history-heading-accent
   /-base), статичное фото. Справа — абзац с золотой inline-фразой и
   цитата. Никакого transform/opacity-анимирования фото. */
#o-dome{ background:var(--bg); }
.history-split{
  display:grid; grid-template-columns:1fr 1fr; gap:48px; align-items:start;
}
.history-col{ display:flex; flex-direction:column; }

/* Декоративные круглые архивные вставки + линия (необязательный акцент
   из референса) — скрыты на мобильном, чтобы не тесниться над заголовком
   на узкой колонке (см. медиа-запрос ниже). */
.history-decor{ display:flex; align-items:center; gap:14px; margin:0 0 22px; }
.history-decor-photo{
  width:56px; height:56px; border-radius:50%; object-fit:cover;
  border:1px solid var(--hairline); flex:none;
}
.history-decor-line{ flex:1 1 auto; height:1px; background:var(--hairline); }

.history-heading{ font-size:22px; letter-spacing:.03em; line-height:1.3; margin:0 0 14px; }
.history-heading-accent{ color:var(--gold); }
.history-heading-base{ color:var(--dark); }

.history-photo-frame{ margin:0; overflow:hidden; border:1px solid var(--hairline); border-radius:16px; }
.history-photo-frame img{ width:100%; height:auto; object-fit:cover; }

.history-body{ margin:0; font-size:17px; line-height:1.65; color:var(--muted); max-width:56ch; }
.history-accent{ color:var(--gold); }

@media (max-width:760px){
  .history-split{ grid-template-columns:1fr; gap:26px; }
  .history-decor{ display:none; }
}

/* ---- Расположение ----
   Тикет 11 (G21): статичная схема (первая карточка, infra_map2.webp)
   убрана — остаётся только интерактивная карта, поэтому сетка на
   один элемент, во всю ширину .wrap, а не 1fr 1fr под два. */
.location-grid{ display:grid; grid-template-columns:1fr; gap:20px; margin-top:8px; }
.location-card{ margin:0; overflow:hidden; background:transparent; border:1px solid var(--hairline); }
.location-card img{ width:100%; height:auto; object-fit:cover; }
.location-card figcaption{ padding:12px 16px; font-weight:500; }
.location-card-map iframe{ display:block; width:100%; height:480px; border:0; }
@media (max-width:760px){ .location-card-map iframe{ height:320px; } }
.location-card-map{ background:var(--dark); border-color:var(--hairline-on-dark); }
.location-card-map figcaption{ color:var(--cream-text); }

/* ---- Инфраструктура (тикет 50, G60; правка после показа пользователю) ----
   Заменяет удалённые разделы #dvor/#lobby/#terrasy/#sauna/#interiery/
   #kommerciya/#parkovka (вместе с ними удалены .split/.material-list/
   .lobby- и .terrace-mosaic/.terrace-lead/.terrace-stack/.gallery-heading/
   .gallery/.gallery-item/.lightbox — использовались только в этих
   разделах, после удаления разметки нигде на странице не остаются;
   [data-gallery] в разметке больше нет, gallery.js после этого тикета
   просто ничего не находит и молча не инициализируется — это ожидаемо,
   сам файл не удалялся, см. отчёт). Простая сетка фото+подпись без
   текста. Первая версия (по присланному пользователем референсу) клала
   подпись в белую скруглённую плашку-капсулу поверх нижнего края фото —
   пользователь посмотрела вживую и попросила убрать: «не белые плашки,
   а в стиль и оформление сайта». Подпись переделана по образцу уже
   существующих подписей карточек на сайте (.plan-card figcaption/
   .fact-cap): обычный текстовый лейбл var(--font-mono) в верхнем
   регистре под фото, в потоке документа, без фона/капсулы/тени, с
   тонким hairline-разделителем сверху (приём .material-list/.fact-card).
   Правка после повторного показа (тикет 52, G62) — пользователь: «плашки
   сделать больше и без закруглений как фото на всем сайте и когда на
   них нажимаешь они увеличиваются». Три правки: (1) minmax увеличен
   260px→340px — на 1440px это 3 колонки вместо 4, карточки крупнее;
   (2) border-radius:20px→0 у .infra-media/.infra-photo-placeholder —
   скругление было сознательным разовым исключением тикета 50, теперь
   убрано по прямой просьбе, приведено к общему правилу сайта (0px везде
   кроме pill-кнопок); (3) клик-зум — 7 карточек с реальным фото стали
   `.infra-media.gallery-item` (кнопка вместо div, .gallery-item даёт
   cursor:zoom-in/сброс отступов кнопки, оба класса на одном элементе не
   конфликтуют — aspect-ratio/overflow остаются на .infra-media), «Кладовые»
   (плейсхолдер) — по-прежнему обычный div, не кликабельна. Использует уже
   существующий gallery.js ([data-gallery] на .infra-grid) — сам JS не
   менялся. `.gallery-item`-реcет и `.lightbox*` (оверлей-просмотрщик)
   тикет 50 удалил целиком как «мёртвый код» (тогда на странице не было ни
   одного [data-gallery]) — оба восстановлены ниже минимально необходимым
   образом. */
.infra-grid{
  display:grid; grid-template-columns:repeat(auto-fit, minmax(340px,1fr));
  gap:24px;
}
.infra-card{ margin:0; }
/* Тикет 74 (G89): реверс border-radius:0 из тикета 52 выше — пользователь
   прямо попросила скругление у всех некрупных фото сайта, включая эти
   карточки; предыдущее «без закруглений» было верно для своего момента,
   сейчас отменено новыми словами пользователя. */
.infra-media{ overflow:hidden; border-radius:16px; aspect-ratio:4/3; }
.infra-photo{ width:100%; height:100%; object-fit:cover; display:block; }
.infra-photo-placeholder{ background:var(--bg-alt); border:1px dashed var(--hairline-strong); border-radius:16px; }
.infra-caption{
  margin:14px 0 0; padding-top:14px; border-top:1px solid var(--hairline);
  font-family:var(--font-mono); font-size:13px; letter-spacing:.04em;
  text-transform:uppercase; color:var(--dark);
}
.gallery-item{
  display:block; padding:0; margin:0; border:none; background:none;
  font:inherit; color:inherit; text-align:inherit; cursor:zoom-in;
}
.gallery-item:focus-visible{ outline:2px solid var(--gold); outline-offset:3px; }

/* Единый hover-эффект «фото двигается» на всех кликабельных фото сайта
   (тикет 64, G77) — .gallery-item покрывает и .infra-media (тикет 52), и
   .presentation-thumb (тикет 56); .terrace-ribbon-track img — отдельный
   не-.gallery-item случай (тикет 55), второе правило специально под него.
   Родительские контейнеры уже имеют overflow:hidden, увеличенное фото
   обрежется по рамке карточки. Не трогает .arch-slide (переключение
   фото по клику/стрелкам, не hover-приближение) и статичные некликабельные
   фото. */
@media (prefers-reduced-motion: no-preference) {
  .gallery-item img{ transition:transform .4s ease; }
  .gallery-item:hover img{ transform:scale(1.06); }
  .terrace-ribbon-track img{ transition:transform .4s ease; }
  .terrace-ribbon-track img:hover{ transform:scale(1.06); }
}

/* Лайтбокс — собственный тёмный оверлей поверх всей страницы независимо
   от базовой палитры, элементы управления уже светлые на тёмном
   (rgba(255,255,255,...) хардкод) — не участвует в развороте тикета 09.
   Восстановлено тикетом 52 (G62) — точный блок из тикета,
   `git show 680ebe0^:styles.css`. */
.lightbox{
  display:none; position:fixed; inset:0; z-index:1100;
  background:rgba(10,10,10,.92); padding:24px; align-items:center; justify-content:center;
}
.lightbox.is-open{ display:flex; }
.lightbox-inner{ position:relative; max-width:min(1100px,94vw); max-height:88vh; width:100%; }
.lightbox-inner img{ max-width:100%; max-height:80vh; margin:0 auto; object-fit:contain; }
.lightbox-caption{ color:rgba(255,255,255,.78); font-size:13.5px; text-align:center; margin-top:12px; }
.lightbox-close, .lightbox-prev, .lightbox-next{
  position:absolute; border:1px solid rgba(255,255,255,.35); background:rgba(0,0,0,.35); color:#fff;
  width:42px; height:42px; border-radius:50%; display:flex; align-items:center; justify-content:center; cursor:pointer;
}
.lightbox-close{ top:-52px; right:0; }
.lightbox-prev{ left:-56px; top:50%; transform:translateY(-50%); }
.lightbox-next{ right:-56px; top:50%; transform:translateY(-50%); }
.lightbox-close:hover, .lightbox-prev:hover, .lightbox-next:hover{ background:rgba(255,255,255,.16); }
.lightbox-close:focus-visible, .lightbox-prev:focus-visible, .lightbox-next:focus-visible{ outline:2px solid var(--gold); outline-offset:2px; }
@media (max-width:760px){
  .lightbox-prev{ left:4px; } .lightbox-next{ right:4px; } .lightbox-close{ top:4px; right:4px; }
}

/* ---- Вкладки (планировки, ход стройки) — см. tabs.js ---- */
.tabs-list{ display:flex; gap:10px; flex-wrap:wrap; margin-bottom:24px; }
.tabs-tab{
  position:relative;
  padding:11px 20px; border-radius:999px; border:1px solid var(--hairline-interactive);
  background:transparent; color:inherit; font-family:var(--font-mono); font-weight:400;
  font-size:13px; letter-spacing:.08em; text-transform:uppercase; cursor:pointer;
  transition:background .2s ease, color .2s ease, border-color .2s ease;
}
.tabs-tab[aria-selected="true"]{ background:rgba(131,103,44,.1); border-color:var(--gold); color:var(--gold); }
.tabs-tab:focus-visible{ outline:2px solid var(--gold); outline-offset:3px; }
.tabs-panel[hidden]{ display:none; }

/* ---- Планировки: карточки планировок ---- */
.plan-lifestyle{ font-family:var(--font-body); font-size:16px; color:var(--muted); max-width:64ch; margin:0 0 24px; }
.plan-grid{ display:grid; grid-template-columns:repeat(auto-fit, minmax(220px,1fr)); gap:24px; }
.plan-card{ margin:0 auto; max-width:380px; width:100%; border:1px solid var(--hairline-strong); border-radius:12px; padding:14px; background:transparent; }
.plan-card img{ display:block; width:100%; height:56vh; max-height:480px; object-fit:contain; background:#fff; }
.plan-card figcaption{ display:flex; flex-wrap:wrap; gap:6px 14px; padding-top:14px; font-family:var(--font-mono); font-size:12px; letter-spacing:.04em; text-transform:uppercase; }
.plan-card figcaption span{ font-weight:500; color:var(--dark); }
.plan-card .plan-price{ margin-left:auto; color:var(--gold); }

/* ---- Ход стройки: прогресс + фотоотчёт по месяцам ---- */
.progress-wrap{ margin-bottom:32px; }
.progress-bar{ height:6px; border-radius:0; background:var(--hairline); overflow:hidden; }
.progress-fill{ height:100%; border-radius:0; background:var(--dark); }
.progress-label{ display:flex; justify-content:space-between; font-family:var(--font-mono); font-size:12px; letter-spacing:.03em; text-transform:uppercase; margin-top:8px; color:rgba(26,26,26,.72); }
.shot-grid{ display:grid; grid-template-columns:repeat(auto-fill, minmax(160px,1fr)); gap:12px; }
.shot-grid img{ width:100%; aspect-ratio:4/3; object-fit:cover; }

/* ---- Ипотека / Застройщик: карточки фактов ---- */
.fact-grid{ display:grid; grid-template-columns:repeat(3,1fr); gap:1px; background:var(--hairline); border:1px solid var(--hairline); }
.fact-card{ background:var(--bg); padding:22px 20px; }
.section-dark .fact-card, .section-deep .fact-card{ background:var(--bg); }
.fact-num{ font-family:var(--font-display); font-weight:400; font-size:22px; color:var(--dark); letter-spacing:.02em; }
.fact-cap{ font-family:var(--font-mono); font-size:11.5px; letter-spacing:.04em; text-transform:uppercase; color:var(--muted); margin-top:6px; }
@media (max-width:600px){ .fact-grid{ grid-template-columns:1fr; } }

/* ---- Вопросы (FAQ) — аккордеон, тикет 67 (G80), поведение навешивает faq.js ---- */
.faq-list{ display:flex; flex-direction:column; gap:6px; max-width:820px; }
.faq-item{
  border-radius:14px; padding:18px 20px; background:transparent;
  transition:background .2s ease;
}
.faq-item[open]{ background:var(--bg-alt); }
.faq-item summary{
  cursor:pointer; font-weight:500; font-size:16px; list-style:none; position:relative; padding-right:28px;
  color:var(--dark); transition:color .2s ease;
}
.faq-item[open] summary{ color:var(--gold); }
.faq-item summary::-webkit-details-marker{ display:none; }
.faq-item summary::after{
  /* Один и тот же шеврон (не меняется на противоположный символ) —
     между закрытым/открытым состоянием он поворачивается на 180°. */
  content:'\2304'; position:absolute; right:0; top:2px; font-size:18px; color:var(--dark); line-height:1;
  transform:rotate(0deg); transform-origin:50% 45%;
  transition:transform .2s ease, color .2s ease;
}
.faq-item[open] summary::after{ color:var(--gold); transform:rotate(180deg); }
.faq-item summary:focus-visible{ outline:2px solid var(--gold); outline-offset:3px; }
.faq-item p{ margin:12px 0 0; color:var(--muted); max-width:70ch; }

/* ---- Планировки: кнопка на живой подбор (тикет 03) ---- */
.plan-cta{ margin-top:32px; }

/* ---- Ипотека: фото-секция (тикет 72, G86) — ровно приём .hero/
   .hero-media/.hero-photo/.hero-scrim/.hero-inner выше: обёртка
   position:relative;overflow:hidden, фото position:absolute;inset:0;
   object-fit:cover, затемняющий scrim поверх для читаемости заголовка,
   контент в отдельном слое с z-index. padding-top/bottom вместо
   базового .section clamp(72px,10vw,120px) — чтобы фото не превращалось
   в тонкую полоску на средних вьюпортах, но и не растягивало секцию
   больше нужного. */
.ipoteka-photo{ position:relative; overflow:hidden; padding-top:72px; padding-bottom:72px; }
.ipoteka-photo-media{ position:absolute; inset:0; z-index:0; }
.ipoteka-photo-media img{ position:absolute; inset:0; width:100%; height:100%; object-fit:cover; }
.ipoteka-scrim{
  position:absolute; inset:0; z-index:1; pointer-events:none;
  background:linear-gradient(180deg, rgba(26,26,26,.4) 0%, rgba(26,26,26,.18) 38%, rgba(26,26,26,.5) 100%);
}
.ipoteka-inner{ position:relative; z-index:2; }
.ipoteka-photo .section-title{ color:var(--cream-text); text-shadow:0 2px 14px rgba(0,0,0,.45); }
@media (max-width:600px){
  /* Тикет 76: 44px было меньше реальной высоты мобильной фикс-шапки
     (70px на этом брейкпоинте) — заголовок «Ипотека» обрезался под
     шапкой при обычной прокрутке (не через якорный клик, там спасал
     offset в smooth.js/scroll-padding-top). padding-bottom не трогаем,
     он не участвует в баге. */
  .ipoteka-photo{ padding-top:calc(var(--header-h) + 8px); padding-bottom:44px; }
}

/* ---- Ипотека: калькулятор (тикет 03; слайдеры + фиксированная ставка —
   тикет 67, G80; разметка строится calculator.js). Тикет 72 (G86):
   раньше был плоский прозрачный блок — теперь на фото поверх сидит
   настоящая «стеклянная» карточка (референс — виджет календаря
   macOS/iOS): полупрозрачный светлый фон + backdrop-filter:blur даёт
   эффект стекла, скругление + мягкая тень отделяют карточку от фото.
   Внутренние элементы (.calc-slider-value, .calc-result и т.д.) не
   тронуты — на этой светлой подложке они читаются так же, как раньше
   на --bg. */
.calc{
  margin-top:8px; max-width:900px;
  background:rgba(255,255,255,.38);
  -webkit-backdrop-filter:blur(16px) saturate(140%);
  backdrop-filter:blur(16px) saturate(140%);
  border-radius:28px;
  padding:32px 36px;
  box-shadow:0 20px 60px rgba(0,0,0,.28);
}
/* Браузеры без поддержки backdrop-filter (проверка на самом надёжном
   свойстве пары) получают почти непрозрачный фон — без blur полупрозрачное
   стекло на фото читалось бы плохо. */
@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  .calc{ background:rgba(255,255,255,.94); }
}
@media (max-width:600px){ .calc{ padding:24px 20px; border-radius:22px; } }

.calc-sliders{ display:grid; grid-template-columns:repeat(3, 1fr); gap:28px 32px; margin-bottom:28px; }
@media (max-width:700px){ .calc-sliders{ grid-template-columns:1fr; } }
.calc-slider-field{ display:flex; flex-direction:column; gap:4px; }
.calc-label{ font-family:var(--font-mono); font-size:12px; letter-spacing:.04em; text-transform:uppercase; font-weight:400; color:rgba(26,26,26,.75); }
.calc-slider-value{ font-family:var(--font-display); font-weight:400; font-size:26px; letter-spacing:.02em; color:var(--dark); margin:2px 0 8px; }

/* Трек закрашивается из calculator.js (paintTrack()) через инлайновый
   background — golden слева от бегунка, --hairline-strong справа;
   здесь только форма трека/бегунка, кроссбраузерно. */
.calc-sliders input[type="range"]{
  -webkit-appearance:none; appearance:none;
  display:block; width:100%; height:5px; border-radius:3px;
  background:var(--hairline-strong);
  outline:none; cursor:pointer; margin:0;
}
.calc-sliders input[type="range"]::-webkit-slider-runnable-track{
  height:5px; border-radius:3px; background:transparent;
}
.calc-sliders input[type="range"]::-webkit-slider-thumb{
  -webkit-appearance:none; appearance:none;
  width:20px; height:20px; margin-top:-7.5px; border-radius:50%;
  background:var(--gold); border:none; cursor:pointer;
  box-shadow:0 0 0 1px rgba(26,26,26,.08);
}
.calc-sliders input[type="range"]::-moz-range-track{
  height:5px; border-radius:3px; background:transparent;
}
.calc-sliders input[type="range"]::-moz-range-thumb{
  width:20px; height:20px; border-radius:50%;
  background:var(--gold); border:none; cursor:pointer;
  box-shadow:0 0 0 1px rgba(26,26,26,.08);
}
.calc-sliders input[type="range"]:focus-visible{ outline:2px solid var(--gold); outline-offset:4px; }

.calc-result{
  display:flex; align-items:center; flex-wrap:wrap; gap:18px 24px;
  background:var(--bg-alt); border-radius:14px; padding:22px 26px;
}
.calc-result-item{ display:flex; flex-direction:column; gap:4px; }
.calc-result-divider{ width:1px; align-self:stretch; min-height:38px; background:var(--hairline); }
.calc-result-label{ font-family:var(--font-mono); font-size:12.5px; letter-spacing:.04em; text-transform:uppercase; color:var(--muted); }
.calc-result-value{ font-family:var(--font-display); font-weight:400; font-size:28px; letter-spacing:.03em; color:var(--gold); }
.calc-result-cta{ margin-left:auto; }
@media (max-width:600px){
  .calc-result{ flex-direction:column; align-items:flex-start; }
  .calc-result-divider{ display:none; }
  .calc-result-cta{ margin-left:0; width:100%; }
}
.calc-note{ font-size:12.5px; color:var(--muted); margin-top:14px; }

/* ---- Заявка: форма (тикет 03) ---- */
.lead-form{ max-width:560px; }
.field{ display:flex; flex-direction:column; gap:6px; margin-bottom:18px; }
.field-label{ font-family:var(--font-mono); font-size:12px; letter-spacing:.04em; text-transform:uppercase; font-weight:400; color:rgba(26,26,26,.85); }
.field input[type="text"], .field input[type="tel"]{
  padding:13px 14px; border-radius:0; border:1px solid var(--hairline-strong);
  background:rgba(26,26,26,.05); color:var(--dark); font-family:var(--font-body); font-size:15px;
}
.field input::placeholder{ color:rgba(26,26,26,.4); }
.field input:focus-visible{ outline:2px solid var(--gold); outline-offset:2px; border-color:var(--gold); }
.field input[aria-invalid="true"]{ border-color:var(--danger); }
.field-error{ display:block; min-height:16px; font-size:12.5px; color:var(--danger); }
.field-checkbox{
  display:flex; align-items:flex-start; gap:10px; font-size:13.5px;
  color:rgba(26,26,26,.85); margin-bottom:2px; cursor:pointer; max-width:520px;
}
.field-checkbox input{ margin-top:3px; flex:0 0 auto; width:16px; height:16px; }
.field-checkbox a{ color:var(--dark); text-decoration:underline; }
.lead-form .btn[disabled]{ opacity:.45; cursor:not-allowed; pointer-events:none; }
/* .btn задаёт display:inline-flex (специфичность равна [hidden] из UA-стиля,
   но автор-CSS всегда перевешивает UA) — без этого переопределения
   submitBtn.hidden=true из lead-form.js (см. showSuccess()) не прячет
   кнопку. Раньше это было прикрыто отдельным .callback-submit[hidden]
   только для #zakazat-zvonok (тикет 48) — при переходе на общий .btn
   (тикет 54) добавлено сюда один раз для обеих форм. */
.lead-form .btn[hidden]{ display:none; }
.lead-form-status{ margin-top:16px; font-size:14px; min-height:1px; }
.lead-form-status.is-success{ color:var(--gold); }
.lead-form-status.is-error{ color:var(--danger); }
.lead-form-status .btn{ margin-top:10px; }
.policy-block{ margin-top:28px; max-width:640px; font-size:13px; color:rgba(26,26,26,.6); }
.policy-block summary{ cursor:pointer; color:rgba(26,26,26,.8); }
.policy-block summary:focus-visible{ outline:2px solid var(--gold); outline-offset:3px; }
.policy-block p{ margin:10px 0 0; line-height:1.6; }
/* не --danger: это служебная пометка о заглушке текста, а не ошибка
   пользователя — не должна делить сигнал с .field-error/.is-error */
.policy-block strong{ color:var(--dark); }

/* ---- CTA-баннер: «Заказать звонок» / «Оставьте заявку» (тикет 54/
   G64) — общий компонент для обеих форм-разделов. Заменяет разошедшиеся
   .callback-* (тикет 48) и разметку .section-deep/.lead-form-grid,
   которые раньше делали эти два раздела визуально разными. Требование
   пользователя: «одинаковые, фон тёмный как в конце сайта, баннер на
   всю ширину но невысокий, стильная полоса» — фон и токены взяты ровно
   из существующих тёмных зон (hero/футер/моб.меню), новых цветов нет:
   --dark (фон, как у <footer>), --cream-text (текст), --gold-on-dark
   (акцент/кнопка — тот же паттерн, что .hero .btn-primary), --hairline-
   on-dark[-interactive] (линии полей/разделители). Компактность — .section
   даёт clamp(72px,10vw,120px) 0, здесь заметно меньше по высоте, и
   контент лежит горизонтально (заголовок слева, форма справа) на
   средних/широких экранах — именно это превращает раздел в «полосу»,
   а не в обычный full-height раздел. */
.cta-banner{
  background:var(--dark);
  padding:clamp(40px,6vw,64px) 0;
  border-top:1px solid var(--hairline-on-dark);
}
.cta-banner-row{
  display:flex; align-items:center; justify-content:space-between;
  gap:clamp(28px,4vw,56px);
}
.cta-banner-head{ flex:0 1 300px; }
.cta-banner-head .eyebrow{ color:var(--gold-on-dark); }
.cta-banner-title{
  font-family:var(--font-display); font-weight:400; text-transform:uppercase;
  letter-spacing:.05em; line-height:1.15; margin:0;
  font-size:clamp(24px,2.6vw,32px); color:var(--cream-text);
}
.cta-banner-form{ flex:1 1 480px; max-width:640px; margin:0; }
.cta-banner-fields{ display:flex; align-items:flex-end; flex-wrap:wrap; gap:16px 20px; }
.cta-banner-fields .field{ flex:1 1 160px; min-width:140px; margin-bottom:0; }
/* Подложка полей рассчитана на светлый фон (rgba(26,26,26,.05)) — на
   тёмном она невидима, поэтому здесь та же «линия снизу», что раньше
   была только у .callback-form, но в -on-dark токенах. */
.cta-banner-form .field-label{ color:rgba(232,223,198,.7); }
.cta-banner-form .field input[type="text"],
.cta-banner-form .field input[type="tel"]{
  background:transparent; border:none; border-radius:0;
  border-bottom:1px solid var(--hairline-on-dark-interactive);
  color:var(--cream-text); padding:10px 2px;
}
.cta-banner-form .field input::placeholder{ color:rgba(232,223,198,.4); }
.cta-banner-form .field input:focus-visible{
  outline:none; border-bottom-color:var(--gold-on-dark); border-bottom-width:2px;
}
/* border-bottom выше (для линии на тёмном) перебивает border-color из
   базового .field input[aria-invalid="true"] — тот же --danger, что и
   у .field-error рядом, восстановлен явно поверх. */
.cta-banner-form .field input[aria-invalid="true"]{ border-bottom-color:var(--danger); }
.cta-banner-form .field-checkbox{ color:rgba(232,223,198,.85); margin-top:18px; }
.cta-banner-form .field-checkbox a{ color:var(--gold-on-dark); }
/* Кнопка — ровно паттерн .hero .btn-primary (border/color --gold-on-dark,
   hover — заливка --gold-on-dark с текстом --dark), не новый стиль. */
.cta-banner .btn-primary{ border-color:var(--gold-on-dark); color:var(--gold-on-dark); flex:0 0 auto; }
.cta-banner .btn-primary:hover{ background:rgba(201,169,110,.14); }
.cta-banner .btn:focus-visible{ outline-color:var(--gold-on-dark); }
.cta-banner-form .lead-form-status{ color:var(--cream-text); }
.cta-banner-form .lead-form-status.is-success{ color:var(--gold-on-dark); }
/* .is-error без этого переопределения наследовал бы --cream-text от
   правила выше (та же специфичность, но правило выше по файлу) — та же
   --danger, что уже красит .field-error, чтобы ошибка поля и ошибка
   отправки читались одним цветом, как и на светлом фоне. */
.cta-banner-form .lead-form-status.is-error{ color:var(--danger); }
/* #zayavka хранит <details id="policyText"> внутри .cta-banner — тот же
   .policy-block, что и раньше, только текст читаем на тёмном фоне. */
.cta-banner .policy-block{ color:rgba(232,223,198,.6); }
.cta-banner .policy-block summary{ color:rgba(232,223,198,.8); }
.cta-banner .policy-block summary:focus-visible{ outline-color:var(--gold-on-dark); }
.cta-banner .policy-block strong{ color:var(--cream-text); }
@media (max-width:760px){
  /* flex:0 1 300px/1 1 480px выше задают flex-basis по главной оси —
     при переключении row→column главная ось становится вертикальной,
     и те же значения превратились бы в min-height, растягивая блоки
     пустотой; сбрасываем на flex:none, ширина/высота уже не общий ресурс. */
  .cta-banner-row{ flex-direction:column; align-items:stretch; }
  .cta-banner-head, .cta-banner-form{ flex:none; }
  .cta-banner-form{ max-width:none; }
  .cta-banner-fields{ flex-direction:column; align-items:stretch; }
  .cta-banner-fields .field{ flex:1 1 auto; }
  .cta-banner-fields .btn{ width:100%; }
}

/* Презентация (тикет 56, G66) — второй слот .cta-banner-row вместо
   .cta-banner-form: 2 маленькие кликабельные превью-миниатюры
   (.gallery-item/[data-gallery], тот же лайтбокс, что у «Инфраструктуры»,
   тикет 52 — не копировать, не трогать) + кнопка «Скачать PDF». Только
   раскладка — сам .cta-banner* не переопределяется. */
.presentation-preview{
  flex:1 1 480px; max-width:640px; margin:0;
  display:flex; align-items:center; gap:24px; flex-wrap:wrap;
}
.presentation-preview-thumbs{ display:flex; gap:12px; }
.presentation-thumb{
  width:96px; aspect-ratio:1755/1241; overflow:hidden;
  border:1px solid var(--hairline-on-dark); border-radius:10px;
}
.presentation-thumb img{ width:100%; height:100%; object-fit:cover; display:block; }
@media (max-width:760px){
  .presentation-preview{ flex:none; width:100%; align-items:flex-start; }
  .presentation-preview .btn{ width:100%; }
}

/* Презентация + заявка (тикет 62, G73–G75) — были два отдельных
   .cta-banner подряд перед тёмным футером (3 тёмные зоны подряд,
   читались сплошной стеной); объединены в один .cta-banner с
   2-колоночной раскладкой. Только раскладка — .cta-banner-head/
   .cta-banner-title/.cta-banner-form/.presentation-preview и т.д.
   переиспользуются как есть, не копируются. */
.cta-banner-split{
  display:grid; grid-template-columns:1fr 1fr; gap:56px; align-items:start;
}
.cta-banner-col{ display:flex; flex-direction:column; gap:28px; }
.cta-banner-col + .cta-banner-col{
  border-left:1px solid var(--hairline-on-dark); padding-left:56px;
}
/* .cta-banner-head/.cta-banner-form/.presentation-preview заданы под
   flex:N M Npx внутри бывшего горизонтального .cta-banner-row — в
   вертикальном .cta-banner-col та же flex-basis легла бы на высоту.
   Точечный сброс только здесь, базовые классы не трогаем — они ещё
   используются в горизонтальном .cta-banner-row у #zakazat-zvonok. */
.cta-banner-col .cta-banner-head,
.cta-banner-col .cta-banner-form,
.cta-banner-col .presentation-preview{ flex:none; max-width:none; }
@media (max-width:760px){
  .cta-banner-split{ grid-template-columns:1fr; gap:40px; }
  .cta-banner-col + .cta-banner-col{
    border-left:none; padding-left:0;
    border-top:1px solid var(--hairline-on-dark); padding-top:32px;
  }
}
