/* Публичный сайт: шапка, экраны, портфолио, конструктор, подвал. */

/* --- Шапка ---------------------------------------------------------------- */

.header {
  position: sticky; top: 0; z-index: 40;
  background: color-mix(in srgb, var(--paper) 88%, transparent);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--line-soft);
}
.header__inner {
  display: flex; align-items: center;
  gap: var(--gap-4); min-height: 72px;
}
/* Логотип слева, меню и инструменты прижаты вправо. Без этого третий
   элемент во flex со space-between оказывается посреди шапки. */
.header__inner .nav { margin-left: auto; }

/* Логотип: знак «ДА» плюс подпись. Знак наследует currentColor, поэтому
   работает в шапке, в подвале и в обеих темах без второго файла. */
.logo {
  display: inline-flex; align-items: center; gap: var(--gap-3);
  text-decoration: none; color: var(--ink); line-height: 1.1;
}
.logo__mark { color: var(--brand-500); flex: none; transition: transform .25s var(--ease); }
.footer .logo__mark { width: 48px; height: 31px; }
.logo:hover .logo__mark { transform: translateY(-1px); }
.logo__text { display: grid; }
.logo__name {
  font-family: var(--font-display); font-weight: 800;
  letter-spacing: -0.04em; font-size: var(--step-1);
}
.logo__title {
  font-size: var(--step--2); color: var(--muted); letter-spacing: .02em;
  white-space: nowrap;
}
@media (max-width: 560px) { .logo__title { display: none; } }

.footer .logo { margin-bottom: var(--gap-3); }

/* --- Переключатель темы --------------------------------------------------
   Кнопка появляется только при работающем JS: без него она бесполезна. */
.header__tools { display: flex; align-items: center; gap: var(--gap-2); flex: none; }

.theme {
  display: none;
  align-items: center; justify-content: center;
  width: 44px; height: 44px; flex: none;
  background: none; border: 1px solid var(--line); border-radius: var(--radius-pill);
  color: var(--ink-2); cursor: pointer;
  transition: border-color .18s var(--ease), color .18s var(--ease);
}
.js .theme { display: inline-flex; }
.theme:hover { border-color: var(--brand-400); color: var(--brand-500); }
.theme__sun, .theme__moon { position: absolute; transition: opacity .2s var(--ease), transform .3s var(--ease); }
.theme { position: relative; }
.theme[data-state="light"] .theme__moon { opacity: 0; transform: rotate(-40deg) scale(.6); }
.theme[data-state="light"] .theme__sun { opacity: 1; transform: none; }
.theme[data-state="dark"] .theme__sun { opacity: 0; transform: rotate(40deg) scale(.6); }
.theme[data-state="dark"] .theme__moon { opacity: 1; transform: none; }

.nav { display: flex; align-items: center; gap: var(--gap-5); }
.nav a { color: var(--ink-2); text-decoration: none; font-size: var(--step--1); }
.nav a:hover { color: var(--brand-500); }
.nav__cta {
  color: #fff !important; background: var(--brand-500);
  padding: var(--gap-2) var(--gap-4); border-radius: var(--radius-pill);
  min-height: 40px; display: inline-flex; align-items: center;
}
.nav__cta:hover { background: var(--brand-600); }
.nav__minor { color: var(--muted) !important; }

