/* ============================================================
   Я зову — корзина и оплата
   ------------------------------------------------------------
   Корзина — единственное место, где средний чек растёт без
   единого лишнего визита. У evyt.ru здесь пусто: две цены,
   ноль допродаж, AOV зафиксирован на 135 ₽. Поэтому order bump
   тут не украшение, а основная функция страницы.
   ============================================================ */

.shop{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,20rem);gap:2.5rem;padding:1.6rem 0 3rem}
.shop h1{font-size:clamp(1.7rem,3.6vw,2.3rem);margin:0 0 1.3rem}

/* ---------- позиция заказа ---------- */
.line{display:grid;grid-template-columns:5.5rem minmax(0,1fr) auto;gap:1.1rem;padding:1.2rem 0;border-top:1px solid var(--rule)}
.line:first-of-type{border-top:0;padding-top:0}
.line .thumb{width:5.5rem}
.line .thumb .yz-inv{border:1px solid var(--rule);box-shadow:var(--shadow-s)}
.line h2{font-family:var(--sans);font-size:1.02rem;font-weight:600;margin:0 0 .2rem;line-height:1.3}
.line .tier{font-size:.86rem;color:var(--brand);font-weight:500;margin:0 0 .35rem}
.line ul{margin:0;padding:0;list-style:none;font-size:.85rem;color:var(--ink-2);display:flex;flex-direction:column;gap:.15rem}
.line li::before{content:"· ";color:var(--brand)}
/* Три подписи в ряд без переноса: на узком телефоне (320–360)
   «Убрать» уезжала за край экрана вместе со страницей. Строка
   ссылок — не таблица, переносить её нечем не жалко. */
.line .acts{display:flex;flex-wrap:wrap;gap:.5rem .8rem;margin-top:.5rem;font-size:.84rem}
.line .acts a,.line .acts button{background:none;border:0;padding:0;color:var(--ink-2);cursor:pointer;text-decoration:underline}
.line .acts a:hover,.line .acts button:hover{color:var(--brand)}
.line .price{font-family:var(--serif);font-size:1.3rem;font-weight:600;white-space:nowrap;text-align:right}

/* ---------- допродажи ---------- */
.bumps{margin:2rem 0 0}
.bumps h2{font-family:var(--sans);font-size:.74rem;letter-spacing:.1em;text-transform:uppercase;color:var(--ink-3);font-weight:500;margin:0 0 .7rem}
.bump{
  display:grid;grid-template-columns:1.1rem 1fr auto;gap:.8rem;align-items:start;
  border:1px solid var(--rule);background:var(--card);padding:.85rem 1rem;margin:0 0 .6rem;cursor:pointer;
}
.bump:hover{border-color:var(--rule-2)}
.bump:has(input:checked){border-color:var(--brand);background:var(--brand-soft)}
.bump input{margin:.2rem 0 0;accent-color:var(--brand);width:1rem;height:1rem}
.bump b{display:block;font-size:.95rem;font-weight:600}
.bump small{display:block;color:var(--ink-2);font-size:.85rem;margin-top:.12rem}
.bump .plus{font-family:var(--serif);font-size:1.05rem;font-weight:600;white-space:nowrap}
.bump .free{color:var(--good-ink);font-family:var(--sans);font-size:.85rem;font-weight:500}

/* ---------- пустая корзина ---------- */
.cart-empty{
  border:1px dashed var(--rule-2);border-radius:12px;
  padding:2rem 1.4rem;text-align:center;margin:1rem 0 0;
}
.cart-empty h2{font-family:var(--serif);font-size:1.35rem;margin:0 0 .4rem}
.cart-empty p{margin:0 0 .3rem;color:var(--ink-2);font-size:.95rem}
.ce-acts{display:flex;gap:.6rem;justify-content:center;flex-wrap:wrap;margin-top:1rem !important}

/* Кнопка оплаты в пустой корзине — на месте, но погашена.
   Исчезнувшая кнопка заставляет искать, куда она делась. */
.sum .btn.is-off{opacity:.45;pointer-events:none}

/* ---------- сводка ---------- */
/* ПОЧЕМУ ЗДЕСЬ ALIGN-SELF, А НЕ ТОЛЬКО STICKY

   position:sticky тут стоял с самого начала и не работал: ячейка
   грида по умолчанию растягивается на всю высоту строки, и липкому
   элементу просто некуда липнуть — он и так занимает всю колонку.
   Выглядело это как «закрепление не сделали», хотя строка была.

   align-self:start сжимает ячейку по содержимому — и сводка
   начинает ехать за прокруткой. Ради этого всё и затевалось:
   на длинной корзине кнопка «Перейти к оплате» иначе остаётся
   где-то вверху, и до неё надо возвращаться. */
.sum{
  position:sticky;top:76px;align-self:start;
  border:1px solid var(--rule);background:var(--card);padding:1.2rem 1.25rem;
  /* Сводка длиннее экрана не должна обрезать кнопку оплаты:
     тогда прокручивается она сама. */
  max-height:calc(100svh - 88px);overflow:auto;
}
.sum h2{font-family:var(--serif);font-size:1.25rem;margin:0 0 .9rem}
.sum .row{display:flex;justify-content:space-between;gap:1rem;font-size:.92rem;padding:.3rem 0;color:var(--ink-2)}
.sum .row span:last-child{color:var(--ink);font-variant-numeric:tabular-nums;white-space:nowrap}
.sum .row.off span:last-child{color:var(--good-ink)}
.sum .total{display:flex;justify-content:space-between;align-items:baseline;border-top:1px solid var(--rule);margin-top:.7rem;padding-top:.8rem}
.sum .total b{font-family:var(--serif);font-size:2rem;font-weight:600;font-variant-numeric:tabular-nums}