.burger { display: none; background: none; border: 0; padding: 12px; cursor: pointer; }
.burger span { display: block; width: 24px; height: 2px; background: var(--ink); margin: 5px 0; transition: transform .2s var(--ease), opacity .2s; }
.burger[aria-expanded="true"] span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.burger[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.burger[aria-expanded="true"] span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

@media (max-width: 900px) {
  .burger { display: block; }
  /* Меню уезжает в выпадающую панель, и его margin-left: auto перестаёт
     работать — тема с бургером оказывались прижаты к логотипу посреди
     шапки. Прижимаем вправо их самих. */
  .header__tools { margin-left: auto; }
  .nav {
    position: fixed; inset: 68px 0 auto 0;
    flex-direction: column; align-items: stretch; gap: 0;
    background: var(--paper); border-bottom: 1px solid var(--line);
    padding: var(--gap-4) 1.25rem var(--gap-6);
    transform: translateY(-120%); transition: transform .25s var(--ease);
    max-height: calc(100dvh - 68px); overflow-y: auto;
  }
  .nav.is-open { transform: translateY(0); }
  .nav a { padding: var(--gap-4) 0; font-size: var(--step-1); border-bottom: 1px solid var(--line-soft); }
  .nav__cta { justify-content: center; margin-top: var(--gap-4); border-bottom: 0; }
}

/* --- Экраны --------------------------------------------------------------- */

.section { padding: var(--gap-8) 0; }
.section--tight { padding: var(--gap-7) 0; }
.section--alt { background: var(--paper-alt); }
.section--ink { background: var(--brand-500); color: #fff; }
.section--ink h2, .section--ink a { color: #fff; }

.eyebrow {
  font-size: var(--step--2); letter-spacing: .16em; text-transform: uppercase;
  color: var(--brand-500); font-weight: 600; margin-bottom: var(--gap-3);
}

.lead { font-size: var(--step-1); color: var(--ink-2); max-width: 62ch; }

/* --- Первый экран --------------------------------------------------------
   Слева — заголовок и мини-расчёт единым столбцом: расчёт продолжает
   мысль заголовка, а не висит сбоку сам по себе. Справа — линейный
   набросок интерьера. */
.hero { padding: var(--gap-8) 0 var(--gap-8); overflow: hidden; }

.hero__inner { display: grid; gap: var(--gap-7); align-items: center; }
@media (min-width: 980px) {
  .hero__inner { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--gap-6); }
}

.hero__title {
  font-size: var(--step-5);
  letter-spacing: -0.055em;
  line-height: .88;
  color: var(--ink);
  margin-bottom: var(--gap-5);
  text-transform: lowercase;
}
.hero__line { display: block; }
.hero__line--accent { color: var(--brand-500); }

.js .hero__line { animation: rise .7s var(--ease) backwards; }
.js .hero__line:nth-child(2) { animation-delay: .08s; }
.js .hero__line:nth-child(3) { animation-delay: .16s; }

@keyframes rise {
  from { opacity: 0; transform: translateY(0.35em); }
  to   { opacity: 1; transform: none; }
}

.hero__sub { font-size: var(--step-1); max-width: 44ch; color: var(--ink-2); }
.hero__actions { display: flex; flex-wrap: wrap; gap: var(--gap-3); margin-top: var(--gap-6); }

/* Мини-расчёт: вопрос и ответ в одну строку каждый, кнопка следом. */
.quick {
  margin-top: var(--gap-6);
  max-width: 460px;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius-3); padding: var(--gap-5);
  box-shadow: var(--shadow-1);
}
.quick__ask {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--gap-4); flex-wrap: wrap;
}
.quick__label { font-size: var(--step-0); color: var(--ink-2); font-weight: 600; margin: 0; }
.quick__field { display: inline-flex; align-items: baseline; gap: var(--gap-2); }
.quick__input {
  width: 4.5ch; min-height: 0; padding: 0 0 2px;
  font-family: var(--font-display);
  font-size: var(--step-3); font-weight: 800; letter-spacing: -.04em;
  color: var(--brand-500); text-align: right;
  background: none; border: 0; border-bottom: 2px solid var(--brand-200);
  border-radius: 0;
}
.quick__input:focus { box-shadow: none; border-bottom-color: var(--brand-500); }
/* Стрелки числового поля крадут место у крупной цифры. */
.quick__input::-webkit-outer-spin-button,
.quick__input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.quick__input { -moz-appearance: textfield; appearance: textfield; }
.quick__unit { font-size: var(--step-0); color: var(--muted); }

.quick__answer {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--gap-4); flex-wrap: wrap;
  margin: var(--gap-4) 0 var(--gap-5);
  padding-top: var(--gap-4); border-top: 1px solid var(--line-soft);
}
.quick__caption { font-size: var(--step--1); color: var(--muted); }
.quick__price {
  font-family: var(--font-display); font-weight: 800;
  font-size: var(--step-2); letter-spacing: -.03em; color: var(--ink);
  white-space: nowrap;
}
.quick .btn { width: 100%; }
.quick__note { font-size: var(--step--2); color: var(--muted); margin: var(--gap-4) 0 0; }

/* --- Набросок ------------------------------------------------------------- */

.hero__art { color: var(--ink-2); }
@media (max-width: 979px) { .hero__art { display: none; } }

.art { width: 100%; height: auto; display: block; }
.art__line { opacity: .55; }
.art__line--soft { opacity: .3; }

/* Линии прорисовываются одна за другой — так же, как их рисуют от руки.
   Длина штриха заведомо больше любого пути в рисунке, поэтому один
   и тот же набор чисел годится для всех. */
.js .art__line {
  stroke-dasharray: 1400;
  stroke-dashoffset: 1400;
  animation: draw 1.1s var(--ease) forwards;
  animation-delay: calc(var(--i) * .07s);
}
@keyframes draw { to { stroke-dashoffset: 0; } }

/* Пар — единственное, что движется постоянно. Он и делает сцену живой. */
.art__vapor {
  opacity: 0;
  stroke: var(--brand-500);
  transform-origin: center bottom;
  animation: vapor 3.4s ease-in-out infinite;
  animation-delay: calc(2s + var(--v) * .55s);
}
@keyframes vapor {
  0%   { opacity: 0; transform: translateY(6px) scaleY(.85); }
  25%  { opacity: .55; }
  70%  { opacity: .3; }
  100% { opacity: 0; transform: translateY(-26px) scaleY(1.15); }
}

/* Мурчание кота — второе живое место на рисунке. Поднимается так же,
   как пар над чашкой, только вбок: звук идёт от кота, а не из него. */
.art__purr {
  opacity: 0;
  fill: var(--brand-500);
  font-family: var(--font-display); font-weight: 700;
  animation: purr 4.2s ease-in-out infinite;
  animation-delay: calc(2.4s + var(--p) * 1.4s);
}
@keyframes purr {
  0%   { opacity: 0; transform: translate(0, 8px); }
  20%  { opacity: .7; }
  65%  { opacity: .35; }
  100% { opacity: 0; transform: translate(14px, -14px); }
}

@media (prefers-reduced-motion: reduce) {
  .js .art__line { stroke-dashoffset: 0; animation: none; }
  .art__vapor { opacity: .4; animation: none; }
  .art__purr { opacity: .45; animation: none; }
}

/* --- Цифры ---------------------------------------------------------------- */

.facts { display: grid; gap: var(--gap-6); grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); }
.fact { display: grid; gap: var(--gap-2); }
.fact__num {
  font-family: var(--font-display); font-weight: 800;
  font-size: var(--step-4); line-height: 1; letter-spacing: -.05em;
  color: var(--brand-500);
}
.fact__label { color: var(--muted); font-size: var(--step--1); max-width: 26ch; }

/* --- Появление при прокрутке --------------------------------------------- */

.will-reveal { opacity: 0; transform: translateY(18px); }
.will-reveal.is-visible {
  opacity: 1; transform: none;
  transition: opacity .6s var(--ease), transform .6s var(--ease);
}

.btn--on-ink { color: #fff; border-color: rgba(255, 255, 255, .5); }
.btn--on-ink:hover { background: rgba(255, 255, 255, .12); color: #fff; border-color: #fff; }

.grid { display: grid; gap: var(--gap-5); }
.grid--2 { grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); }
.grid--3 { grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); }

.card {
  background: var(--surface); border: 1px solid var(--line-soft);
  border-radius: var(--radius-3); padding: var(--gap-5);
}
.card__title { font-size: var(--step-1); margin-bottom: var(--gap-2); }
.card__muted { color: var(--muted); font-size: var(--step--1); }

.split { display: grid; gap: var(--gap-7); grid-template-columns: 1fr; align-items: start; }
@media (min-width: 900px) { .split { grid-template-columns: 1fr 1fr; } }

.portrait { border-radius: var(--radius-3); overflow: hidden; background: var(--sand); aspect-ratio: 4/5; }
.portrait img { width: 100%; height: 100%; object-fit: cover; }

/* --- Портфолио ------------------------------------------------------------ */

.works { display: grid; gap: var(--gap-5); grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); }
.work { text-decoration: none; color: inherit; display: grid; gap: var(--gap-3); }
.work__img { aspect-ratio: 4/3; background: var(--sand); border-radius: var(--radius-3); overflow: hidden; }
.work__img img { width: 100%; height: 100%; object-fit: cover; transition: transform .4s var(--ease); }
.work:hover .work__img img { transform: scale(1.03); }
.work__title { font-weight: 700; font-size: var(--step-1); }
.work__meta { color: var(--muted); font-size: var(--step--1); }

/* --- Услуги и вопросы ----------------------------------------------------- */

.accordion { border-top: 1px solid var(--line); }
.accordion__item { border-bottom: 1px solid var(--line); }
.accordion__head {
  width: 100%; display: flex; justify-content: space-between; align-items: center; gap: var(--gap-4);
  background: none; border: 0; padding: var(--gap-5) 0; cursor: pointer;
  font: inherit; font-weight: 700; font-size: var(--step-1); color: var(--ink); text-align: left;
}
.accordion__head::after { content: "+"; font-size: var(--step-2); color: var(--brand-500); flex: none; }
.accordion__item.is-open .accordion__head::after { content: "−"; }
.accordion__body { padding-bottom: var(--gap-5); max-width: 70ch; color: var(--ink-2); }
.accordion__body[hidden] { display: none; }

.note {
  border-left: 3px solid var(--brand-500);
  background: var(--brand-50);
  padding: var(--gap-4) var(--gap-5);
  border-radius: 0 var(--radius-2) var(--radius-2) 0;
}
.note--warn { border-color: var(--warn); background: var(--warn-bg); }

/* --- Этапы ---------------------------------------------------------------- */