/* «Разовый платёж» — между суммой и кнопкой.

   Зелёная галочка, а не бренд: это снятие возражения, а не
   предложение. Малиновым здесь набрана кнопка, и вторая
   малиновая строка рядом с ней спорит с ней за внимание. */
.sum-once{
  display:flex;gap:.42rem;align-items:flex-start;
  margin:.7rem 0 .85rem;font-size:.83rem;line-height:1.4;color:var(--ink-2);
}
.sum-once svg{
  width:.95rem;height:.95rem;flex:none;margin-top:.15rem;
  fill:none;stroke:var(--good);stroke-width:2.4;stroke-linecap:round;stroke-linejoin:round;
}
.sum .btn{width:100%;margin-top:.9rem}

/* ============================================================
   Кнопка «Перейти к оплате»
   ------------------------------------------------------------
   Единственное действие на экране корзины, и вокруг него четыре
   галочки допродаж, которые перетягивают внимание. Поэтому кнопка
   не стоит молча: раз в несколько секунд по ней проходит блик.

   Движение намеренно редкое и короткое. Пульсация или подпрыгивание
   на кнопке оплаты читаются как давление и работают против доверия —
   а здесь как раз момент, когда человек решает, отдавать ли деньги.
   Блик только сообщает «я живая и я тут главная».
   ============================================================ */