.steps { display: grid; gap: var(--gap-4); counter-reset: step; }
.step {
  display: grid; grid-template-columns: 56px 1fr; gap: var(--gap-4);
  padding: var(--gap-5); background: var(--surface);
  border: 1px solid var(--line-soft); border-radius: var(--radius-3);
}
.step__num {
  font-family: var(--font-display); font-size: var(--step-2); font-weight: 800;
  color: var(--brand-500); letter-spacing: -.04em; line-height: 1;
}
.step__days { color: var(--muted); font-size: var(--step--1); margin-top: var(--gap-2); }

/* ==========================================================================
   Конструктор: дом из кубиков
   ========================================================================== */

/* Две колонки задаются НА ФОРМЕ, а не на обёртке: дом и склад лежат
   внутри неё, и колонки внешнего контейнера до них просто не доходили —
   форма занимала одну колонку, а внутри всё вставало друг под друга. */
.constructor { display: block; }

/* На узком экране колонок нет, и это не «то же самое в одну колонку».
   Сетка в один столбец давала каждому блоку свою строку, а липкий
   элемент прилипает только внутри своей строки — то есть дом уезжал
   за экран ровно тогда, когда человек добирался до склада блоков.
   Тащить становилось некуда: блок в руке, а дома не видно.

   Поэтому здесь flex-колонка: липкий дом держится за всю форму
   целиком и остаётся сверху, пока склад прокручивается под ним.
   Пояснения к цене при этом уходят в самый низ — они не должны стоять
   между домом и блоками. */
.constructor__form { display: flex; flex-direction: column; gap: var(--gap-5); }
.constructor__left, .constructor__right { display: contents; }
.total__notes { order: 5; }

@media (min-width: 1000px) {
  .constructor__form {
    display: grid;
    grid-template-columns: minmax(360px, 44%) 1fr;
    /* Колонки НЕ выравниваем по верху: при align-items: start левая
       колонка получает высоту своего содержимого, и липкий дом
       перестаёт держаться, как только она закончилась. А список блоков
       справа втрое длиннее — то есть у нижних блоков дом уже за экраном,
       и тащить их некуда. Растянутая колонка чинит это целиком. */
    align-items: stretch;
  }
  /* Колонок ровно две, и обе — прямые дети формы. Любой лишний блок
     на этом уровне уехал бы в чужую колонку и развалил раскладку. */
  .constructor__left, .constructor__right { display: block; min-width: 0; }
  .total__notes { order: 0; }
}

/* Дом «прилипает» и остаётся перед глазами, пока справа прокручивается
   склад блоков. Иначе тащить нечего: блок и цель не помещаются на экран
   одновременно. */
.house-panel {
  position: sticky; top: 68px; z-index: 20;
  background: var(--paper);
  padding-bottom: var(--gap-3);
}
@media (min-width: 1000px) {
  /* На широком экране колонка с домом прокручивается вместе со страницей
     до своего конца и там останавливается — так итог с ценой всегда виден
     рядом с блоками. */
  .house-panel { max-height: calc(100dvh - 84px); overflow: visible; }
}
@media (max-width: 999px) {
  /* Дом закреплён сверху, склад прокручивается под ним. Тащить недалеко:
     палец не идёт через весь экран — на телефоне это важнее любой
     анимации. */
  .house-panel {
    box-shadow: 0 12px 20px -18px rgba(35, 32, 29, .8);
    padding-top: var(--gap-2);
    margin-inline: calc(var(--gap-3) * -1);
    padding-inline: var(--gap-3);
  }
}

.house {
  position: relative;
  aspect-ratio: 5 / 4;
  max-height: 30dvh;
  margin-inline: auto;
  width: 100%;
  background:
    linear-gradient(to bottom, var(--surface-2) 0%, var(--paper-alt) 100%);
  border-radius: var(--radius-3);
  overflow: hidden;
}
@media (min-width: 1000px) { .house { max-height: none; aspect-ratio: 4 / 3; } }

@media (max-width: 999px) { .house { max-height: 24dvh; } }

/* Каждый элемент дома — свой слот. Пустой слот рисуется пунктиром:
   это и есть «правило честного отказа». Текст можно пролистать, дыру нельзя. */
.slot {
  position: absolute;
  display: grid; place-items: center;
  border-radius: 6px;
  transition: background .25s var(--ease), border-color .25s var(--ease), opacity .25s;
  font-size: var(--step--2);
  text-align: center;
  color: transparent;
}
/* Пустое место — тонкий контур, и только. Штриховка внутри каждого
   слота превращала недостроенный дом в кашу из серых коробок:
   вместо «здесь чего-то нет» читалось «здесь что-то сломалось». */
.slot.is-empty {
  background: none;
  border: 1.5px dashed color-mix(in srgb, var(--muted-2) 70%, transparent);
  color: var(--muted);
}
/* Положенный блок должен читаться как нарисованный от руки, а не как
   залитый прямоугольник. Ровная заливка на маленьком доме терялась:
   человек доносил стены и не понимал, изменилось что-нибудь или нет.
   Поэтому у каждой части своя штриховка и свой контур — и короткая
   анимация появления, чтобы момент постановки было видно. */
.slot.is-filled {
  border: 0;
  box-shadow: inset 0 0 0 2px var(--ink-2);
  animation: part-in .34s var(--ease) both;
}
@keyframes part-in {
  from { transform: scale(.88); opacity: 0; }
  to   { transform: none; opacity: 1; }
}

/* Только что положенный блок отбивается кольцом: на телефоне палец
   закрывает пол-дома, и без вспышки постановка проходит незамеченной. */
.slot.is-just-placed { animation: part-in .34s var(--ease) both, part-ring .7s var(--ease); }
@keyframes part-ring {
  0%   { outline: 3px solid var(--brand-500); outline-offset: 6px; }
  100% { outline: 3px solid transparent; outline-offset: 2px; }
}

/* Убрать блок — нажать на него в доме. Крестик показывает, что часть
   дома вообще можно трогать: без него вопрос «а как убрать обратно»
   остаётся без ответа. */
.slot.is-filled { cursor: pointer; }
.slot.is-filled::after {
  content: '×';
  position: absolute; top: 2px; right: 4px;
  font-size: var(--step-0); line-height: 1; font-weight: 700;
  color: var(--paper);
  text-shadow: 0 0 4px rgba(35, 32, 29, .55);
  opacity: 0; transition: opacity .18s var(--ease);
}
.slot.is-filled:hover::after, .slot.is-filled:focus-visible::after { opacity: 1; }
.house.is-receiving .slot.is-filled::after { opacity: 0; }

@media (prefers-reduced-motion: reduce) {
  .slot.is-filled, .slot.is-just-placed { animation: none; }
}
/* Куда можно положить — видно с момента, как блок взяли в руку,
   а не когда его уже поднесли. Иначе человек тащит наугад и решает,
   что перетаскивание не работает. */