#payBtn{position:relative;overflow:hidden;isolation:isolate}
#payBtn::after{
  content:"";position:absolute;inset:0;z-index:-1;
  background:linear-gradient(105deg,transparent 35%,rgba(255,255,255,.42) 50%,transparent 65%);
  transform:translateX(-120%);
  animation:pay-shine 4.5s cubic-bezier(.3,0,.2,1) 1.2s infinite;
}
@keyframes pay-shine{
  0%{transform:translateX(-120%)}
  /* сам блик занимает пятую часть цикла, остальное — пауза */
  22%,100%{transform:translateX(120%)}
}
/* нажали — движение прекращается: решение принято, подгонять больше некого */
#payBtn:active::after,#payBtn.is-going::after{animation:none;opacity:0}
#payBtn{transition:transform .16s ease,box-shadow .16s ease}
#payBtn:hover{transform:translateY(-1px);box-shadow:var(--shadow-m)}
#payBtn:active{transform:translateY(0)}
@media (prefers-reduced-motion:reduce){#payBtn::after{display:none}}
/* ПОЛЕ ПРОМОКОДА ЗАДАВАЛО ШИРИНУ ВСЕЙ СТРАНИЦЕ

   У <input type="text"> есть врождённая ширина — около двадцати
   знаков, — и она считается минимальной шириной содержимого
   строки. Вместе с «Применить» и зазором это 373 точки: больше,
   чем экран телефона на 320 и на 360.

   min-width:0 здесь стоял с самого начала и от этого не спасает:
   он снимает автоминимум флекс-элемента, а врождённую ширину
   учитывает расчёт min-content у РОДИТЕЛЯ — то есть сводки. И
   дальше неважно, растянута сводка или считает себя по
   содержимому: 373 точки не влезают в экран ни так, ни этак, и
   лишнее просто вылезает наружу. Вбок ехала вся страница
   корзины: на 360 — на 26 точек, на 320 — на 66.

   Поэтому: строка умеет переноситься, а поле — сжиматься до
   7rem. Ниже 7rem промокод набирать неудобно, и тогда кнопка
   честно уходит на вторую строку. */
.promo{display:flex;flex-wrap:wrap;gap:.4rem;margin:.9rem 0 0}
.promo input{flex:1 1 7rem;min-width:0;font-family:var(--sans);font-size:.88rem;padding:.45rem .6rem;border:1px solid var(--rule-2);background:var(--paper);border-radius:2px;color:var(--ink)}
/* «Применить» рядом с полем промокода: была 38 точек. */
.promo button{background:transparent;border:1px solid var(--rule-2);border-radius:2px;
  padding:.45rem .8rem;font-size:.86rem;cursor:pointer;color:var(--ink-2);
  min-height:44px}
.promo button:hover{border-color:var(--brand);color:var(--brand)}
.promo-msg{font-size:.82rem;margin:.4rem 0 0;min-height:1.1rem}
.promo-msg.ok{color:var(--good-ink)}
.promo-msg.err{color:var(--brick)}
.fine{margin:.9rem 0 0;font-size:.82rem;color:var(--ink-3);display:flex;flex-direction:column;gap:.25rem}
.fine b{color:var(--ink-2);font-weight:500}

/* ---------- оплата ---------- */
.pay-field{margin:0 0 1.2rem}
.pay-field label{display:block;font-size:.74rem;letter-spacing:.05em;text-transform:uppercase;color:var(--ink-3);margin:0 0 .25rem}
.pay-field input{
  font-family:var(--sans);font-size:1rem;padding:.65rem .7rem;width:100%;
  background:var(--card);border:1px solid var(--rule-2);border-radius:2px;color:var(--ink);
}
.pay-field .hint{font-size:.83rem;color:var(--ink-3);margin:.3rem 0 0}
.methods{display:grid;gap:.5rem;margin:0 0 1.2rem}
.methods label{
  display:grid;grid-template-columns:1.1rem 1fr auto;gap:.8rem;align-items:center;
  border:1px solid var(--rule);background:var(--card);padding:.75rem .9rem;cursor:pointer;
}
.methods label:has(input:checked){border-color:var(--brand);background:var(--brand-soft)}
.methods input{accent-color:var(--brand);width:1rem;height:1rem}
.methods b{font-weight:500;font-size:.95rem}
.methods small{display:block;color:var(--ink-2);font-size:.83rem}
.methods .tagline{font-size:.76rem;color:var(--ink-3);letter-spacing:.04em;text-transform:uppercase}
.consent{display:flex;gap:.65rem;align-items:flex-start;font-size:.87rem;color:var(--ink-2);margin:0 0 1.2rem}
.consent input{margin:.2rem 0 0;accent-color:var(--brand);width:1rem;height:1rem;flex:none}
.consent a{color:var(--ink-2)}

.after{display:grid;grid-template-columns:repeat(auto-fit,minmax(12rem,1fr));gap:1.2rem}
.after div h3{margin:0 0 .25rem;font-size:.97rem;font-weight:600}
.after div p{margin:0;font-size:.9rem;color:var(--ink-2)}
.after .n{font-family:var(--serif);font-size:1.5rem;color:var(--brand);font-weight:600;line-height:1;display:block;margin-bottom:.35rem}

/* ---------- успешная оплата ---------- */
.paid{max-width:34rem;margin:0 auto;text-align:center;padding:1rem 0 0}
.paid .tick{width:3rem;height:3rem;border-radius:50%;background:var(--good-ink);color:var(--paper);display:grid;place-items:center;font-size:1.5rem;margin:0 auto 1rem}
.paid h1{font-size:2rem;margin:0 0 .4rem}
.paid > p{margin:0 0 1.6rem;color:var(--ink-2)}
.files{display:flex;flex-direction:column;gap:.5rem;text-align:left;margin:0 0 1.2rem}
.file{display:grid;grid-template-columns:3.2rem 1fr auto;gap:.9rem;align-items:center;border:1px solid var(--rule);background:var(--card);padding:.8rem .95rem}
.file .ext{font-family:var(--serif);font-size:1rem;font-weight:600;color:var(--brand)}
.file b{display:block;font-size:.94rem;font-weight:500}
.file small{display:block;color:var(--ink-3);font-size:.82rem}
.file .go{font-size:.86rem;color:var(--ink-2);text-decoration:underline;background:none;border:0;cursor:pointer}
.file .go:hover{color:var(--brand)}
.linkbox{display:flex;gap:.4rem;margin:0 0 1.4rem}
.linkbox input{flex:1;min-width:0;font-family:var(--sans);font-size:.9rem;padding:.55rem .7rem;border:1px solid var(--rule-2);background:var(--card);color:var(--ink);border-radius:2px}
.paid .btn{margin:0 .3rem}

@media (max-width:820px){
  /* minmax(0,…), а не голый 1fr.

     Голый «1fr» — это minmax(auto,1fr), и его нижняя граница —
     минимальная ширина содержимого. У сводки внутри поле промокода
     со своей врождённой шириной, и колонка отказывалась сжиматься
     до экрана: страница ехала вбок на тридцать четыре пикселя,
     причём на всех трёх экранах магазина сразу. */
  .shop{grid-template-columns:minmax(0,1fr);gap:1.8rem}
  /* align-self:start СУЩЕСТВУЕТ ТОЛЬКО РАДИ STICKY

     Он сжимает ячейку по содержимому, чтобы липкой сводке было
     куда липнуть (почему — написано у самого правила). Здесь
     sticky выключен, а align-self оставался — и сводка
     продолжала считать себя по содержимому: в колонке fit-content
     означает «по содержимому, но не шире места».

     На телефоне содержимого хватало, чтобы занять всю ширину, и
     разницы не было видно. А на планшете и в половине окна
     (до 820 точек макет однополосный) сводка вставала шириной
     545 из 800: позиция над ней во всю страницу, а «Перейти к
     оплате» — на четверть уже всего остального. Выглядит как
     недогрузившийся блок.

     Свойство, поставленное ради одного режима, обязано
     выключаться вместе с этим режимом. Обе строки — про одно и
     то же, и стоят рядом.

     Отдельно: боком страница ехала НЕ из-за этой строки. Первая
     догадка была именно такой, и замер её опроверг — виновато
     было поле промокода, см. .promo выше. Проверка uzko меряет
     оба свойства порознь, чтобы догадка больше не подменяла
     причину. */
  .sum{position:static;max-height:none;overflow:visible;align-self:stretch}
  .line{grid-template-columns:4.5rem minmax(0,1fr);grid-template-areas:"t b" "p p"}
  .line .thumb{grid-area:t;width:4.5rem}
  .line .body{grid-area:b;min-width:0}
  .line .price{grid-area:p;text-align:left}
}


/* ============================================================
   Главная допродажа в корзине
   ------------------------------------------------------------
   Это не «ещё одна галочка», а переход на другой тариф, и вес
   у неё должен быть другой. В ряду одинаковых строк предложение
   пролистывают: глаз считает их списком мелочей и ищет кнопку
   оплаты. Поэтому у блока свой заголовок, свой список выгод
   и рамка акцентного цвета.

   ПОЧЕМУ ДВА ПЕРЕКЛЮЧАТЕЛЯ, А НЕ ГАЛОЧКА

   Галочка «добавить за +341 ₽» оставляет отказ невидимым: не
   отметил — и не понял, что выбрал. Дальше человек идёт к оплате
   с ощущением, что где-то его дожали. Два переключателя рядом
   показывают обе цены и обе строки одинаково, и выбран тот,
   который человек уже сделал на витрине.

   Отказ поэтому набран тем же кеглем и той же насыщенностью,
   что и согласие. Разница только в акцентном цвете выбранного —
   она показывает, что выбрано, а не что правильно.
   ============================================================ */
.bump-main{
  position:relative;overflow:hidden;
  border:1px solid color-mix(in srgb, var(--brand) 34%, transparent);
  background:
    radial-gradient(circle at 96% -6%, color-mix(in srgb, var(--brand) 11%, transparent) 0 7rem, transparent 7.05rem),
    color-mix(in srgb, var(--brand) 5%, var(--paper));
  border-radius:14px;
  padding:1.35rem 1.35rem 1.2rem;
  margin:0;
}

/* Настоящие переключатели формы. Они и есть состояние — кнопка
   ниже только щёлкает по ним, а расчёт итога читает их же.
   Прятать через display:none нельзя: скрытый так элемент
   выпадает из последовательности фокуса, и форма перестаёт
   работать с клавиатуры. */
/* .bm-hidden прячется общим правилом в base.css. */

.bm-head{display:flex;align-items:flex-start;justify-content:space-between;gap:1.2rem}
.bm-eyebrow{
  display:inline-flex;align-items:center;gap:.35rem;
  margin:0 0 .35rem;color:var(--brand);font-size:.8rem;font-weight:600;
}
.bm-eyebrow svg{width:1.05rem;height:1.05rem;fill:currentColor}
.bump-main h2{
  font-family:var(--serif);font-size:clamp(1.35rem,3vw,1.72rem);font-weight:600;
  letter-spacing:0;text-transform:none;color:var(--ink);margin:0;line-height:1.15;
}
.bm-lead{margin:.45rem 0 0;font-size:.95rem;line-height:1.5;color:var(--ink-2);max-width:34rem}

.bm-phone{
  flex:none;display:grid;place-items:center;width:3.1rem;height:3.1rem;
  border-radius:1rem;background:var(--card);color:var(--brand);
  box-shadow:var(--shadow-m);
}
.bm-phone svg{width:1.5rem;height:1.5rem;fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round}

/* Четыре выгоды в две колонки: столбец из четырёх строк читается
   как список дел, сетка два на два — как набор свойств. */
.bm-grid{
  display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:.6rem 1.2rem;
  margin:1.15rem 0;padding:0;list-style:none;
}
.bm-grid li{display:flex;align-items:center;gap:.55rem;font-size:.88rem;line-height:1.35;color:var(--ink)}
.bm-ic{
  flex:none;display:grid;place-items:center;width:1.6rem;height:1.6rem;
  border-radius:.5rem;background:var(--card);color:var(--brand);
  font-size:.82rem;font-weight:700;
}

.bm-act{
  display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:1rem;
  padding:.85rem .95rem;border:1px solid transparent;border-radius:11px;
  background:var(--card);box-shadow:var(--shadow-m);
  transition:border-color .2s ease;
}
.bm-plan{display:block;margin-bottom:.15rem;color:var(--ink-2);font-size:.8rem}
.bm-nums{display:flex;align-items:baseline;gap:.5rem}
.bm-nums b{font-family:var(--serif);font-size:1.55rem;font-weight:600;line-height:1;color:var(--brand)}
.bm-nums small{color:var(--ink-2);font-size:.8rem}

.bm-btn{
  min-height:2.9rem;padding:0 1.25rem;border:0;border-radius:9px;
  /* Допродажа: нажатие стоит 341 ₽. Красной она стояла рядом
     с «Перейти к оплате» — то есть доплата выглядела как
     «продолжить». См. tokens.css, роли кнопок. */
  background:var(--up-soft);color:var(--up-ink);box-shadow:inset 0 0 0 1px var(--up-ink);
  font:inherit;font-size:.95rem;font-weight:600;
  cursor:pointer;transition:background .18s ease,transform .18s ease,opacity .18s ease;
}
.bm-btn:hover:not(:disabled){background:var(--up-soft);transform:translateY(-1px);
  box-shadow:inset 0 0 0 1px var(--up-ink), 0 0 0 3px color-mix(in srgb, var(--up-ink) 18%, transparent)}
.bm-btn:disabled{cursor:default;transform:none}

.bm-safe{
  display:flex;align-items:center;gap:.4rem;
  margin:.65rem .15rem 0;color:var(--ink-2);font-size:.78rem;line-height:1.4;
}
.bm-safe svg{
  flex:none;width:1rem;height:1rem;fill:none;stroke:var(--good);
  stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round;
}
.bm-err{margin:.7rem 0 0;color:var(--brick);font-size:.85rem}

/* ---------- базовый тариф: он же видимый отказ ---------- */
.bm-base{
  display:grid;grid-template-columns:1.5rem 1fr auto;align-items:center;gap:.75rem;
  width:100%;margin:.6rem 0 0;padding:.8rem .95rem;text-align:left;
  border:1px solid var(--rule);border-radius:11px;background:var(--card);
  font:inherit;color:inherit;cursor:pointer;
  transition:border-color .2s ease,opacity .2s ease;
}
.bm-base:hover{border-color:var(--rule-2)}
.bm-base b{display:block;font-size:.92rem;font-weight:600}
.bm-base small{display:block;color:var(--ink-2);font-size:.8rem;margin-top:.08rem}
.bm-base-price{font-family:var(--serif);font-size:1.15rem;font-weight:600;white-space:nowrap}
.bm-dot{
  flex:none;width:1.5rem;height:1.5rem;border-radius:50%;
  border:1.5px solid var(--ink-3);display:grid;place-items:center;
}
.bm-dot::after{content:"";width:.72rem;height:.72rem;border-radius:50%;background:transparent;transition:background .18s ease}
.bump-main[data-plan="file"] ~ .bm-base .bm-dot{border-color:var(--brand)}
.bump-main[data-plan="file"] ~ .bm-base .bm-dot::after{background:var(--brand)}

/* ---------- «Праздник» добавлен ---------- */
.bump-main[data-plan="party"] .bm-act{border-color:color-mix(in srgb, var(--good) 45%, transparent)}
/* Доплата гаснет: она уже уплачена решением. Оставить её самым
   ярким пятном экрана значит продолжать продавать то, что человек
   только что купил. */
.bump-main[data-plan="party"] .bm-nums b{color:var(--ink-2)}
.bump-main[data-plan="party"] .bm-btn{
  background:var(--good-soft);color:var(--good-ink);transform:none;
}
.bump-main[data-plan="party"] ~ .bm-base{opacity:.86}

/* Пока идёт запрос — не даём нажать второй раз. Дубли запросов
   не столько ломают сумму (её всё равно считает сервер), сколько
   создают гонку ответов: последним приходит не последний. */
.bump-main.is-busy .bm-btn{opacity:.6}
.bump-main.is-busy .bm-btn,
.bump-main.is-busy ~ .bm-base{pointer-events:none}

@media (max-width:600px){
  .bump-main{padding:1.1rem 1rem}
  .bm-phone{display:none}
  .bm-grid{grid-template-columns:1fr;gap:.5rem;margin:1rem 0}
  .bm-act{grid-template-columns:1fr;gap:.75rem}
  .bm-btn{width:100%}
}

/* Бесплатные настройки файла — тише допродаж: у них другая
   задача и другая цена, и одинаковый вид смазывает разницу.
   Отмеченная заранее галочка тем более не должна светиться
   акцентом: она ничего не продаёт и ничего не меняет в сумме. */
.bumps-free{margin-top:1.4rem}
.bumps-free .bump,
.bumps-free .bump:has(input:checked){background:transparent;border-color:var(--rule)}

/* На узком экране цена справа съедает половину строки, и заголовок
   в оставшейся половине ломается пополам. Цена уходит под текст:
   читается тем же порядком, каким читают вслух — сначала что, потом
   сколько. */
@media (max-width:520px){
  .bm-opt,.bump{grid-template-columns:1.1rem 1fr;row-gap:.35rem}
  .bm-opt .plus,.bump .plus,.bump .free{grid-column:2;justify-self:start}
}

/* ---------- оформление ---------- */
.co-err{
  margin:0 0 1.2rem;padding:.75rem .9rem;border-radius:8px;
  background:color-mix(in srgb, var(--bad, #B23A2E) 10%, transparent);
  border:1px solid color-mix(in srgb, var(--bad, #B23A2E) 35%, transparent);
  font-size:.92rem;
}
.co-agree{display:flex;gap:.6rem;align-items:flex-start;margin:1rem 0 1.2rem;font-size:.9rem;line-height:1.45}
.co-agree input{margin-top:.25rem;flex:none;accent-color:var(--brand)}
.line-who{margin:0 0 .3rem;font-size:.9rem;color:var(--ink-2)}

/* ============================================================
   320 пикселей
   ------------------------------------------------------------
   Самый узкий экран, который ещё встречается: старый iPhone SE
   и любой телефон, у которого страницу открыли в половине
   разделённого экрана. Колонка «1fr» без minmax(0,…) не сжимается
   ниже собственного минимума, и строка заказа выдавливала страницу
   на тридцать пикселей вбок — вся страница ехала горизонтально.
   ============================================================ */
@media (max-width:360px){
  .shell{padding:0 .85rem}
  .line{gap:.75rem}
  .bump-main{padding:.95rem .85rem}
  .bm-base{padding:.7rem .8rem;gap:.6rem}
  .bm-nums b{font-size:1.35rem}
}

/* ============================================================
   Вторая допродажа тише первой
   ------------------------------------------------------------
   Именной тираж стоит дороже приглашения, и набранный тем же
   кеглем он перетягивает внимание с того, что мы предлагаем
   на самом деле. Ему хватает одной строки: кто её ждёт, тот
   её увидит, а остальным она не мешает выбирать тариф.
   ============================================================ */
.bumps > .bump{
  border-style:dashed;
}
.bumps > .bump b{font-weight:600;font-size:.9rem;color:var(--ink-2)}
.bumps > .bump:has(input:checked) b{color:var(--ink)}
.bumps > .bump .plus{font-family:var(--sans);font-size:.92rem;font-weight:600;color:var(--ink-2)}
.bumps > .bump:has(input:checked) .plus{color:var(--brand)}

/* ---------- похожие дизайны ---------- */
.sim-sec{border-bottom:0;padding:2.4rem 0 0}
.similar{display:grid;grid-template-columns:repeat(auto-fill,minmax(9rem,1fr));gap:1.1rem}
.similar a{text-decoration:none;display:flex;flex-direction:column;gap:.4rem;color:inherit}
.sim-name{font-size:.88rem}
.sim-price{font-size:.84rem;color:var(--ink-2)}

/* ============================================================
   Порядок колонок на телефоне
   ------------------------------------------------------------
   Сводка и «Перейти к оплате» лежат во второй колонке грида и на
   узком экране оказываются ниже всего: товар, допродажа, тираж,
   метки реза, три рекомендации — и только потом кнопка.

   Человек, уже решивший купить, не должен пролистывать чужие
   дизайны, чтобы дойти до оплаты. Разбираем левую колонку на
   части и ставим сводку между допродажей и рекомендациями.
   ============================================================ */
@media (max-width:820px){
  .shop{display:flex;flex-direction:column}
  .shop > div{display:contents}
  .shop .sum{order:3}
  .shop .sim-sec{order:4;padding-top:1.8rem}
}

/* ---------- список имён в позиции тиража ---------- */
.line-names{margin:.4rem 0 0;font-size:.86rem}
.line-names summary{cursor:pointer;color:var(--ink-2)}
.line-names summary::marker{color:var(--ink-3)}
.line-names p{margin:.4rem 0 0;color:var(--ink-2);line-height:1.5}
.tir-err{margin:.5rem 0 0;color:var(--brick);font-size:.85rem}

/* ============================================================
   ОКНО ПРАВКИ ТЕКСТА В КОРЗИНЕ
   ------------------------------------------------------------
   <dialog>, поэтому подложку, запирание фокуса и Escape делает
   браузер. Здесь только вид.

   Ширина небольшая: полей пять, и растягивать их на весь экран
   значит гнать взгляд слева направо на каждой строке.
   ============================================================ */
.ed-mod{
  border:0;border-radius:16px;padding:0;max-width:min(30rem, calc(100vw - 2rem));width:100%;
  background:var(--card);color:var(--ink);box-shadow:var(--shadow-l);
}
.ed-mod::backdrop{background:rgba(24,18,28,.5)}
.ed-form{display:flex;flex-direction:column;gap:.85rem;padding:1.3rem 1.4rem 1.4rem}
.ed-head{display:flex;align-items:center;justify-content:space-between;gap:1rem}
.ed-head h2{margin:0;font-size:1.15rem;font-weight:600}
.ed-x{
  background:none;border:0;padding:.35rem;margin:-.35rem;cursor:pointer;line-height:0;
  color:var(--ink-3);border-radius:6px;
}
.ed-x:hover{color:var(--ink)}
.ed-x svg{width:1.15rem;height:1.15rem;fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round}
.ed-note{margin:0;font-size:.84rem;color:var(--ink-3);line-height:1.45}
.ed-f{display:flex;flex-direction:column;gap:.25rem;position:relative;min-width:0}
.ed-f label{font-size:.74rem;letter-spacing:.05em;text-transform:uppercase;color:var(--ink-3)}
.ed-f input[type="text"]{
  font-family:var(--sans);font-size:.95rem;padding:.55rem .65rem;background:var(--card);
  border:1px solid var(--rule-2);border-radius:8px;color:var(--ink);width:100%;
}
.ed-f input[type="text"]:focus{outline:0;border-color:var(--brand);box-shadow:0 0 0 3px var(--brand-soft)}
.ed-row{display:grid;grid-template-columns:1fr 1fr;gap:.7rem}
.ed-err{margin:0;font-size:.85rem;color:var(--brick);font-weight:500;line-height:1.4}
.ed-acts{display:flex;gap:.6rem;margin-top:.2rem}
.ed-acts .btn{flex:1;min-height:44px}

/* Кнопка «Изменить текст» выглядит как ссылка: это второе
   действие рядом с «Удалить», и превращать её в кнопку с рамкой
   значит уравнять по весу с покупкой. */
.acts button#edOpen{
  background:none;border:0;padding:0;cursor:pointer;
  color:var(--brand);font-size:inherit;text-decoration:underline;text-underline-offset:.18em;
}
.acts button#edOpen:hover{text-decoration:none}

@media (max-width:520px){
  .ed-row{grid-template-columns:1fr}
  .ed-acts{flex-direction:column-reverse}
}

/* Строка скидки в счёте: тем же зелёным, что и «разовый платёж».
   Скидка — единственная строка со знаком минус, и её надо
   отличать от остальных не только знаком. */
.sum .row-off span{color:var(--good-ink)}
.sum .row-off span:last-child{font-weight:600}

/* ============================================================
   ОКНО СМЕНЫ ДИЗАЙНА
   ------------------------------------------------------------
   Карточки настоящие и с текстом из корзины: человек выбирает
   свой результат, а не картинку, которую потом надо представить
   со своим именем.
   ============================================================ */
.tpl-mod .ed-form{max-width:52rem}
.ed-note{margin:0 0 1rem;font-size:.88rem;color:var(--ink-2)}

.tpl-grid{
  display:grid;grid-template-columns:repeat(auto-fill,minmax(8.5rem,1fr));
  gap:1rem .8rem;max-height:60vh;overflow-y:auto;padding:.2rem;
}
.tpl-one{
  display:flex;flex-direction:column;gap:.4rem;
  background:none;border:0;padding:0;cursor:pointer;font:inherit;text-align:center;
}
.tpl-one .yz-inv-wrap{
  border:2px solid transparent;border-radius:2px;
  transition:transform .2s ease,border-color .2s ease,box-shadow .2s ease;
}
@media (hover:hover) and (pointer:fine){
  .tpl-one:hover .yz-inv-wrap{transform:translateY(-3px);box-shadow:var(--shadow-m)}
}
.tpl-one:focus-visible .yz-inv-wrap{outline:2px solid var(--brand);outline-offset:2px}
.tpl-one[aria-pressed="true"] .yz-inv-wrap{border-color:var(--brand);box-shadow:var(--shadow-m)}
.tpl-nm{font-size:.82rem;color:var(--ink-2);line-height:1.25}
.tpl-one[aria-pressed="true"] .tpl-nm{color:var(--brand);font-weight:600}
@media (prefers-reduced-motion:reduce){.tpl-one .yz-inv-wrap{transition:none}}

/* Счётчик имён: сверх порога — предупреждением, а не молча.
   Лишние имена стоят денег, и узнать об этом надо до оплаты. */
.fld-n.is-over{color:var(--amber);font-weight:600}

/* ============================================================
   ОФОРМЛЕНИЕ ЗАКАЗА
   ------------------------------------------------------------
   Единственный экран сайта, где следующее нажатие означает
   деньги. Поэтому здесь ничего «примерно»: у каждого поля своё
   состояние, у каждой кнопки — отклик, и всё, что человек может
   спросить перед оплатой, отвечено на самом экране.
   ============================================================ */

/* ---------- три шага ---------- */
.co-steps{
  display:flex;gap:.55rem;align-items:center;flex-wrap:wrap;
  list-style:none;margin:0 0 1.4rem;padding:0;
  font-size:.8rem;color:var(--ink-3);
}
.co-steps li{display:flex;align-items:center;gap:.55rem}
/* Разделитель рисуется псевдоэлементом, а не отдельным узлом:
   стрелка между шагами — это оформление, а не содержание, и
   голосом её читать незачем. */
.co-steps li + li::before{content:"";width:1.1rem;height:1px;background:var(--rule-2)}
.co-steps a{color:inherit;text-decoration:none;border-bottom:1px solid transparent;transition:color .16s ease,border-color .16s ease}
.co-steps a:hover{color:var(--brand);border-color:var(--brand)}
.co-steps .is-done{color:var(--ink-2)}
.co-steps .is-done a::after{content:" ✓";color:var(--good-ink)}
.co-steps .is-now{color:var(--brand);font-weight:600}

.co-page h1{margin:0 0 1.4rem}

/* ---------- поле почты ---------- */
/* Коробка вокруг единственного поля.

   Поле во всю ширину колонки выглядело как незаконченная
   вёрстка: одна строка ввода длиной в тысячу точек. Коробка
   задаёт ей край и заодно отделяет ввод от согласия и кнопки —
   трёх разных действий, которые до этого шли сплошняком. */
.co-box{
  background:var(--card);border:1px solid var(--rule);
  padding:1.15rem 1.25rem 1.3rem;margin:0 0 1.1rem;
  max-width:34rem;
  transition:border-color .2s ease,box-shadow .2s ease;
}
.co-box:focus-within{border-color:var(--brand);box-shadow:0 0 0 3px var(--brand-soft)}
.co-box .pay-field{margin:0}
.co-box input{max-width:24rem}

/* ---------- согласие ---------- */
.co-agree{
  display:flex;gap:.6rem;align-items:flex-start;
  max-width:34rem;margin:0 0 1.2rem;padding:.15rem 0;
  font-size:.92rem;line-height:1.45;color:var(--ink-2);cursor:pointer;
}
.co-agree input{margin-top:.2rem;flex:none;width:1.05rem;height:1.05rem;accent-color:var(--brand);cursor:pointer}
.co-agree a{color:var(--brand);text-decoration:none;border-bottom:1px solid var(--rule-2);transition:border-color .16s ease}
.co-agree:hover a{border-color:var(--brand)}

/* ---------- кнопка ---------- */
.co-go{
  display:inline-flex;align-items:center;justify-content:center;gap:.5rem;
  width:100%;max-width:22rem;
  transition:gap .2s ease,transform .18s ease,box-shadow .2s ease;
}
.co-go svg{
  width:1.05rem;height:1.05rem;flex:none;
  fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;
}
@media (hover:hover) and (pointer:fine){
  .co-go:hover{gap:.85rem;transform:translateY(-1px);box-shadow:0 10px 24px -12px rgba(222,47,87,.7)}
}
.co-go:active{transform:translateY(0)}
.co-after{margin:.7rem 0 0;max-width:34rem;font-size:.85rem;color:var(--ink-3);line-height:1.45}

/* ---------- что дальше ---------- */
.co-next{margin:2.6rem 0 0;padding-top:1.8rem;border-top:1px solid var(--rule)}
.co-next h2{font-size:1.15rem;margin:0 0 1.1rem}
.co-next ol{
  list-style:none;margin:0;padding:0;
  display:grid;grid-template-columns:repeat(auto-fit,minmax(13rem,1fr));gap:1rem;
  counter-reset:co;
}
.co-next li{
  counter-increment:co;
  background:var(--card);border:1px solid var(--rule);padding:1rem 1.1rem 1.1rem;
  transition:border-color .2s ease,transform .2s ease,box-shadow .2s ease;
}
/* Номер — счётчиком, а не цифрой в разметке: порядок задаёт
   список, и вписанная руками цифра рано или поздно разойдётся
   с ним при перестановке пунктов. */
.co-next li::before{
  content:counter(co);
  display:grid;place-items:center;width:1.6rem;height:1.6rem;margin:0 0 .6rem;
  border-radius:50%;background:var(--brand-soft);color:var(--brand);
  font-size:.85rem;font-weight:700;line-height:1;
}
@media (hover:hover) and (pointer:fine){
  .co-next li:hover{border-color:var(--brand);transform:translateY(-2px);box-shadow:0 12px 28px -18px rgba(0,0,0,.45)}
}
.co-next b{display:block;font-size:.98rem;margin:0 0 .3rem}
.co-next p{margin:0;font-size:.88rem;color:var(--ink-2);line-height:1.5}

/* ---------- сводка ---------- */
.co-sum{position:sticky;top:76px}
@media (max-width:880px){.co-sum{position:static}}

/* Карточка того, за что платят. Её здесь не было вовсе: человек
   платил за приглашение, не видя приглашения. */
.co-card{display:flex;gap:.85rem;align-items:flex-start;margin:0 0 1rem;padding:0 0 1rem;border-bottom:1px solid var(--rule)}
.co-card .yz-inv-wrap{
  width:4.6rem;flex:none;border:1px solid var(--rule);
  transition:transform .25s cubic-bezier(.2,.7,.3,1),box-shadow .25s ease;
}
@media (hover:hover) and (pointer:fine){
  .co-card:hover .yz-inv-wrap{transform:translateY(-3px) rotate(-1.5deg);box-shadow:var(--shadow-m)}
}
.co-card-t{min-width:0;display:flex;flex-direction:column;gap:.15rem}
.co-card-t b{font-size:.95rem;line-height:1.25}
.co-card-t span{font-size:.85rem;color:var(--ink-2)}
.co-card-t a{
  align-self:flex-start;margin-top:.25rem;font-size:.82rem;color:var(--brand);
  text-decoration:none;border-bottom:1px solid transparent;transition:border-color .16s ease;
}
.co-card-t a:hover{border-color:var(--brand)}

@media (prefers-reduced-motion:reduce){
  .co-box,.co-go,.co-next li,.co-card .yz-inv-wrap{transition:none}
  .co-go:hover,.co-next li:hover,.co-card:hover .yz-inv-wrap{transform:none}
}

/* ============================================================
   ЭКРАН ГОТОВНОСТИ: ОТПРАВИТЬ, А НЕ СКАЧАТЬ
   ------------------------------------------------------------
   Главное действие после оплаты — отправить приглашение. Ради
   этого живая страница и куплена, и до сих пор этот шаг человек
   делал сам: экран давал ссылку и оставлял его сочинять подпись
   для родительского чата.

   Блок стоит выше кнопки в кабинет и оформлен как действие,
   а не как справка: поле с текстом, который видно и можно
   поправить, и одна заметная кнопка.
   ============================================================ */
.send{
  margin:1.6rem 0 0;padding:1.1rem 1.2rem;border-radius:12px;
  background:var(--brand-soft);
  border:1px solid color-mix(in srgb, var(--brand) 22%, transparent);
}
.send h2{font-family:var(--serif);font-size:1.15rem;margin:0 0 .3rem}
.send-h{margin:0 0 .7rem;font-size:.88rem;color:var(--ink-2);line-height:1.45}
.send textarea{
  width:100%;box-sizing:border-box;resize:vertical;
  font-family:var(--sans);font-size:.95rem;line-height:1.5;
  padding:.7rem .8rem;border-radius:8px;color:var(--ink);
  background:var(--card);border:1px solid var(--rule-2);
}
.send textarea:focus{outline:2px solid var(--brand);outline-offset:1px;border-color:transparent}
.send-acts{display:flex;gap:.6rem;flex-wrap:wrap;margin:.7rem 0 0}
.send-acts .btn{min-height:44px;display:inline-flex;align-items:center;justify-content:center}
.send-acts .btn.is-ok{background:var(--good-ink);border-color:var(--good-ink)}
.send-note{margin:.7rem 0 0;font-size:.8rem;line-height:1.45;color:var(--ink-3)}

.paid-next{margin:1.4rem 0 0}
.paid-fine{margin:1.2rem 0 0;font-size:.86rem;color:var(--ink-3);line-height:1.5}
.fine.is-gap{margin-top:1rem}
.cart-empty.is-mid{margin:2rem auto;max-width:34rem}

@media (max-width:560px){
  .send{padding:.9rem .9rem}
  .send-acts .btn{width:100%}
}
.paid-same{margin:.6rem 0 0;font-size:.9rem;color:var(--ink-2);line-height:1.5}