.slot.is-available {
  border: 2px dashed var(--brand-400);
  background: color-mix(in srgb, var(--brand-500) 12%, transparent);
  animation: slot-pulse 1.2s var(--ease) infinite;
}
.slot.is-target {
  border-color: var(--brand-500);
  border-style: solid;
  background: color-mix(in srgb, var(--brand-500) 22%, transparent);
  box-shadow: 0 0 0 4px var(--brand-100);
  animation: none;
}
@keyframes slot-pulse {
  0%, 100% { opacity: .75; }
  50%      { opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .slot.is-available { animation: none; }
}

.house.is-receiving { outline: 2px dashed var(--brand-300); outline-offset: -4px; }
.house.is-receiving .house__hint { color: var(--brand-500); font-weight: 600; }

.slot[data-part="foundation"] { left: 6%; right: 6%; bottom: 4%; height: 9%; }
.slot[data-part="foundation"].is-filled {
  background:
    repeating-linear-gradient(90deg,
      transparent 0 13px, color-mix(in srgb, var(--paper) 45%, transparent) 13px 15px),
    var(--ink-2);
}

/* Стены — кирпичная кладка: вертикальные швы и ряды. Именно на стенах
   ровная заливка читалась хуже всего, а кладка видна сразу. */
.slot[data-part="walls"] { left: 12%; right: 12%; bottom: 13%; height: 38%; }
.slot[data-part="walls"].is-filled {
  background:
    repeating-linear-gradient(90deg,
      transparent 0 26px, color-mix(in srgb, var(--ink) 22%, transparent) 26px 28px),
    repeating-linear-gradient(0deg,
      transparent 0 13px, color-mix(in srgb, var(--ink) 22%, transparent) 13px 15px),
    var(--sand);
}

/* Фасад — штриховка по диагонали: так рисуют эскиз от руки. */
.slot[data-part="facade"] { left: 12%; right: 12%; bottom: 51%; height: 12%; }
.slot[data-part="facade"].is-filled {
  background:
    repeating-linear-gradient(-45deg,
      transparent 0 5px, color-mix(in srgb, var(--brand-600) 45%, transparent) 5px 7px),
    var(--brand-200);
}

.slot[data-part="finish"] { left: 12%; width: 7%; bottom: 13%; height: 38%; }
.slot[data-part="finish"].is-filled {
  background: repeating-linear-gradient(
    0deg, var(--brand-300), var(--brand-300) 5px, var(--brand-200) 5px, var(--brand-200) 10px);
}

/* Окна — переплёт крестом: без него светлый прямоугольник на стене
   ничего не обозначает. */
.slot[data-part="windows"] { left: 33%; width: 17%; bottom: 25%; height: 15%; }
.slot[data-part="windows"].is-filled {
  background:
    linear-gradient(var(--ink-2), var(--ink-2)) center / 2px 100% no-repeat,
    linear-gradient(var(--ink-2), var(--ink-2)) center / 100% 2px no-repeat,
    #cfe0e6;
}
.slot[data-part="windows"].has-light {
  background:
    linear-gradient(var(--ink-2), var(--ink-2)) center / 2px 100% no-repeat,
    linear-gradient(var(--ink-2), var(--ink-2)) center / 100% 2px no-repeat,
    #F6DFA0;
  box-shadow: inset 0 0 0 2px var(--ink-2), 0 0 26px rgba(246, 223, 160, .95);
}

/* Крыша — черепица штрихами по скату. Контур внутрь тут не нарисуешь:
   его срежет clip-path, поэтому линии делают всю работу. */
.slot[data-part="roof"] { left: 6%; right: 6%; bottom: 63%; height: 20%; }
.slot[data-part="roof"].is-filled {
  background:
    repeating-linear-gradient(90deg,
      transparent 0 14px, color-mix(in srgb, var(--ink) 28%, transparent) 14px 16px),
    var(--brand-500);
  clip-path: polygon(50% 0, 100% 100%, 0 100%);
  box-shadow: none;
}
.slot[data-part="roof"].is-filled::after { right: 8%; top: 46%; }

/* Труба: стоит на скате, а не висит сбоку. */
.slot[data-part="light"] { right: 22%; width: 6%; bottom: 66%; height: 14%; }
.slot[data-part="light"].is-filled { background: var(--ink-2); border-radius: 2px 2px 0 0; }

.slot[data-part="garden"] { right: 2%; width: 10%; bottom: 13%; height: 22%; }
.slot[data-part="garden"].is-filled { background: var(--ok); border-radius: 50% 50% 20% 20%; }
/* Сад — не дыра в доме, а необязательное украшение рядом с ним. Пунктир
   на его месте читался бы как поломка, а не как «этого нет». */
.slot[data-part="garden"].is-empty { background: none; border: 0; }

/* Итог всегда виден в момент постановки блока — иначе теряется весь смысл.
   Но именно поэтому он НЕ липкий сам по себе: липким внутри липкой панели
   он наезжал на дом и закрывал то, ради чего человек сюда пришёл.
   Панель целиком прилипает, а внутри неё дом и итог просто лежат друг
   под другом. */
.total {
  margin-top: var(--gap-3);
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius-3); padding: var(--gap-4);
  box-shadow: var(--shadow-1);
}
.total__row { display: flex; justify-content: space-between; gap: var(--gap-4); padding: var(--gap-2) 0; }
.total__row + .total__row { border-top: 1px solid var(--line-soft); }
.total__label { color: var(--muted); font-size: var(--step--1); }
.total__value { font-family: var(--font-display); font-weight: 800; letter-spacing: -.03em; font-size: var(--step-1); white-space: nowrap; }
.total__notes { margin-top: var(--gap-4); }
.total__notes .total__note { margin-top: var(--gap-3); }
.total__note { font-size: var(--step--2); color: var(--muted); margin-top: var(--gap-3); }
.total__row--grand { border-top: 2px solid var(--ink); margin-top: var(--gap-2); }
.total__row--grand .total__value { color: var(--brand-500); font-size: var(--step-2); }

/* Закреплённая панель обязана оставить место складу. Дом с итогом
   во весь экран — это дом, к которому нечего нести: блоки под ним
   просто не помещаются. Поэтому на телефоне итог ужимается до предела,
   а подписи-уточнения уходят вниз, в пояснения под складом.
   Стоять этот блок обязан ПОСЛЕ обычных правил .total: при равной
   силе побеждает последний, и написанный выше он бы просто не работал. */
@media (max-width: 999px) {
  .house__note { margin-top: var(--gap-1); }
  .total { padding: var(--gap-2) var(--gap-3); margin-top: var(--gap-2); }
  .total__row { padding: 2px 0; gap: var(--gap-3); }
  .total__label { font-size: var(--step--2); }
  .total__label .card__muted { display: none; }
  .total__value { font-size: var(--step--1); }
  .total__row--grand { margin-top: var(--gap-1); }
  .total__row--grand .total__value { font-size: var(--step-1); }
}

/* Склад блоков. */
.shelf { display: grid; gap: var(--gap-3); }
.shelf__group { display: grid; gap: var(--gap-2); }
.shelf__head { font-size: var(--step--1); color: var(--muted); text-transform: uppercase; letter-spacing: .12em; }

/* Взаимоисключающие блоки — крыша, окна, стены — сведены в рамку
   с заголовком. Без неё человек кладёт «выезды», видит крышу, кладёт
   «надзор» — снова крышу, и логика выглядит сломанной. */
.shelf__choice {
  border: 1px solid var(--line);
  border-radius: var(--radius-3);
  padding: var(--gap-4);
  background: var(--surface-2);
}
.shelf__choice-head { font-size: var(--step--1); font-weight: 700; margin-bottom: var(--gap-3); }

.block {
  /* touch-action: none только на самих блоках. Повесить его на контейнер —
     значит убить прокрутку всей страницы. */
  touch-action: none;
  user-select: none;
  -webkit-touch-callout: none;
  position: relative;
  display: grid; grid-template-columns: auto 1fr auto; gap: var(--gap-3); align-items: center;
  padding: var(--gap-4);
  min-height: 56px;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius-2);
  cursor: grab;
  transition: border-color .18s var(--ease), background .18s var(--ease), box-shadow .18s var(--ease);
}
.block:hover { border-color: var(--brand-300); box-shadow: var(--shadow-1); }
.block.is-selected { border-color: var(--brand-500); background: var(--brand-50); }
.block.is-required { cursor: default; opacity: .85; }

.block__grip { width: 18px; color: var(--muted-2); line-height: 1; letter-spacing: 2px; }
.block__title { font-weight: 600; min-width: 0; }
.block__price { font-size: var(--step--1); color: var(--muted); white-space: nowrap; }

/* На узком экране цена в третьей колонке не переносится и не сжимается —
   и весь склад уезжал за правый край экрана вместе с домом. Поэтому
   на телефоне цена встаёт под названием отдельной строкой. */
@media (max-width: 560px) {
  .block { grid-template-columns: auto 1fr; }
  .block__price { grid-column: 2; white-space: normal; }
}

/* --- Группа вариантов: один блок вместо трёх --------------------------- */

.block--group { align-items: start; }
/* Цена активного варианта нужна только в руке: на складе её показывают
   строки переключателя. */
.block--group > .block__price { display: none; }

.block__variants {
  grid-column: 1 / -1;
  display: grid; gap: var(--gap-2);
  margin-top: var(--gap-2);
}

.variant {
  font: inherit; text-align: left; cursor: pointer;
  display: grid; grid-template-columns: 18px 1fr auto; gap: var(--gap-3);
  align-items: center;
  min-height: 44px; padding: var(--gap-2) var(--gap-3);
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius-2); color: var(--ink-2);
  transition: border-color .18s var(--ease), background .18s var(--ease);
}
.variant:hover { border-color: var(--brand-300); }
.variant__mark {
  width: 16px; height: 16px; border-radius: 50%;
  border: 2px solid var(--muted-2); flex: none;
}
.variant.is-active { border-color: var(--brand-500); background: var(--brand-50); color: var(--ink); }
.variant.is-active .variant__mark {
  border-color: var(--brand-500);
  box-shadow: inset 0 0 0 3px var(--paper), inset 0 0 0 9px var(--brand-500);
}
.variant__title { font-size: var(--step--1); font-weight: 600; }
.variant__price { font-size: var(--step--2); color: var(--muted); }
@media (max-width: 560px) {
  .variant { grid-template-columns: 18px 1fr; }
  .variant__price { grid-column: 2; }
}

.block__hint {
  grid-column: 1 / -1;
  font-size: var(--step--2); color: var(--muted);
  margin-top: var(--gap-2);
}

/* Без JavaScript перетаскивания нет, и галочки перестают быть скрытыми:
   иначе обещание «страница работает без JS» пустое — отмечать было бы
   нечего, а кнопка «Пересчитать» ничего бы не считала. */
.no-js .block__check {
  position: static; width: auto; height: auto; overflow: visible;
  clip: auto; clip-path: none; white-space: normal;
  grid-column: 1 / -1; font-size: var(--step--1); color: var(--ink-2);
}
.no-js .block__check[type="checkbox"] { width: 22px; height: 22px; }
.no-js .block { cursor: default; }
.block__more {
  grid-column: 1 / -1; font-size: var(--step--1); color: var(--ink-2);
  border-top: 1px solid var(--line-soft); padding-top: var(--gap-3); margin-top: var(--gap-2);
}
.block__more[hidden] { display: none; }

/* «Подробнее» — отдельной строкой во всю ширину. Иначе кнопка встаёт
   в первую колонку сетки и растягивает её на свою ширину: название
   блока отъезжает от края и висит посреди карточки. */
.block > .clause__toggle { grid-column: 1 / -1; justify-self: start; }

/* Блок в руке: приподнят над пальцем на 56px, иначе человек тащит то,
   чего не видит. Позиционирование только трансформом — layout не трогаем. */
.block--dragging {
  position: fixed; left: 0; top: 0; z-index: 60;
  /* Ширину клона ограничиваем: карточка блока во всю колонку, поднятая
     под курсор, закрывает пол-экрана вместе с домом, куда её несут. */
  width: min(var(--drag-width, 260px), 300px);
  pointer-events: none;
  box-shadow: var(--shadow-lift);
  border-color: var(--brand-500);
  transform: translate3d(0, 0, 0) scale(1.05);
}
/* В руке от блока нужны название и цена. Переключатель формата
   и пояснения делают карточку в полэкрана — она закрывает ровно тот дом,
   к которому её несут. */
.block--dragging .block__variants,
.block--dragging .block__hint,
.block--dragging .clause__toggle { display: none; }
.block--dragging.block--group > .block__price { display: inline; }
.block--ghost { opacity: .35; }

.house__hint {
  position: absolute; inset-inline: 0; top: var(--gap-3);
  text-align: center; font-size: var(--step--2); color: var(--muted);
  pointer-events: none;
}
.house__note {
  text-align: center; font-size: var(--step--2); color: var(--muted);
  margin-top: var(--gap-2);
}

.warnings { display: grid; gap: var(--gap-3); margin-top: var(--gap-4); }
.warning {
  background: var(--warn-bg); color: var(--warn);
  border-radius: var(--radius-2); padding: var(--gap-3) var(--gap-4);
  font-size: var(--step--1);
}
.warning strong { display: block; }

.presets { display: flex; flex-wrap: wrap; gap: var(--gap-2); }
.preset {
  font: inherit; font-size: var(--step--1); cursor: pointer;
  padding: var(--gap-2) var(--gap-4); min-height: 44px;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-pill);
  color: var(--ink);
}
.preset.is-active { background: var(--brand-500); border-color: var(--brand-500); color: #fff; }

/* --- Куки ----------------------------------------------------------------- */

.cookies {
  position: fixed; z-index: 50; left: var(--gap-4); right: var(--gap-4); bottom: var(--gap-4);
  display: grid; gap: var(--gap-4);
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius-3); padding: var(--gap-5);
  box-shadow: var(--shadow-2);
  max-width: 620px; margin-inline: auto;
  font-size: var(--step--1);
}
.cookies__actions { display: flex; flex-wrap: wrap; gap: var(--gap-3); }
.cookies__actions .btn { flex: 1 1 200px; }
.cookies__link { margin: 0; }

/* --- Подвал --------------------------------------------------------------- */

.footer { background: var(--paper-alt); border-top: 1px solid var(--line); padding: var(--gap-7) 0 var(--gap-6); margin-top: var(--gap-8); }
.footer__inner { display: grid; gap: var(--gap-6); grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); }
.footer__col a { display: block; color: var(--ink-2); text-decoration: none; padding: var(--gap-1) 0; font-size: var(--step--1); }
.footer__col a:hover { color: var(--brand-500); }
.footer__name { font-family: var(--font-display); font-weight: 800; font-size: var(--step-1); letter-spacing: -.03em; margin-bottom: var(--gap-1); }
.footer__head { font-size: var(--step--2); text-transform: uppercase; letter-spacing: .12em; color: var(--muted); margin-bottom: var(--gap-3); }
.footer__muted { color: var(--muted); font-size: var(--step--1); margin-bottom: var(--gap-1); }

/* Подпись автора: тише всего остального в подвале. */
.author {
  margin-top: var(--gap-6); padding-top: var(--gap-4);
  border-top: 1px solid var(--line);
  font-size: var(--step--2); color: var(--muted-2);
}
.author a {
  color: var(--muted); text-decoration: none;
  font-weight: 700; letter-spacing: .06em;
  border-bottom: 1px solid var(--line);
  transition: color .18s var(--ease), border-color .18s var(--ease);
}
.author a:hover { color: var(--brand-500); border-color: var(--brand-300); }
.author__sub { color: var(--muted-2); }

/* --- КП, договор, счёт ---------------------------------------------------- */

.doc { max-width: 78ch; }
.doc h2 { margin-top: var(--gap-6); }
.doc ul { padding-left: 1.1em; }

.clause { padding: var(--gap-4) 0; border-bottom: 1px solid var(--line-soft); }
.clause.is-important { border-left: 3px solid var(--brand-500); padding-left: var(--gap-4); background: var(--brand-50); border-radius: 0 var(--radius-2) var(--radius-2) 0; }
.clause__num { font-weight: 700; color: var(--brand-500); }
.clause__plain { background: var(--surface-2); border-radius: var(--radius-2); padding: var(--gap-4); margin-top: var(--gap-3); color: var(--ink-2); }
.clause__plain[hidden] { display: none; }
.clause__toggle { background: none; border: 0; color: var(--brand-500); font: inherit; font-size: var(--step--1); cursor: pointer; padding: var(--gap-2) 0; text-decoration: underline; }

.summary-lines { display: grid; gap: var(--gap-2); }
.summary-line { display: flex; justify-content: space-between; gap: var(--gap-4); padding: var(--gap-2) 0; border-bottom: 1px solid var(--line-soft); }
