/* ============================================================
   Lab — interim home, service pages, case previews. Third pass.
   Language of the site: dark ground #171719, panels #232325, light plates
   #EAEAEA / #F7F7F7, Inter, radii 20/16/14, page gutter 24 → 6 by band
   (the steps of 01-header.css and 14b-footer.css).
   No WebGL, no Lenis, no reveal or decorative scroll motion. States move by
   the site law: capsule left→right, 300 ms in, 240 ms out,
   cubic-bezier(.4,0,.2,1) — the two durations are tokens (--lab-in/--lab-out,
   set in lab-chrome.css) and collapse to 1 ms under reduced motion. No idle
   animation: the SKARR.PRO column highlight is a static block.
   ============================================================ */

:root {
  --g: 24px;                 /* page gutter, one number per band */
  --hdr-h: 88px;             /* first-screen header: padding-top + bar + padding-bottom, by band */
  --clear: 72px;             /* anchor line: below the compact logo that stands where the header left */
  --ink: #eaeaea;
  --ink-dim: #d9d9d9;
  --ink-mute: #818181;
  --ground: #171719;
  --panel: #232325;
  --plate: #eaeaea;
  --ww: #f7f7f7;
  --line: rgba(234, 234, 234, 0.14);
  --line-dark: rgba(23, 23, 25, 0.16);
  --lab-in: 300ms;
  --lab-out: 240ms;
  --lab-ease: cubic-bezier(0.4, 0, 0.2, 1);
}
@media (max-width: 1200px)   { :root { --g: 20px; --hdr-h: 84px; } }
@media (max-width: 1024px)   { :root { --g: 16px; --hdr-h: 80px; } }
@media (max-width: 768px)    { :root { --g: 12px; --hdr-h: 76px; } }
@media (max-width: 519.98px) { :root { --g: 8px;  --hdr-h: 68px; } }
@media (max-width: 375px)    { :root { --g: 6px; } }
@media (max-width: 374.98px) { :root { --hdr-h: 56px; } }

.lab, .lab * { box-sizing: border-box; }
/* The page keeps no tail under the footer (Alexa, 20.09.2026 — COMPONENTS.md
   law 7). It held the dock's height since 16.09, when the service line still
   lived under the frame and the pill covered Accessibility; law 6 moved that
   line above the frame on 19.09, so the reserve has been holding 80 px of
   empty floor for nothing. The pill steps aside at the frame instead
   (js/nav.js, meetsFooter). */
.lab { min-width: 320px; overflow-x: clip; }
.lab-main, .sp { position: relative; z-index: 5; }
#services, #cases, #next, #improving, #contact, #contact-card, [data-dock-target] { scroll-margin-top: var(--clear); }

/* ---------- Shared type ---------- */
.lab-h2 {
  margin: 0;
  font: 600 40px/44px "Inter", sans-serif;
  letter-spacing: -0.02em;
  text-transform: uppercase;
  color: var(--ink);
}
.lab-lead { margin: 12px 0 0; max-width: 62ch; font: 400 18px/26px "Inter", sans-serif; color: var(--ink-dim); }
.lab-eyebrow {
  margin: 0;
  font: 500 12px/16px "Inter", sans-serif;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-mute);
}
.lab-sechead { display: flex; flex-direction: column; }
.lab-sechead--row { flex-direction: row; align-items: flex-end; justify-content: space-between; gap: 24px 32px; flex-wrap: wrap; }
.lab-visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
/* Text link with a 44 px hit area that does not move the text. */
.lab-textlink {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  margin-block: -12px;
  padding: 0 2px;
  font: 500 13px/16px "Inter", sans-serif;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: currentColor;
  text-decoration: underline;
  text-underline-offset: 4px;
  text-decoration-color: rgba(128, 128, 128, 0.5);
  white-space: nowrap;
  -webkit-user-select: none;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
  transition: text-decoration-color var(--lab-out) linear;
}
.lab-textlink:hover, .lab-textlink:active { text-decoration-color: currentColor; transition-duration: var(--lab-in); }
.lab-textlink:focus-visible { outline: 2px solid currentColor; outline-offset: 2px; border-radius: 4px; }
/* Tags on the home are the canonical chip (.svc-chips / .svc-chip from
   05-services-row.css, hover fill from 95-chips.css) — not these rules.
   .lab-tags / .lab-tag stay only for the editions on /apps/ (src/apps.mjs,
   pool 2); once that list takes the canonical chip too, delete them. */
.lab-tags { display: flex; flex-wrap: wrap; gap: 6px; margin: 0; padding: 0; list-style: none; }
.lab-tag {
  display: inline-flex;
  align-items: center;
  height: 30px;
  padding: 0 12px;
  border-radius: 999px;
  box-shadow: inset 0 0 0 1px currentColor;
  font: 500 12px/16px "Inter", sans-serif;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  white-space: nowrap;
}
/* Visible marker of prototype or unconfirmed content. */
.lab-pending {
  display: inline-flex;
  align-items: center;
  height: 30px;
  padding: 0 12px;
  border-radius: 999px;
  box-shadow: inset 0 0 0 1px currentColor;
  font: 500 12px/16px "Inter", sans-serif;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  white-space: nowrap;
}
.lab-pending::before { content: "["; }
.lab-pending::after { content: "]"; }
.lab-pending--small { height: auto; min-height: 24px; margin-top: 8px; padding: 3px 8px; font-size: 10px; line-height: 14px; white-space: normal; text-align: left; color: var(--ink-mute); }
@media (max-width: 1024px) {
  .lab-h2 { font-size: 34px; line-height: 36px; }
  .lab-lead { font-size: 17px; line-height: 25px; }
}
@media (max-width: 719.98px) {
  .lab-h2 { font-size: 28px; line-height: 30px; }
  .lab-lead { font-size: 16px; line-height: 24px; margin-top: 10px; }
}

/* Her line breaks (Alexa, 16.09.2026): the tail phrase of a line is one piece —
   it drops to the next line whole instead of leaving a widow, and wraps inside
   itself only where a column is narrower than the phrase. */
.lab-tail { display: inline-block; }
/* The services lead carries her own division (Alexa, 20.09.2026): the first
   line ends on «Open a service,», the whole invitation stands as the second.
   Held as one piece, the second phrase puts the break there on every measure
   down to 430: 462/385 at 1440, 437/363 at 834, 411/342 at 600 — where the
   free flow used to leave a full line and a stub (672/175, 597/155).
   The switch below is geometry, not a band: the first phrase measures 410.89
   px at 16 px, so with the 8 px gutter it stops fitting a line of its own
   under 427, and holding the second phrase whole would leave the single word
   «service,» on a line. There the outer piece opens up and the line fills
   again, while the inner .lab-tail still keeps «buy the one that fits.»
   together — without it 390 ends on the single word «fits.»
   (346/246/155 instead of 346/374/28). */
@media (max-width: 426.98px) { .svs-lead-tail { display: inline; } }

/* ---------- Button, type B (one label). Buttons law, sections 2–4. ---------- */
.lab-btn {
  --btn-bg: var(--ww);
  --btn-ink: #171719;
  --btn-fill: #171719;
  --btn-fill-ink: #eaeaea;
  --btn-ring: none;
  --btn-focus: #eaeaea;
  --btn-radius: 14px;
  /* The fill stops short of the edge: a rim of the rest colour stays, so the
     capsule still reads when filled (Alexa, 16.09.2026). */
  --btn-inset: 2px;
  position: relative;
  isolation: isolate;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 56px;
  min-height: 56px;
  max-height: 56px;
  padding: 0 32px;
  border: 0;
  border-radius: var(--btn-radius);
  background: transparent;
  font: 600 16px/20px "Inter", sans-serif;
  letter-spacing: 0.01em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--btn-ink);
  white-space: nowrap;
  cursor: pointer;
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
  -webkit-tap-highlight-color: transparent;
  transition: color var(--lab-out) linear;
}
.lab-btn::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -2;
  border-radius: inherit;
  background: var(--btn-bg);
  box-shadow: var(--btn-ring);
}
.lab-btn::after {
  content: "";
  position: absolute;
  inset: var(--btn-inset);
  z-index: -1;
  border-radius: calc(var(--btn-radius) - var(--btn-inset));
  background: var(--btn-fill);
  clip-path: inset(0 100% 0 0 round calc(var(--btn-radius) - var(--btn-inset)));
  transition: clip-path var(--lab-out) var(--lab-ease);
}
.lab-btn:hover::after, .lab-btn:active::after, .lab-btn:focus-visible::after,
.svs-link:hover .lab-btn::after, .svs-link:focus-visible .lab-btn::after,
.svr-link:hover .lab-btn::after, .svr-link:focus-visible .lab-btn::after,
.cse-link:hover .lab-btn::after, .cse-link:focus-visible .lab-btn::after {
  clip-path: inset(0 round calc(var(--btn-radius) - var(--btn-inset)));
  transition-duration: var(--lab-in);
}
.lab-btn:hover, .lab-btn:active, .lab-btn:focus-visible,
.svs-link:hover .lab-btn, .svs-link:focus-visible .lab-btn,
.svr-link:hover .lab-btn, .svr-link:focus-visible .lab-btn,
.cse-link:hover .lab-btn, .cse-link:focus-visible .lab-btn {
  color: var(--btn-fill-ink);
  transition-duration: var(--lab-in);
}
.lab-btn:focus-visible { outline: 2px solid var(--btn-focus); outline-offset: 3px; }
.lab-btn--dark { --btn-bg: #171719; --btn-ink: #eaeaea; --btn-fill: var(--ww); --btn-fill-ink: #171719; --btn-focus: #171719; }
.lab-btn--ghost { --btn-bg: transparent; --btn-ring: inset 0 0 0 1px var(--ink); --btn-ink: var(--ink); --btn-fill: var(--ink); --btn-fill-ink: #171719; --btn-focus: var(--ink); }

/* ---------- Section tabs in the canonical .cs-tabs (09-cases.css) ----------
   Filter buttons share the tab look. Hover: the site's capsule; the active tab
   is a plate and does not react. The row scrolls when the width runs out. */
.hs-nav { margin-top: 24px; }
.hs-row { overflow-x: auto; scrollbar-width: none; scroll-snap-type: x proximity; }
.hs-row::-webkit-scrollbar { display: none; }
.hs-tab {
  position: relative;
  isolation: isolate;
  flex: 1 0 auto;
  gap: 8px;
  font-family: "Inter", sans-serif;
  text-decoration: none;
  scroll-snap-align: start;
  -webkit-user-select: none;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
  transition: color var(--lab-out) linear;
}
.hs-tab::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  background: #eaeaea;
  clip-path: inset(0 100% 0 0 round 51px);
  transition: clip-path var(--lab-out) var(--lab-ease);
}
.hs-tab:not(.cs-tab--active):hover::after,
.hs-tab:not(.cs-tab--active):active::after,
.hs-tab:not(.cs-tab--active):focus-visible::after { clip-path: inset(0 round 51px); transition-duration: var(--lab-in); }
.hs-tab:not(.cs-tab--active):hover,
.hs-tab:not(.cs-tab--active):active,
.hs-tab:not(.cs-tab--active):focus-visible { color: #232325; transition-duration: var(--lab-in); }
.hs-tab.cs-tab--active { cursor: pointer; }
.hs-tab.cs-tab--active::after { display: none; }
.hs-tab:focus-visible { outline: 2px solid #eaeaea; outline-offset: -4px; }
.hs-count { font-weight: 400; opacity: 0.6; }
.cse-tabs { position: relative; }
.cse-tabs::after { content: ""; position: absolute; top: 4px; right: 4px; bottom: 4px; width: 48px; border-radius: 0 51px 51px 0; background: linear-gradient(90deg, rgba(35, 35, 37, 0), #232325); pointer-events: none; opacity: 1; transition: opacity 160ms linear; }
.cse-tabs[data-at-end]::after { opacity: 0; }

/* ============================================================
   HOME
   ============================================================ */

/* ---------- Hero: big typography with two fragments of real work inside it ---------- */
.hero { padding: calc(var(--hdr-h) + 40px) var(--g) 0; color: var(--ink); }
.hero-kicker { margin: 0; font: 500 13px/16px "Inter", sans-serif; letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink-mute); }
.hero-title {
  display: flex;
  flex-direction: column;
  gap: 0.04em;
  margin: 16px 0 0;
  font: 600 clamp(40px, 5.4vw, 88px) / 1 "Inter", sans-serif;
  letter-spacing: -0.03em;
  text-transform: uppercase;
}
.hero-line { display: flex; align-items: center; gap: 0.2em; white-space: nowrap; }
.hero-frag {
  position: relative;
  isolation: isolate;
  flex: 0 0 auto;
  display: block;
  width: 2.2em;
  height: 0.9em;
  overflow: hidden;
  border-radius: 0.2em;
  background: var(--panel);
  color: var(--ink);
  text-decoration: none;
  letter-spacing: 0;
  text-transform: none;
  -webkit-user-select: none;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
  transition: width var(--lab-out) var(--lab-ease);
}
.hero-frag.is-open { width: max(4.2em, 240px); transition-duration: var(--lab-in); }
.hero-frag-media { position: absolute; inset: 0; }
.hero-frag-media img { display: block; width: 100%; height: 100%; object-fit: cover; object-position: center top; }
.hero-frag-cap {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 18px 12px 10px;
  background: linear-gradient(180deg, rgba(23, 23, 25, 0), rgba(23, 23, 25, 0.86));
  font: 500 12px/16px "Inter", sans-serif;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: #eaeaea;
  white-space: nowrap;
  opacity: 0;
  transform: translateY(6px);
  transition: opacity var(--lab-out) linear, transform var(--lab-out) var(--lab-ease);
}
.hero-frag-cap strong { font-weight: 600; }
.hero-frag-cap span { color: #b8b8bd; overflow: hidden; text-overflow: ellipsis; }
.hero-frag-cap em { margin-left: auto; font-style: normal; text-decoration: underline; text-underline-offset: 3px; }
.hero-frag.is-open .hero-frag-cap { opacity: 1; transform: none; transition-duration: var(--lab-in); }
.hero-frag:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }
.hero-sub { margin: 22px 0 0; max-width: 60ch; font: 400 18px/26px "Inter", sans-serif; color: var(--ink-dim); }
.hero-strip { display: none; }
.hero-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 26px; }

/* ---------- Services ---------- */
.svs { margin-top: 64px; padding: 0 var(--g); }

/* Category navigator: a product element, room for an icon per category. */
.cat { margin-top: 24px; }
.cat-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 8px; margin: 0; padding: 0; list-style: none; }
.cat-item {
  display: grid;
  grid-template-columns: 44px minmax(0, 1fr);
  gap: 12px;
  height: 100%;
  min-height: 132px;
  padding: 14px 16px 14px 14px;
  border-radius: 16px;
  background: var(--panel);
  box-shadow: inset 0 0 0 1px rgba(234, 234, 234, 0.1);
  color: var(--ink);
  text-decoration: none;
  -webkit-tap-highlight-color: transparent;
  transition: box-shadow var(--lab-out) var(--lab-ease), background-color var(--lab-out) var(--lab-ease);
}
.cat-item:hover, .cat-item:active { background-color: #2a2a2d; box-shadow: inset 0 0 0 1px var(--ink); transition-duration: var(--lab-in); }
.cat-item:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }
.cat-icon {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: 12px;
  background: rgba(234, 234, 234, 0.06);
  font: 500 12px/16px "Inter", sans-serif;
  letter-spacing: 0.1em;
  color: var(--ink-mute);
  transition: background-color var(--lab-out) var(--lab-ease), color var(--lab-out) var(--lab-ease);
}
/* Наведение переворачивает квадрат с номером (правка Alexa, 20.09.2026): одной
   рамки мало, чтобы карточка читалась выбранной — рамка светится на краю, а
   глаз в этот момент на номере. Квадрат берёт тот же белый, что и рамка в ту
   же секунду, номер — цвет фона наведённой карточки: квадрат читается
   вырезанным из неё, третьего цвета в состояние не вводится. */
.cat-item:hover .cat-icon, .cat-item:active .cat-icon {
  background-color: var(--ink);
  color: #2a2a2d;
  transition-duration: var(--lab-in);
}
.cat-body { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.cat-kicker { font: 500 10px/14px "Inter", sans-serif; letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink-mute); }
.cat-title { font: 600 17px/20px "Inter", sans-serif; letter-spacing: -0.01em; }
.cat-line { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; font: 400 13px/18px "Inter", sans-serif; color: var(--ink-dim); }
.cat-meta { margin-top: auto; padding-top: 6px; font: 500 12px/16px "Inter", sans-serif; letter-spacing: 0.04em; text-transform: uppercase; color: var(--ink-mute); }
.cat-title, .cat-kicker, .cat-meta { -webkit-user-select: none; user-select: none; }

/* Featured offer: copy with the two payments, the site's gallery on the right. */
.sps-card {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr);
  gap: 4px;
  margin-top: 24px;
  padding: 4px;
  border-radius: 20px;
  background: var(--plate);
  color: #171719;
}
.sps-copy { display: flex; flex-direction: column; min-width: 0; padding: 28px; }
.sps-eyebrow { color: #5c5c60; }
.sps-title { margin: 10px 0 0; max-width: 14ch; font: 600 clamp(28px, 2.6vw, 40px) / 1.05 "Inter", sans-serif; letter-spacing: -0.02em; text-transform: uppercase; }
.sps-tags { margin-top: 16px; column-gap: 8px; }
.sps-tags .svc-chip { padding: 7px 12px; font-size: 14px; line-height: 18px; }
.sps-lead { margin: 18px 0 0; max-width: 52ch; font: 400 18px/26px "Inter", sans-serif; }
.sps-support { margin: 8px 0 0; max-width: 52ch; font: 400 15px/22px "Inter", sans-serif; color: #444448; }
.sps-prices {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 20px 24px;
  margin: 32px 0 0;
  padding-top: 24px;
  border-top: 1px solid var(--line-dark);
}
.sps-price { min-width: 0; }
.sps-price dt { font: 500 12px/16px "Inter", sans-serif; letter-spacing: 0.12em; text-transform: uppercase; color: #5c5c60; }
.sps-price dd { display: flex; flex-direction: column; gap: 6px; margin: 10px 0 0; }
.sps-price strong { font: 600 36px/40px "Inter", sans-serif; letter-spacing: -0.02em; font-variant-numeric: tabular-nums; white-space: nowrap; }
.sps-price small { font: 500 16px/20px "Inter", sans-serif; letter-spacing: 0; color: #444448; }
.sps-price dd span { max-width: 28ch; font: 400 13px/18px "Inter", sans-serif; color: #444448; }
/* The buttons stand at the bottom-left, the same distance from the left and
   the bottom edge as the copy (Alexa, 16.09.2026). In the dealer card the
   button carries no caption at all (Alexa, 19.09.2026), so that distance is
   the button's own: 4 of the card plate + 28 of the copy on both sides. The
   note on press is not a caption — it is hidden until the button is pressed
   and only then takes its line below.
   Это поле держится только на телефоне. От 720 карточка главной услуги его
   отменяет: кнопка сходит на кромку, 4 слева и снизу (см. блок сразу ниже). */
.sps-buy { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 12px; margin-top: auto; padding-top: 36px; }
.sps-buy-item { display: flex; flex-direction: column; }
.sps-buy .cmp-test { margin-top: 8px; color: #5c5c60; }
/* Кромка вместо поля — на планшете тоже (Alexa, 20.09.2026: «на таблете до сих
   пор сохранилось, что на этой карточке бай кнопка на таком большом отступе
   снизу и сверху»). Полоса 720…1439 оставалась единственной, где кнопка стояла
   в поле копии, 32 от левого и нижнего края: на телефоне она на кромке с
   19.09, от 1440 — с 20.09, а середина не была переведена ни разу. Отступ —
   тот же −28, что и в полосе от 1440: 28 поля копии минус 4 плиты карточки
   даёт 4 от края. Правило адресное, `#dealer`: ту же разметку носит карточка
   приложения на /apps, её геометрию не трогаем. */
@media (min-width: 720px) {
  #dealer .sps-buy { margin-inline-start: -28px; margin-bottom: -28px; }
}
.sps-visual {
  position: relative;
  margin: 0;
  min-height: 440px;
  overflow: hidden;
  border-radius: 16px;
  background: var(--panel);
  color: var(--ink);
}
.sps-media { position: absolute; inset: 0; outline: none; }
.sps-media > img, .sps-media .gal-frame--native img { display: block; width: 100%; height: 100%; object-fit: cover; object-position: top; }
.sps-visual.is-focus-left .sps-media .gal-frame--native img { object-position: left top; }
.sps-media:focus-visible { outline: 2px solid var(--ink); outline-offset: -4px; }
/* The canonical gallery on this slot: the concentric radii of the case slot
   (96-gallery.css), the native first frame fills the slot like the others. */
.sps-media.gal { --gal-bar: 24px; --gal-nav: 52px; --gal-radius: 16px; border-radius: 16px; }
.sps-media .gal-frame--native { position: absolute; inset: 0; }

/* Six cards: title → chips → line → price → See details.
   Две в ряд — это база, три в ряд начинаются с десктопа (Alexa, 20.09.2026:
   «чтобы на десктопе уже начиналось 3 в ряд… это на таблете только будет»).
   Граница — 1440, та же, с которой в этом файле начинается десктопная полоса
   карточки главной услуги. Ниже неё три в ряд давали карточку уже порога 424
   (1280 → 403), и плашка цены складывалась в два этажа; см. комментарий к
   `.svs-card` ниже. */
.svs-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; margin: 12px 0 0; padding: 0; list-style: none; }
@media (min-width: 1440px) { .svs-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
/* The card is the measure for its own plate: in this grid the card width
   does not follow the viewport (2560 → 829, 1440 → 456, 1439 → 690,
   1280 → 610, 1024 → 491, 768 → 367), and at the 1440 band it drops by 234
   while the window grows by one pixel. A band query would put the one-storey
   plate on cards too narrow to hold it. The plate asks the card, not the
   window. */
.svs-card { display: flex; min-width: 0; container-type: inline-size; }
.svs-link {
  display: flex;
  flex-direction: column;
  width: 100%;
  padding: 4px;
  border-radius: 20px;
  background: var(--plate);
  color: #171719;
  text-decoration: none;
  -webkit-tap-highlight-color: transparent;
  -webkit-touch-callout: none;
  transition: background-color var(--lab-out) var(--lab-ease);
}
.svs-link:hover, .svs-link:active { background-color: var(--ww); transition-duration: var(--lab-in); }
.svs-link:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }
.svs-media { aspect-ratio: 16 / 10; overflow: hidden; border-radius: 16px; background: #1d1d1f; }
.svs-media img { display: block; width: 100%; height: 100%; object-fit: cover; object-position: top; }
.svs-media.is-focus-left img { object-position: left top; }
.svs-media.is-focus-center img, .cse-media.is-focus-center img, .spv-frame.is-focus-center .spv-media img { object-position: center; }
.svs-media.is-tile, .cse-media.is-tile, .spv-frame.is-tile .spv-media {
  display: grid;
  place-items: center;
  background: radial-gradient(120% 120% at 30% 20%, rgba(224, 85, 154, 0.20), rgba(224, 85, 154, 0) 62%), var(--ground);
}
.svs-media.is-tile img, .cse-media.is-tile img, .spv-frame.is-tile .spv-media img { width: 32%; height: auto; border-radius: 22%; }
/* A portrait shot stands whole in the frame, on the dark plate. */
.cse-media.is-phone, .spv-frame.is-phone .spv-media { position: relative; background: #1d1d1f; }
.cse-media.is-phone img, .spv-frame.is-phone .spv-media img { position: absolute; top: 6%; left: 50%; width: auto; height: 100%; max-width: none; transform: translateX(-50%); object-fit: cover; object-position: top; border-radius: 12px 12px 0 0; box-shadow: 0 0 0 1px rgba(234, 234, 234, 0.12); }
.svs-body { display: flex; flex-direction: column; flex: 1 1 auto; gap: 12px; padding: 16px 16px 12px; }
.svs-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.svs-title { margin: 0; font: 600 24px/24px "Inter", sans-serif; letter-spacing: -0.02em; text-transform: uppercase; }
.svs-index { font: 500 12px/16px "Inter", sans-serif; letter-spacing: 0.14em; color: var(--ink-mute); }
.svs-line { margin: 0; max-width: 38ch; font: 400 15px/22px "Inter", sans-serif; color: #2c2c2c; }
/* ---------- The edge plate (Alexa, 20.09.2026) ----------
   Carried back from the big home: the sum and the action are one object
   lying on the card's edge, not two things floating in its field. Two steps,
   both concentric — card 20 → plate 16 (gap 4), plate 16 → button 10 (gap 6),
   8 on the two-storey plate (gap 8). The button ends up 10 from the card's
   outer edge, 12 where the plate stacks, as it did on the old home
   (css/05-services-row.css: .svc-body padding 0 4 4, .svc-price 72/16,
   .svc-btn right 6). Heights by band are that file's: 72 / 124 / 112.
   The plate is the last child of the link, the body grows — so the plate sits
   on the floor of the card and the cards in a row stay one height without
   margin-top: auto. */
.svs-plate {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  /* A floor and a minimum seam, not a fixed lid: the heights are the old
     home's (124 / 112 / 72) and they hold for every card here, but the sum
     and the action never come closer than 16 — the field under the sum is the
     one above it (Alexa, 20.09.2026: «верхнее внутреннее поле сделать равным
     левому; нижнее — тоже, с учётом появившейся второй строки»). The sum now
     always takes two lines here, so the plate grows past the floor instead of
     pinching them together. */
  gap: 16px;
  min-height: 124px;
  padding: 16px 8px 8px;
  border-radius: 16px;
  background: #171719;
  color: var(--ink);
}
/* Two storeys on the stacked plate (Alexa, 20.09.2026: «первой строкой цена,
   второй строкой под ней подпись»): the sum stands large and its terms stand
   under it — the same column the wide card already uses at `@container 424`.
   The price loses its half-leading on purpose: at 22/26 there are 2.78 px of
   dead box above the ink, so a box-equal 16 reads as 18.8 against a left 16. */
.svs-sum { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; min-width: 0; margin: 0; padding-left: 8px; }
.svs-sum strong { font: 600 22px/1 "Inter", sans-serif; letter-spacing: -0.02em; font-variant-numeric: tabular-nums; white-space: nowrap; }
.svs-sum span { font: 500 12px/14px "Inter", sans-serif; letter-spacing: 0.04em; text-transform: uppercase; color: rgba(234, 234, 234, 0.62); white-space: nowrap; }
.svs-plate .lab-btn { --btn-radius: 8px; display: flex; width: 100%; height: 60px; min-height: 60px; max-height: 60px; padding: 0 16px; }

/* The smallest screens take the old home's compact plate — 112 with a 48
   button, the step of css/05-services-row.css at 375. This one is the
   screen's, not the card's: the card at 768 is no wider, but the screen there
   is not short. */
@media (max-width: 375px) {
  .svs-plate { min-height: 112px; }
  .svs-sum strong { font-size: 20px; line-height: 1; }
  .svs-sum span { font-size: 11px; }
  .svs-plate .lab-btn { height: 48px; min-height: 48px; max-height: 48px; }
}

/* One storey — sum left, action right — only where the card is wide enough
   to hold both, and only above the phone band: below 720 every button on the
   page runs the full width, and the card does not step out of that. */
@media (min-width: 720px) {
  /* 424 is measured, not chosen: the widest sum on the page (201) plus its
     field (20), the gap (12), the button (165.5) and the ring (6), inside a
     plate that is the card less 8. Below it the two halves would touch. */
  @container (min-width: 424px) {
    .svs-plate { flex-direction: row; flex-wrap: wrap; align-items: center; min-height: 72px; padding: 6px 6px 6px 20px; }
    /* Кегль суммы и просвет под ней — её замер 20.09.2026 по снимку карточек:
       «цену ставь 21, субтекст оставляй 12, и расстояние между ними сделай
       чуть больше — они сейчас впритык». Было 24/28 и зазор 2. Блок суммы от
       этого не меняет высоту: 25 + 6 + 14 = 45 против 28 + 2 + 14 = 44, то
       есть плашка 72 и ряд карточек стоят на прежних местах. */
    .svs-sum { flex: none; flex-direction: column; align-items: flex-start; gap: 6px; padding-left: 0; }
    .svs-sum strong { font-size: 21px; line-height: 25px; }
    .svs-plate .lab-btn { --btn-radius: 10px; flex: none; width: auto; padding: 0 32px; }
  }
}
.svs-title, .svs-cta, .lab-tags, .svc-chips, .cse-title, .cse-status, .cse-cta, .svr-title, .svr-cta, .svr-entries, .svs-sum {
  -webkit-user-select: none;
  user-select: none;
}

/* Seventh: three entry points. */
.svr-card { margin-top: 12px; }
.svr-link {
  display: grid;
  grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr) auto;
  gap: 24px 32px;
  align-items: center;
  padding: 28px;
  border-radius: 20px;
  background: var(--panel);
  box-shadow: inset 0 0 0 1px rgba(234, 234, 234, 0.14);
  color: var(--ink);
  text-decoration: none;
  -webkit-tap-highlight-color: transparent;
  transition: box-shadow var(--lab-out) var(--lab-ease);
}
.svr-link:hover, .svr-link:active { box-shadow: inset 0 0 0 1px var(--ink); transition-duration: var(--lab-in); }
.svr-link:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }
.svr-title { margin: 8px 0 0; font: 600 32px/34px "Inter", sans-serif; letter-spacing: -0.02em; text-transform: uppercase; }
.svr-lead { margin: 12px 0 0; max-width: 52ch; font: 400 16px/24px "Inter", sans-serif; color: var(--ink-dim); }
.svr-thesis { margin: 12px 0 0; max-width: 40ch; font: 500 18px/26px "Inter", sans-serif; }
.svr-line { margin: 0 0 8px; font: 400 14px/20px "Inter", sans-serif; color: var(--ink-mute); }
.svr-entries { display: grid; gap: 0; margin: 0; padding: 0; list-style: none; }
.svr-entries li { display: flex; align-items: baseline; gap: 12px; padding: 12px 0; border-top: 1px solid var(--line); font: 400 16px/22px "Inter", sans-serif; }
.svr-entries li:last-child { border-bottom: 1px solid var(--line); }
.svr-num { font: 500 12px/16px "Inter", sans-serif; letter-spacing: 0.14em; color: var(--ink-mute); }
.svr-cta {
  justify-self: end;
  width: 168px;
  height: 168px;
  min-height: 168px;
  max-height: 168px;
  padding: 24px;
  --btn-radius: 50%;
  font-size: 14px;
  line-height: 18px;
  white-space: normal;
  text-align: center;
}

/* ---------- Cases: the library ---------- */
.cse { margin-top: 96px; padding: 0 var(--g); }
.cse-count { margin: 0; font: 500 13px/16px "Inter", sans-serif; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-mute); }
.cse-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; margin: 12px 0 0; padding: 0; list-style: none; }
.cse-card { display: flex; min-width: 0; }
.cse-card[hidden] { display: none; }
.cse-link, .cse-nda {
  display: flex;
  flex-direction: column;
  width: 100%;
  padding: 4px;
  border-radius: 20px;
  background: var(--panel);
  color: var(--ink);
  text-decoration: none;
}
.cse-link { -webkit-tap-highlight-color: transparent; -webkit-touch-callout: none; transition: background-color var(--lab-out) var(--lab-ease); }
.cse-link:hover, .cse-link:active { background-color: #2a2a2d; transition-duration: var(--lab-in); }
.cse-link:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }
.cse-media { aspect-ratio: 16 / 10; overflow: hidden; border-radius: 16px; background: #1d1d1f; }
.cse-media img { display: block; width: 100%; height: 100%; object-fit: cover; object-position: top; }
.cse-media.is-focus-left img { object-position: left top; }
.cse-body { display: flex; flex-direction: column; flex: 1 1 auto; gap: 8px; padding: 18px 16px 16px; }
.cse-link > .cse-body { padding-bottom: 12px; }
.cse-meta { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px 12px; margin: 0; }
.cse-status {
  display: inline-flex;
  align-items: center;
  height: 24px;
  padding: 0 10px;
  border-radius: 999px;
  box-shadow: inset 0 0 0 1px rgba(234, 234, 234, 0.3);
  font: 500 11px/16px "Inter", sans-serif;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-dim);
}
.cse-title { margin: 0; font: 600 26px/28px "Inter", sans-serif; letter-spacing: -0.02em; text-transform: uppercase; }
.cse-line { margin: 0; font: 400 16px/24px "Inter", sans-serif; color: var(--ink-dim); }
/* The action takes a step down from the description (Alexa, 20.09.2026, on the
   phone and again on the desktop: «the gap over VIEW CASE should be 8 more»).
   The card's copy runs on one 8, so without a step of its own the button stood
   as close to the line above it as the title stands to the status row, and the
   card read as three paragraphs instead of a card and its action. 12 of the
   body's floor plus 8 here — one measure on every width, since the rhythm is
   the card's and not the screen's. */
.cse-foot { display: flex; align-items: center; margin-top: 8px; }
.cse-foot .lab-btn { --btn-radius: 16px; display: flex; flex: 1 1 100%; }
/* NDA card: the frame where a screenshot would stand is deliberately
   classified (Alexa, 16.09.2026) — grain, the ghost of a screen under
   redaction bars, an inked stamp; then the category, one title element with
   the name blurred and the label over it, the map's role line and three short
   rows: what, where, role. No product visual, no name, no link. */
.cse-nda { box-shadow: inset 0 0 0 1px rgba(234, 234, 234, 0.1); }
.cse-media--nda {
  position: relative;
  display: grid;
  place-items: center;
  overflow: hidden;
  background: #141416;
  color: rgba(234, 234, 234, 0.9);
}
.cse-media--nda::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  background-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23g)'/%3E%3C/svg%3E");
  background-size: 180px 180px;
  opacity: 0.16;
  mix-blend-mode: screen;
  pointer-events: none;
}
/* The ghost of a screen: a bar, a headline, two lines, a visual, two cards. */
.cse-ghost {
  position: absolute;
  inset: 10% 9% 0;
  border-radius: 12px 12px 0 0;
  background:
    linear-gradient(#333338, #333338) 5% 6% / 18% 4% no-repeat,
    linear-gradient(#2c2c30, #2c2c30) 95% 6% / 30% 4% no-repeat,
    linear-gradient(#2e2e33, #2e2e33) 5% 24% / 52% 14% no-repeat,
    linear-gradient(#27272b, #27272b) 5% 44% / 44% 3% no-repeat,
    linear-gradient(#27272b, #27272b) 5% 51% / 36% 3% no-repeat,
    linear-gradient(#2a2a2e, #2a2a2e) 96% 62% / 34% 46% no-repeat,
    linear-gradient(#232327, #232327) 5% 96% / 26% 16% no-repeat,
    linear-gradient(#232327, #232327) 40% 96% / 26% 16% no-repeat,
    #1c1c1f;
  box-shadow: inset 0 0 0 1px rgba(234, 234, 234, 0.08);
  filter: blur(1.4px);
}
/* Redaction bars over the headline and the first line. */
.cse-ghost::before, .cse-ghost::after { content: ""; position: absolute; left: 5%; background: #08080a; box-shadow: 0 0 0 1px rgba(234, 234, 234, 0.06); }
.cse-ghost::before { top: 21%; width: 46%; height: 7%; }
.cse-ghost::after { top: 31%; width: 30%; height: 6%; }
.cse-stamp {
  position: relative;
  z-index: 3;
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 5px;
  padding: 12px 22px 14px;
  border: 3px solid currentColor;
  border-radius: 8px;
  box-shadow: inset 0 0 0 4px #141416, inset 0 0 0 5.5px currentColor;
  transform: rotate(-7deg);
  -webkit-mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240'%3E%3Cfilter id='k'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.7' numOctaves='2' seed='7' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3CfeComponentTransfer%3E%3CfeFuncA type='table' tableValues='0 0.2 1 1 1 1'/%3E%3C/feComponentTransfer%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23k)'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240'%3E%3Cfilter id='k'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.7' numOctaves='2' seed='7' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3CfeComponentTransfer%3E%3CfeFuncA type='table' tableValues='0 0.2 1 1 1 1'/%3E%3C/feComponentTransfer%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23k)'/%3E%3C/svg%3E");
  -webkit-mask-size: 240px 240px;
  mask-size: 240px 240px;
}
.cse-stamp-big { font: 800 26px/26px "Inter", sans-serif; letter-spacing: 0.16em; text-transform: uppercase; white-space: nowrap; }
.cse-stamp-small { font: 600 9px/12px "Inter", sans-serif; letter-spacing: 0.2em; text-transform: uppercase; white-space: nowrap; }
.cse-facts { display: grid; margin: 6px 0 0; padding: 0; }
.cse-facts > div { display: grid; grid-template-columns: 52px minmax(0, 1fr); gap: 12px; padding: 8px 0; border-top: 1px solid var(--line); }
.cse-facts dt { font: 500 11px/20px "Inter", sans-serif; letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-mute); }
.cse-facts dd { margin: 0; font: 400 14px/20px "Inter", sans-serif; color: var(--ink-dim); }
.cse-title--nda { position: relative; display: block; margin: 4px 0 0; }
.cse-redacted { display: inline-block; filter: blur(7px); opacity: 0.55; -webkit-user-select: none; user-select: none; }
.cse-nda-label {
  position: absolute;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
  display: inline-flex;
  align-items: center;
  height: 26px;
  padding: 0 10px;
  border-radius: 999px;
  background: var(--panel);
  box-shadow: inset 0 0 0 1px var(--ink);
  font: 500 11px/16px "Inter", sans-serif;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}
.cse-nda .cse-line { margin-top: 4px; font-size: 15px; line-height: 22px; }

/* ---------- Transitional CTA: short, tied to the order path, leading below ---------- */
.nxt {
  display: grid;
  grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr);
  gap: 24px 48px;
  align-items: start;
  margin: 80px var(--g) 0;
  padding-top: 32px;
  border-top: 1px solid var(--line);
  color: var(--ink);
}
.nxt-title { margin: 0; font: 600 34px/38px "Inter", sans-serif; letter-spacing: -0.02em; text-transform: uppercase; }
.nxt-text { margin: 12px 0 0; max-width: 64ch; font: 400 18px/26px "Inter", sans-serif; color: var(--ink-dim); }
.nxt-text span { display: block; }
.nxt-side { display: flex; flex-direction: column; align-items: flex-start; gap: 14px; }
.nxt-below { margin: 0; max-width: 44ch; font: 400 14px/20px "Inter", sans-serif; color: var(--ink-mute); }
.lab .imp-stage { margin-top: 56px; }

/* ---------- Contact: the real callback form, channels, briefs as a line ---------- */
.ctc { margin-top: 56px; padding: 0 var(--g); }
/* Потолок воздуха над рамкой футера — 32 (COMPONENTS.md, закон 7). Было 48:
   от строки до контура 48, от последней буквы © до контура 62 — одинаково на
   всех ширинах, шире поля, на котором сама рамка стоит. */
.lab--home > .ftr { margin-top: 32px; }
.ctc-panel {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(320px, 1fr);
  grid-template-rows: auto auto;
  gap: 8px;
  padding: 8px;
  border-radius: 38px 38px 24px 24px;
  background: var(--plate);
  color: #171719;
}
.ctc-intro { grid-column: 1; grid-row: 1; display: flex; flex-direction: column; min-width: 0; padding: 24px 24px 8px; }
.ctc-title { margin: 0; max-width: 18ch; font: 600 36px/40px "Inter", sans-serif; letter-spacing: -0.02em; text-transform: uppercase; }
.ctc-lead { margin: 16px 0 0; max-width: 52ch; font: 400 18px/26px "Inter", sans-serif; color: #2c2c2c; }
.ctc-briefs { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px; margin: 28px 0 0; font: 400 14px/20px "Inter", sans-serif; color: #444448; }
.ctc-briefs .lab-eyebrow { flex-basis: 100%; color: #5c5c60; }
.ctc-brief {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  margin-block: -12px;
  padding: 0 2px;
  color: #171719;
  text-decoration: underline;
  text-underline-offset: 4px;
  text-decoration-color: rgba(23, 23, 25, 0.35);
  -webkit-tap-highlight-color: transparent;
  transition: text-decoration-color var(--lab-out) linear;
}
.ctc-brief:hover, .ctc-brief:active { text-decoration-color: currentColor; transition-duration: var(--lab-in); }
.ctc-brief:focus-visible { outline: 2px solid #171719; outline-offset: 2px; border-radius: 4px; }
.ctc-dot { color: #8a8a8f; }
.ctc-panel .ctc-form { grid-column: 2; grid-row: 1 / 3; min-height: 0; }
.ctc-panel .brf-channels { grid-column: 1; grid-row: 2; align-self: end; }
.brf-channel, .brf-channel *, .brf-send { -webkit-user-select: none; user-select: none; -webkit-tap-highlight-color: transparent; }
.imp-system button { -webkit-user-select: none; user-select: none; -webkit-tap-highlight-color: transparent; }

/* ============================================================
   SERVICE PAGES, CASE PREVIEWS
   ============================================================ */
.sp { padding: calc(var(--hdr-h) + 40px) 0 96px; color: var(--ink); }
.sp-head { padding: 0 var(--g); }
.sp-crumb { margin: 0; font: 500 13px/16px "Inter", sans-serif; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-mute); }
.sp-crumb a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  margin-block: -14px;
  padding: 0 2px;
  color: var(--ink-dim);
  text-decoration: underline;
  text-decoration-color: transparent;
  text-underline-offset: 4px;
  -webkit-user-select: none;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
  transition: text-decoration-color var(--lab-out) linear;
}
.sp-crumb a:hover, .sp-crumb a:active { text-decoration-color: currentColor; transition-duration: var(--lab-in); }
.sp-crumb a:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; border-radius: 4px; }
.sp-kicker { margin-bottom: 12px; }
.sp-headgrid { display: grid; grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr); gap: 24px 32px; align-items: end; margin-top: 20px; }
.sp-title { margin: 0; font: 600 clamp(36px, 4.2vw, 64px) / 1 "Inter", sans-serif; letter-spacing: -0.03em; text-transform: uppercase; }
.sp-meta { margin: 16px 0 0; font: 500 14px/20px "Inter", sans-serif; letter-spacing: 0.06em; text-transform: uppercase; color: var(--ink-mute); }
.sp-explain { margin: 0; max-width: 58ch; font: 400 18px/26px "Inter", sans-serif; color: var(--ink-dim); }

/* ---------- Ribbon: kinds of work, the current one marked ---------- */
.rib { margin-top: 40px; padding: 0 var(--g); }
.rib-wrap { position: relative; }
.rib-wrap::after, .rib-wrap::before {
  content: "";
  position: absolute;
  top: 0; bottom: 0;
  width: 56px;
  pointer-events: none;
  opacity: 1;
  transition: opacity 160ms linear;
}
.rib-wrap::after { right: 0; background: linear-gradient(90deg, rgba(23, 23, 25, 0), var(--ground)); }
.rib-wrap::before { left: 0; background: linear-gradient(270deg, rgba(23, 23, 25, 0), var(--ground)); }
.rib-wrap[data-at-end]::after, .rib-wrap[data-at-start]::before { opacity: 0; }
.rib-track {
  position: relative;
  display: flex;
  gap: 8px;
  overflow-x: auto;
  scroll-snap-type: x proximity;
  scrollbar-width: none;
  padding: 5px 5px 8px;
  margin: -5px -5px 0;
}
.rib-track::-webkit-scrollbar { display: none; }
.rib-item {
  flex: 1 0 auto;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 4px;
  min-width: 172px;
  min-height: 72px;
  padding: 14px 18px;
  border-radius: 16px;
  background: var(--panel);
  box-shadow: inset 0 0 0 1px rgba(234, 234, 234, 0.10);
  color: var(--ink);
  text-decoration: none;
  scroll-snap-align: start;
  -webkit-user-select: none;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
  transition: box-shadow var(--lab-out) var(--lab-ease);
}
.rib-name { font: 500 16px/20px "Inter", sans-serif; letter-spacing: -0.01em; white-space: nowrap; }
.rib-count { font: 400 13px/16px "Inter", sans-serif; color: var(--ink-mute); white-space: nowrap; }
.rib-item:not([aria-current]):hover, .rib-item:not([aria-current]):active { box-shadow: inset 0 0 0 1px var(--ink); transition-duration: var(--lab-in); }
.rib-item:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }
.rib-item[aria-current="page"] { background: var(--plate); color: #171719; box-shadow: none; }
.rib-item[aria-current="page"] .rib-count { color: #5c5c60; }

/* ---------- Visuals: two frames shared by the whole service ---------- */
.spv { margin-top: 40px; padding: 0 var(--g); }
.spv-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
.spv-frame { position: relative; display: flex; flex-direction: column; min-width: 0; margin: 0; padding: 4px; border-radius: 20px; background: var(--panel); color: var(--ink); }
.spv-media { aspect-ratio: 16 / 10; overflow: hidden; border-radius: 16px; background: #1d1d1f; }
.spv-media img { display: block; width: 100%; height: 100%; object-fit: cover; object-position: top; }
.spv-frame.is-focus-left .spv-media img { object-position: left top; }
.spv-cap { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 14px 14px 12px; font: 400 14px/20px "Inter", sans-serif; color: var(--ink-dim); }

/* ---------- Comparison: options in columns, criteria in rows, groups ---------- */
.cmp {
  margin-top: 72px;
  padding: 0 var(--g);
  /* PLACEHOLDER hue for the SKARR.PRO highlight — not decided; Alexa sends the
     final one. Everything below derives from this single variable. */
  --cmp-accent: #8f6bff;
  --cmp-accent-soft: color-mix(in srgb, var(--cmp-accent) 14%, transparent);
  --cmp-accent-faint: color-mix(in srgb, var(--cmp-accent) 5%, transparent);
  --cmp-accent-glow: color-mix(in srgb, var(--cmp-accent) 45%, transparent);
  --cmp-accent-plate: color-mix(in srgb, var(--cmp-accent) 14%, var(--ground));
}
.cmp-order {
  max-width: 44ch;
  padding: 16px 18px;
  border-radius: 14px;
  background: var(--panel);
  font: 400 14px/20px "Inter", sans-serif;
  color: var(--ink-dim);
}
.cmp-order p { margin: 6px 0 0; }
.cmp-order .lab-eyebrow { margin: 0; }
.cmp-tabs { display: none; }
.cmp-wrap { position: relative; margin-top: 28px; border-radius: 20px; }
/* SKARR.PRO: ONE continuous highlight behind the whole column — the tier
   name, the price, Buy and every row, straight through the group bars, no
   gaps (Alexa, 16.09.2026, after the «Ultimate» card of reactbits.dev): a
   frame and a soft glow, the content above it. compare.js sets left/width
   from the real column geometry; top and bottom are the table's own. */
.cmp-glow {
  position: absolute;
  top: 0;
  bottom: 0;
  z-index: 0;
  border-radius: 20px;
  border: 1.5px solid var(--cmp-accent);
  background: linear-gradient(180deg, var(--cmp-accent-soft), var(--cmp-accent-faint) 55%, var(--cmp-accent-soft));
  box-shadow: 0 0 60px 10px var(--cmp-accent-glow);
  pointer-events: none;
}
.cmp-glow[hidden] { display: none; }
.cmp-table { position: relative; z-index: 1; width: 100%; border-collapse: separate; border-spacing: 0; table-layout: fixed; color: var(--ink); }
.cmp-table th, .cmp-table td { padding: 20px 20px 22px 0; border-top: 1px solid var(--line); text-align: left; vertical-align: top; }
.cmp-table thead th { padding-top: 0; padding-bottom: 20px; border-top: 0; vertical-align: top; }
.cmp-table th[scope="row"], .cmp-corner { width: 20%; }
.cmp-table th[data-tier], .cmp-table td[data-tier] { padding-left: 16px; padding-right: 16px; }
.cmp-row th[scope="row"] { padding-top: 24px; font: 500 12px/16px "Inter", sans-serif; letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink-mute); }
.cmp-tier { display: block; font: 500 12px/16px "Inter", sans-serif; letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink-mute); }
.cmp-price { display: block; margin-top: 10px; font: 600 36px/40px "Inter", sans-serif; letter-spacing: -0.02em; white-space: nowrap; }
.cmp-per { font: 500 16px/20px "Inter", sans-serif; letter-spacing: 0; color: var(--ink-dim); }
.cmp-period { display: block; margin-top: 6px; font: 400 14px/20px "Inter", sans-serif; color: var(--ink-mute); }
.cmp-buy { display: block; margin-top: 16px; }
.cmp-buy .lab-btn { display: flex; width: 100%; }
.cmp-test { margin: 10px 0 0; font: 400 13px/18px "Inter", sans-serif; color: var(--ink-mute); }
.cmp-test--soon { color: #a8a8ad; }
.cmp-test[hidden] { display: none; }
.cmp-cell-label { display: none; }
.cmp-prose { margin: 0; max-width: 36ch; font: 400 16px/24px "Inter", sans-serif; }
/* Group rows: a name, and for a secondary group the toggle. */
.cmp-group-head th { padding: 28px 0 6px; border-top: 0; }
.cmp-group-head .cmp-group-name { font: 500 12px/16px "Inter", sans-serif; letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink-dim); }
.cmp-group:first-of-type .cmp-group-head th { padding-top: 8px; }
.cmp-toggle {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  margin-block: -8px;
  margin-left: 12px;
  padding: 0 12px;
  border: 0;
  border-radius: 999px;
  background: transparent;
  box-shadow: inset 0 0 0 1px var(--line);
  color: var(--ink-dim);
  font: 500 11px/16px "Inter", sans-serif;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  cursor: pointer;
  -webkit-user-select: none;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
  transition: background-color var(--lab-out) var(--lab-ease), box-shadow var(--lab-out) var(--lab-ease);
}
.cmp-toggle:hover, .cmp-toggle:active, .cmp-toggle:focus-visible { background: rgba(234, 234, 234, 0.08); box-shadow: inset 0 0 0 1px var(--ink); transition-duration: var(--lab-in); }
.cmp-toggle:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.cmp-row[hidden] { display: none; }
@media (min-width: 720px) {
  .cmp-table thead th { position: sticky; top: 0; z-index: 2; padding-top: 20px; }
  /* Once the head is stuck it is a plate over the rows; the PRO cell keeps the
     column's tint and its two side lines, so the block reads continuous. */
  .cmp-wrap.is-stuck thead th { background: var(--ground); box-shadow: 0 1px 0 var(--line); }
  .cmp-wrap.is-stuck thead th[data-tier="pro"] { background: var(--cmp-accent-plate); box-shadow: inset 1.5px 0 0 var(--cmp-accent), inset -1.5px 0 0 var(--cmp-accent), 0 1px 0 var(--line); }
}

/* ---------- Contact strip on sub-pages ---------- */
.spc { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 16px 24px; align-items: center; margin: 72px var(--g) 0; padding-top: 32px; border-top: 1px solid var(--line); }
.spc-title { margin: 0; font: 600 24px/28px "Inter", sans-serif; letter-spacing: -0.02em; text-transform: uppercase; }
.spc p { margin: 8px 0 0; max-width: 52ch; font: 400 16px/24px "Inter", sans-serif; color: var(--ink-dim); }

/* ---------- Service Redesign page ---------- */
.rdt { display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr); gap: 12px; margin-top: 40px; padding: 0 var(--g); }
.rdt-thesis { padding: 28px; border-radius: 20px; background: var(--plate); color: #171719; }
.rdt-title { margin: 0; max-width: 16ch; font: 600 clamp(28px, 2.8vw, 40px) / 1.08 "Inter", sans-serif; letter-spacing: -0.02em; }
.rdt-thesis p { margin: 16px 0 0; max-width: 52ch; font: 400 17px/25px "Inter", sans-serif; color: #2c2c2c; }
.rdt-path { display: flex; flex-direction: column; gap: 12px; padding: 24px; border-radius: 20px; background: var(--panel); }
.rdt-path-frame {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  gap: 12px;
  min-height: 220px;
  padding: 20px;
  border: 1px dashed rgba(234, 234, 234, 0.32);
  border-radius: 14px;
  background: repeating-linear-gradient(135deg, rgba(234, 234, 234, 0.04) 0 12px, transparent 12px 24px), #1d1d1f;
}
.rdt-path-frame .lab-pending { align-self: flex-start; }
.rdt-path-frame p { margin: 0; max-width: 40ch; font: 400 14px/20px "Inter", sans-serif; color: var(--ink-mute); }
.rde { margin-top: 72px; padding: 0 var(--g); }
.rde-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; margin: 28px 0 0; padding: 0; list-style: none; }
.rde-card { display: flex; flex-direction: column; gap: 12px; padding: 24px; border-radius: 20px; background: var(--panel); box-shadow: inset 0 0 0 1px rgba(234, 234, 234, 0.10); }
.rde-num { font: 500 12px/16px "Inter", sans-serif; letter-spacing: 0.14em; color: var(--ink-mute); }
.rde-card h3 { margin: 0; font: 600 24px/26px "Inter", sans-serif; letter-spacing: -0.02em; text-transform: uppercase; }
.rde-card p { margin: 0; font: 400 15px/22px "Inter", sans-serif; color: var(--ink-dim); }
.rde-price { display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px 12px; margin-top: auto; padding-top: 16px; border-top: 1px solid var(--line); }
.rde-price strong { font: 600 28px/32px "Inter", sans-serif; letter-spacing: -0.02em; font-variant-numeric: tabular-nums; }
.rde-price > span:not(.lab-pending) { font: 400 14px/20px "Inter", sans-serif; color: var(--ink-mute); }
.rde-price .lab-pending { height: 26px; font-size: 11px; color: var(--ink-dim); }
.rde-buy .lab-btn { display: flex; width: 100%; margin-top: 12px; }
.rde-buy .cmp-test { margin-top: 8px; }
.rde-actions { margin-top: 24px; }

/* ---------- Case previews ---------- */
.csp { margin-top: 40px; padding: 0 var(--g); }
.csp-grid { display: grid; grid-template-columns: minmax(0, 2fr) minmax(300px, 1fr); gap: 12px; align-items: start; }
.csp-frame { grid-column: 1; }
.csp-facts { grid-column: 2; grid-row: 1 / span 4; position: sticky; top: 24px; display: flex; flex-direction: column; gap: 14px; padding: 24px; border-radius: 20px; background: var(--plate); color: #171719; }
.csp-facts .lab-eyebrow { color: #5c5c60; }
.csp-facts ul { margin: 0; padding: 0; list-style: none; display: grid; gap: 10px; font: 400 15px/22px "Inter", sans-serif; }
.csp-facts li { position: relative; padding-left: 16px; }
.csp-facts li::before { content: ""; position: absolute; left: 0; top: 9px; width: 5px; height: 5px; border-radius: 50%; background: #171719; }
.csp-note { margin: 4px 0 0; font: 400 14px/20px "Inter", sans-serif; color: #444448; }
.csp-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: auto; padding-top: 12px; }
.csp-actions .lab-btn--light { --btn-bg: #171719; --btn-ink: #eaeaea; --btn-fill: var(--ww); --btn-fill-ink: #171719; --btn-focus: #171719; }
.csp-actions .lab-btn--ghost { --btn-ring: inset 0 0 0 1px #171719; --btn-ink: #171719; --btn-fill: #171719; --btn-fill-ink: #eaeaea; --btn-focus: #171719; }

/* ============================================================
   Bands
   ============================================================ */
@media (max-width: 1200px) {
  .cat-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .svs-grid { gap: 10px; }
  .svs-title { font-size: 22px; line-height: 22px; }
  .svr-link { grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr); }
  .svr-cta { grid-column: 1 / -1; justify-self: end; }
  .cse-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 1024px) {
  .hero { padding-top: calc(var(--hdr-h) + 32px); }
  .svs { margin-top: 56px; }
  .cse { margin-top: 72px; }
  .nxt { margin-top: 64px; grid-template-columns: minmax(0, 1fr); gap: 20px; }
  .sps-card { grid-template-columns: minmax(0, 1fr); }
  .sps-visual { order: -1; min-height: 320px; }
  /* One column: the copy's head splits in two — eyebrow and title on the
     left, the chips with the description on the right — so the width beside
     the short title works instead of standing empty, and the chips wrap in
     their own column instead of one tight line (Alexa's marked iPad shot,
     16.09.2026, pool 3). Prices and the buttons keep the full width below. */
  .sps-copy--split { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); column-gap: 32px; align-content: start; }
  .sps-copy--split .sps-info .sps-tags { margin-top: 0; }
  .sps-copy--split .sps-prices, .sps-copy--split .sps-buy { grid-column: 1 / -1; }
  .sp { padding-top: calc(var(--hdr-h) + 32px); }
  .sp-headgrid { grid-template-columns: minmax(0, 1fr); align-items: start; }
  .cmp-price { font-size: 30px; line-height: 34px; }
  .cmp-order { max-width: none; }
  .ctc-panel { grid-template-columns: minmax(0, 1fr) minmax(300px, 0.9fr); }
  .csp-grid { grid-template-columns: minmax(0, 1fr); }
  .csp-facts { grid-column: 1; grid-row: 2; position: static; }
}

@media (max-width: 768px) {
  .cat-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .spv-grid { grid-template-columns: minmax(0, 1fr); }
  .cse-grid { grid-template-columns: minmax(0, 1fr); }
  .rdt { grid-template-columns: minmax(0, 1fr); }
  .rde-grid { grid-template-columns: minmax(0, 1fr); }
  .cmp-table th, .cmp-table td { padding-right: 12px; }
}

@media (max-width: 719.98px) {
  .hero { padding-top: calc(var(--hdr-h) + 20px); }
  /* Кегль привязан к мере, а не к кадру: замер 320…719 даёт 8.30vw — предел, на
     котором «Websites that work.» ещё стоит одной строкой. Взято 8vw, тот же
     предел с запасом 3.5 % на подстановку гарнитуры. Выше него браузер рвёт
     фразу посередине, и три утверждения читаются одним блоком из шести строк.

     Ритм строк один на весь заголовок — её правка 20.09.2026: «у строк разные
     отступы между друг другом, надо подогнать визуально, чтобы были
     симметрично». Прежде промежуток между утверждениями задавал gap 0.24em
     поверх интерлиньяжа 1, а перенос внутри фразы шёл без него: на телефоне
     выходили три шага по 1.24em и один по 1.00em, и заголовок рассыпался.
     Теперь шаг несёт один интерлиньяж, gap ноль — переходы равны независимо от
     того, граница это фразы или перенос внутри неё. Прежнее обоснование
     «промежуток между утверждениями крупнее внутреннего интерлиньяжа» её
     словом отменено. 1.12 — то значение, при котором высота заголовка не
     меняется ни на одной ширине 320…719 (157.7 на 440, 140.8 на 393, 129 на
     360, 114.6 на 320 — те же числа, что до правки): правится ритм и только
     он, ничто ниже не двигается. Переменная — чтобы стенд
     new-home/preview/hero-lead.html переключал интерлиньяж живьём. */
  .hero-title { font-size: clamp(25px, 8vw, 44px); line-height: var(--hero-lead, 1.12); gap: 0; }
  /* Авторских переносов в заголовке нет: третью фразу, которая в меру не
     влезает, делит balance — сама она роняет вдову в одно слово. */
  .hero-line { display: block; white-space: normal; text-wrap: balance; }
  .hero-title .hero-frag { display: none; }
  .hero-sub { margin-top: 16px; font-size: 16px; line-height: 24px; }
  /* The fragments move into their own row between the thesis and the buttons. */
  .hero-strip { display: flex; gap: 8px; margin-top: 18px; }
  .hero-strip .hero-frag { flex: 1 1 0; width: auto; height: 96px; border-radius: 12px; transition: flex-grow var(--lab-out) var(--lab-ease); }
  .hero-strip .hero-frag.is-open { flex-grow: 2.2; width: auto; transition-duration: var(--lab-in); }
  .hero-actions { margin-top: 18px; }
  .hero-actions .lab-btn { flex: 1 1 100%; display: flex; }
  .svs { margin-top: 40px; }
  .cat { margin-top: 16px; }
  .cat-grid { grid-template-columns: minmax(0, 1fr); gap: 6px; }
  .cat-item { min-height: 0; padding: 12px 14px 12px 12px; }
  .cat-line { -webkit-line-clamp: 1; }
  .cse { margin-top: 56px; }
  .nxt { margin-top: 48px; padding-top: 24px; }
  .nxt-title { font-size: 26px; line-height: 28px; }
  .nxt-text { font-size: 16px; line-height: 24px; }
  .nxt-side .lab-btn { align-self: stretch; display: flex; }
  .lab .imp-stage { margin-top: 40px; }
  .ctc { margin-top: 40px; }
  .hs-nav { margin-top: 16px; }
  .sps-card { margin-top: 16px; }
  /* The action stands on the card's own edge, not in the copy field (Alexa,
     20.09.2026): 4 left, right and bottom — the plate's padding and nothing
     more, the same line the visual keeps. The copy keeps its 16 for the
     reading column; the button alone steps back out of it. */
  .sps-copy { padding: 20px 16px 0; }
  /* Phones: too narrow for two columns — the head and the info stack again. */
  .sps-copy--split { display: flex; }
  .sps-copy--split .sps-info .sps-tags { margin-top: 16px; }
  .sps-prices { grid-template-columns: minmax(0, 1fr); gap: 16px; margin-top: 24px; padding-top: 18px; }
  .sps-price + .sps-price { padding-top: 16px; border-top: 1px solid var(--line-dark); }
  .sps-buy { padding-top: 24px; margin-inline: -16px; }
  /* The row itself is left to stretch — a width of 100% here would measure the
     copy field and leave the action 32 short of the card's right edge. Only
     the item inside it runs the full measure, and the press note steps back
     into the reading column. */
  .sps-buy-item { width: 100%; }
  .sps-buy .cmp-test { padding-inline: 16px; }
  .sps-buy .lab-btn { display: flex; width: 100%; }
  .sps-visual { min-height: 240px; }
  .svs-grid { grid-template-columns: minmax(0, 1fr); gap: 8px; }
  .svs-body { gap: 10px; padding: 14px 12px 24px; }
  .svr-link { grid-template-columns: minmax(0, 1fr); gap: 20px; padding: 20px 16px; }
  .svr-title { font-size: 26px; line-height: 28px; }
  .svr-cta { justify-self: end; display: flex; }
  .cse-grid { gap: 8px; }
  .cse-title { font-size: 22px; line-height: 24px; }
  .ctc-panel { grid-template-columns: minmax(0, 1fr); grid-template-rows: auto; padding: 8px; border-radius: 24px; }
  .ctc-intro { grid-row: auto; padding: 16px 12px 12px; }
  .ctc-title { font-size: 28px; line-height: 30px; }
  .ctc-lead { font-size: 16px; line-height: 24px; }
  .ctc-briefs { margin-top: 20px; }
  .ctc-panel .ctc-form, .ctc-panel .brf-channels { grid-column: auto; grid-row: auto; }
  .ctc-panel .brf-contact { min-height: 0; padding: 16px; border-radius: 18px; gap: 20px; }
  .ctc-panel .brf-contact-title { padding: 0; font-size: 24px; line-height: 26px; }
  .ctc-panel .brf-contact-fields { margin-top: 0; gap: 8px; padding: 0; }
  .ctc-panel .brf-inp-dark { height: 44px; padding: 0 12px; }
  .ctc-panel .brf-send { min-height: 44px; padding: 10px 12px; font-size: 14px; }
  .sp { padding-top: calc(var(--hdr-h) + 20px); padding-bottom: 72px; }
  .sp-headgrid { margin-top: 16px; }
  .sp-explain { font-size: 16px; line-height: 24px; }
  .rib { margin-top: 32px; }
  .rib-item { min-width: 160px; min-height: 64px; padding: 12px 16px; }
  .spv { margin-top: 32px; }
  .spv-cap { flex-wrap: wrap; gap: 8px 16px; }
  .cmp { margin-top: 56px; }
  /* Tabs switch the visible option; the criteria stay next to its values. */
  .cmp-tabs {
    position: sticky;
    top: 8px;
    z-index: 3;
    display: flex;
    gap: 4px;
    margin-top: 20px;
    padding: 4px;
    border-radius: 999px;
    background: var(--panel);
    box-shadow: 0 10px 30px rgba(0, 0, 0, 0.35), inset 0 0 0 1px rgba(234, 234, 234, 0.14);
  }
  .cmp-tab {
    flex: 1 1 0;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 5px;
    min-width: 0;
    height: 48px;
    padding: 0 6px;
    border: 0;
    border-radius: 999px;
    background: transparent;
    color: var(--ink);
    font: 600 11px/14px "Inter", sans-serif;
    letter-spacing: 0.02em;
    text-transform: uppercase;
    white-space: nowrap;
    cursor: pointer;
    -webkit-user-select: none;
    user-select: none;
    -webkit-tap-highlight-color: transparent;
    transition: background-color var(--lab-out) var(--lab-ease), color var(--lab-out) linear;
  }
  .cmp-tab[aria-selected="true"] { background: var(--plate); color: #171719; transition-duration: var(--lab-in); }
  .cmp-tab:focus-visible { outline: 2px solid var(--ink); outline-offset: -3px; }
  .cmp-tab-price { font: 500 11px/14px "Inter", sans-serif; letter-spacing: 0; text-transform: none; opacity: 0.8; }
  .cmp-wrap { margin-top: 16px; }
  .cmp-table, .cmp-table thead, .cmp-table tbody, .cmp-table tr, .cmp-table th, .cmp-table td { display: block; width: auto; }
  .cmp-corner, .cmp-table [data-tier] { display: none; }
  .cmp-wrap[data-tier="lite"] [data-tier="lite"],
  .cmp-wrap[data-tier="skarr"] [data-tier="skarr"],
  .cmp-wrap[data-tier="pro"] [data-tier="pro"] { display: block; }
  .cmp-table th[data-tier], .cmp-table td[data-tier] { padding-left: 0; padding-right: 0; }
  .cmp-table thead th { position: static; padding: 4px 0 20px; border: 0; }
  .cmp-price { font-size: 32px; line-height: 36px; }
  .cmp-group-head th { padding: 20px 0 4px; }
  .cmp-group:first-of-type .cmp-group-head th { padding-top: 4px; }
  .cmp-row th[scope="row"] { width: auto; padding: 14px 0 4px; border-top: 1px solid var(--line); }
  .cmp-row td { padding: 0 0 14px; border-top: 0; }
  .cmp-prose { max-width: none; font-size: 15px; line-height: 22px; }
  .spc { grid-template-columns: minmax(0, 1fr); margin-top: 56px; }
  .spc .lab-btn { display: flex; }
  .rdt-thesis, .rdt-path { padding: 20px 16px; }
  .rde-actions .lab-btn { display: flex; }
  .csp-actions .lab-btn { flex: 1 1 100%; display: flex; }
}

@media (max-width: 430px) {
  .sps-title { font-size: 26px; }
  .sps-price strong { font-size: 30px; line-height: 34px; }
  .cmp-price { font-size: 28px; line-height: 32px; }
  .hero-strip .hero-frag { height: 84px; }
}

@media (max-width: 375px) {
  .svs-line { font-size: 14px; line-height: 21px; }
  .rib-item { min-width: 152px; }
}

@media (max-width: 320px) {
  .hero-actions .lab-btn, .cmp-buy .lab-btn, .spc .lab-btn, .sps-buy .lab-btn, .csp-actions .lab-btn { padding: 0 16px; }
}

/* ---------- Перенос в строке каталога на широком экране (Alexa, 20.09.2026) --
   «Переносы текстов организуйте, пожалуйста, проверьте, чтобы были» — пять
   размеченных строк на снимке с 2560. Каждая её черта стоит на границе, с
   которой начинается хвост: «launched | as a working site.», «content | and
   design built as one system.», «finished design: | responsive, connected to
   your data.», «the audience, | the product model and the core interface.»,
   «works | — and where the customer experience could work better.» Сами фразы
   заданы в new-home/src/content.mjs (`catTail`) и проверяются сборкой.

   Хвост и так неразрывен (`.lab-tail` — inline-block), поэтому на любой мере
   он уходит на вторую строку целиком. Но на широком экране вся фраза влезает
   в одну строку, и переноса не возникает вовсе — на 2560 так стояли пять
   карточек из восьми. Здесь хвост становится блоком: строка делится всегда.

   1920 — замер, а не круглое число. Строка каталога обрезана двумя строками
   (`-webkit-line-clamp: 2`), значит голова обязана уместиться в одну, иначе
   хвост уедет под обрез. Самая длинная голова — «Work that starts before the
   screens: the task, the audience,» (363.6 при кегле 13), мера колонки в
   сетке из четырёх равна (vw − 72) / 4 − 97, и 363.6 она даёт на 1915.
   Ниже 1920 строка обрезается на полуслове в любом случае, и неразрывный
   хвост там только крадёт место: замер на 1512 — 5 карточек из 8 не влезают,
   и с хвостом-блоком видно на 3–6 слов меньше, чем при обычном переносе.
   Поэтому ниже полосы хвост живёт как простой текст, а короткие слова держит
   склейка в new-home/build.mjs (`noDangle`), чтобы «as a» не осталось в конце
   строки. */
.cat-line .lab-tail { display: inline; }

@media (min-width: 1920px) {
  .cat-line .lab-tail { display: block; }
}

/* ---------- Главная услуга на широком экране (Alexa, 20.09.2026) ----------
   «Эта карточка до сих пор маленькая… она должна быть большой карточкой, это
   главная услуга, и картинка может быть шире… вспомни, как было на основной
   главной: изображение практически вот так открывалось».

   Было — карточка главной услуги старой главной, css/03-service-ecom.css,
   кадр Figma 1600: высота 756, тёмная рамка от 576 из 1552 ширины карточки
   (37.1 %), деньги и кнопка внизу на кромке. Оттуда все три числа полосы.

   1. Колонки 1 : 1.7 — под текст те же 37.2 % карточки, остальное картинке
      (на 2560 рамка 1310 → 1574). Ниже 1440 доля не трогается: при колонке
      уже 480 строка «$1,500 / month» (185 по содержимому) перестаёт влезать
      в свой столбец цены — замерено, на 1200 она уже обрезается.
   2. Высота карточки идёт за окном, а не стоит числом. Три её замера в один
      день дали обе границы. Сначала 800 по линиям на снимках (оранжевая 794,
      зелёная 807 от верха карточки), затем «ещё процентов на 12» — 896 на 2K.
      Постоянные 888 держались и на ноутбуке: «на 2К ещё куда ни шло, но на
      десктопе надо делать иначе» — на 1512 рамка становилась 914×888, почти
      квадратом, с дырой в 236 в колонке текста. Отдав высоту целиком форме
      рамки, я получил обратное: «не нужно делать опять маленькая карточка,
      теперь тык в притык» — карточка села на собственную высоту текста (659),
      и просвет над линией цен исчез совсем. Поэтому пол — прямая через две её
      точки: 760 на 1512 и 896 на 2560 (12.98·vw + 555.8 для рамки). Выше 2560
      её сменяет форма 2K — 1574×888, то есть 1.7725: одна и та же обрезка
      кадра на ультрашироких (на 3440 карточка 1208, 90 % высоты снимка), тогда
      как прямая дала бы там плоские 2.12. Обе ветви сходятся ровно на 2560.
   2а. Просвет над линией цен не может быть нулём. `margin-top: auto` съедает
      весь свободный запас, а когда его нет — даёт ноль, и чипсы упираются в
      линию. Базовые 32 поэтому сняты с `auto` и отданы блоку чипсов: гарантия
      снизу, поверх неё ложится запас. Замер: 132 на 1512, 335 на 2560.
   3. Деньги и действие стоят на полу карточки, весь новый воздух собирается
      одним просветом над линией цен — как на старой главной, где перки и
      плашка цены стояли внизу, а воздух был над ними.

   Кнопка лежит на кромке плиты: 4 слева и снизу от внешнего края карточки.
   Сначала было 10 — мера кнопки карточки услуги (плашка 4 + её 6), «как
   остальные карточки»; посмотрев вживую, она сказала: «отступ у кнопки
   слишком большой в том и другом случае, кнопка должна быть поближе к
   границе». Ближе 4 ставить некуда: это поле самой плиты, тот же зазор, на
   котором стоит рамка картинки. 28 поля копии − 28 = 0, остаются 4 плиты.

   Форма пишется делением, а не `aspect-ratio`: вместе с `min-height` она
   задаёт рамке минимальную ширину 1584, и на 1441 и 2000 страница получает
   горизонтальную прокрутку — замерено, `min-width: 0` её не снимает.

   Полоса только для главной: `#dealer`, а не `.sps-card` — ту же разметку
   держит карточка приложения на /apps, её геометрия остаётся прежней.
   И только горизонтальное окно: повёрнутый 2K (1440×2560) проходит по ширине,
   но там действует вертикальная раскладка — своя рамка 460 и форма 4:5. */
@media (min-width: 1440px) and (orientation: landscape) {
  #dealer.sps-card { grid-template-columns: minmax(0, 1fr) minmax(0, 1.7fr); }
  #dealer .sps-visual { min-height: max(calc(12.98vw + 555.8px), calc((62.95vw - 37.5px) / 1.7725)); }
  #dealer .sps-info { margin-bottom: 32px; }
  #dealer .sps-prices { margin-top: auto; }
  #dealer .sps-buy { margin-top: 0; }
}

/* ---------- Reduced motion: states change at once, nothing travels, no idle drift ---------- */
@media (prefers-reduced-motion: reduce) {
  :root { --lab-in: 1ms; --lab-out: 1ms; }
  .rib-wrap::after, .rib-wrap::before { transition-duration: 1ms; }
}

/* ---------- Forced colours: shapes survive without the fill layers ---------- */
@media (forced-colors: active) {
  .lab-btn, .hs-tab, .rib-item, .cat-item, .cmp-tab, .cmp-toggle, .ctc-brief, .hero-frag { border: 1px solid ButtonText; }
  .lab-btn::after, .hs-tab::after { display: none; }
  .hs-tab.cs-tab--active, .rib-item[aria-current="page"], .cmp-tab[aria-selected="true"] { outline: 2px solid Highlight; outline-offset: -2px; }
  .cmp-glow { display: none; }
}

/* ============================================================
   Hero главной — центральная выключка. Её решение 20.09.2026: «мне нравится
   то, что я сейчас вижу», воздух первого экрана — «72 / 28».

   Правила жили отдельным слоем в new-home/preview/hero-center.css, пока вариант
   смотрели на localhost; в тот же день она сказала переводить в прод всё, что
   можно, и слой переехал сюда целиком, без изменений. Класс `.hero--center`
   оставлен: он выше `.hero` по весу, поэтому порядок правил в файле роли не
   играет, а откат — одна строка в new-home/build.mjs, а не разбор этого блока.
   Центр живёт только в первом экране главной: каталог, цены, списки и карточки
   остаются слева.
   ============================================================ */

.hero--center { text-align: center; }
/* Строка целиком — текст и вошедшая в него плитка — встаёт на ось своим
   содержимым: строка остаётся во всю меру (`align-items: stretch` у колонки
   заголовка), а по центру её ставит `justify-content`. Ужимать саму строку до
   содержимого (`align-items: center` у .hero-title) нельзя: тогда её ширина
   считается по детям, процент в ширине раскрытой плитки становится
   циклическим, и плитка схлопывается в ноль — замер 20.09.2026 на 1440
   показал ровно это. */
.hero--center .hero-line { justify-content: center; }

/* Пояснение — одна строка, а не центрированный абзац: у абзаца по центру каждая
   следующая строка начинается в новом месте. Мера взята по замеру: 76ch держат
   фразу одной строкой от 1024 и шире, ниже она ложится в две. */
.hero--center .hero-sub { max-width: min(100%, 76ch); margin-inline: auto; }
.hero--center .hero-actions { justify-content: center; }

/* Раскрытая плитка не имеет права развалить строку. Строка не переносится
   (`white-space: nowrap`), поэтому всё, что не поместилось в меру, ушло бы в
   горизонтальный скролл, а по закону раскрытия (#070, п. 1) высота блока от
   раскрытия меняться не должна вовсе. Замер на 1440 (кегль 77.76): самая
   длинная строка с плиткой — «Websites» 380.08 + «that work.» 474.70 + два
   зазора 31.10 = 885.88, это 11.39em. Взято 11.6em с запасом на подстановку
   гарнитуры; остаток меры — плитке. Проценты считаются от меры строки, а не от
   100vw: vw шире на полосу прокрутки. */
.hero--center .hero-line--split .hero-frag.is-open {
  width: min(max(4.2em, 240px), calc(100% - 11.6em));
}

/* Телефон: плитки уходят из заголовка в свою строку (правило ≤719.98 выше), и
   эта строка тоже встаёт на ось. */
@media (max-width: 719.98px) {
  .hero--center .hero-strip { justify-content: center; }
}

/* Воздух первого экрана. Три её шага подряд: «на 40 % больше сверху и снизу» →
   «сверху чуть больше, 64 на 48» → «72 / 28». Итог: сверху +72 %, снизу +28 %
   от величин выше — снизу воздуха и так много, блок ставится на ось.

   Считается только просвет, который виден глазу, а не вся величина padding: в
   `calc(var(--hdr-h) + 40px)` первое слагаемое — высота самой шапки, место под
   ней, а не отступ. Растёт второе: 40 → 68.8, 32 → 54.4, 20 → 34.4 по полосам.

   Снизу у .hero ноль: просвет до каталога задаёт `.svs` своим margin-top
   (64 / 56 / 40 по тем же полосам). Его не трогаем — +28 % добираются
   собственным padding-bottom героя: 17.92 / 15.68 / 11.2, в сумме
   81.92 / 71.68 / 51.2. Соседние поля здесь не схлопываются, поэтому просветы
   складываются. Перекос верх/низ был 1 : 1.6, стал 1 : 1.19.

   Четвёртый шаг, в тот же день: «и на 2К, и на десктопе… от шапки до Design &
   Development Studio… где-то на 16 пикселей увеличить, и остальной контент вниз
   подсъедет». Это только широкая полоса — 68.8 → 84.8. Замер: просвет от нижней
   кромки плашки шапки до строки кикера 80.8 → 96.8 на 2560, 1512 и 1440 (на
   1025–1200 своя высота шапки, там 76.8 → 92.8). Полосы 1024 и 719.98 она не
   называла — их величины остаются. Низ не трогается, перекос стал 1 : 0.97. */
.hero--center { padding-top: calc(var(--hdr-h) + 84.8px); padding-bottom: 17.92px; }

@media (max-width: 1024px) {
  .hero--center { padding-top: calc(var(--hdr-h) + 54.4px); padding-bottom: 15.68px; }
}

@media (max-width: 719.98px) {
  .hero--center { padding-top: calc(var(--hdr-h) + 34.4px); padding-bottom: 11.2px; }
}

/* ================= Вертикальная раскладка (Alexa, 20.09.2026) =================
   «На мобильном и на планшете, когда ориентация вертикальная, там всё ещё
   горизонтальные изображения… нужно две системы картинки.» Раскладка под
   вертикальное окно — своя: свой кадр, своя форма рамки, свой состав.

   Условие — форма окна плюс потолок по ширине. Одна форма окна ловила лишнее:
   `orientation: portrait` в CSS значит буквально «высота ≥ ширины», и окно
   десктопа 1278×1300 попадало в правило вместе с телефоном — галерея дилера
   схлопывалась в полоску 460 внутри двухколоночной карточки, а кадры карточек
   услуг вырастали до 751 (Alexa, 20.09.2026, по её снимку: «он должен
   нормально расширяться по размеру карточки… под вертикальный один контент,
   под горизонтальный другой, и это должно переключаться автоматически»).
   Потолок 1024 — та же граница, на которой карточка главной услуги переходит
   в одну колонку: выше неё раскладка горизонтальная целиком, и кадр, и файл.
   Ровно то же условие стоит в `js/home-gallery.js` и в `new-home/build.mjs`
   (`<source media>`): форма рамки и выбор файла обязаны включаться вместе,
   иначе вертикальный файл попадёт в широкую рамку.

   Форма 4:5 временная: Alexa выбирает её на стенде
   /new-home/preview/portrait-frames.html. Всё остальное в этом блоке от её
   выбора не зависит.

   Блок стоит в конце файла и ничего выше не переписывает: он переопределяет
   только внутри @media, и только те свойства, которые называет. */

/* `<picture>` вставляет узел между рамкой и картинкой, а галерея дилера
   выбирает картинку прямым потомком (`.sps-media > img`, выше по файлу).
   Повторяем те же свойства для обёрнутого случая, чтобы первый кадр галереи
   не остался без правил ни в одной ориентации. */
.sps-media > picture { position: absolute; inset: 0; display: block; }
.sps-media > picture > img { display: block; width: 100%; height: 100%; object-fit: cover; object-position: top; }
.sps-visual.is-focus-left .sps-media > picture > img { object-position: left top; }

@media (orientation: portrait) and (max-width: 1024px) {
  /* Форма рамки. Карточки услуг, карточки кейсов, кадры страниц услуг и
     превью кейсов — все места, кроме плиток первого экрана: они миниатюры,
     их форма решается отдельно. */
  .svs-media,
  .cse-media,
  .spv-media { aspect-ratio: var(--portrait-ar, 4 / 5); }

  /* Галерея дилера: рамка стоит на min-height (320/240 выше по файлу), а не
     на пропорции, поэтому вертикаль ей задаётся здесь и min-height снимается —
     иначе он держал бы прежнюю горизонтальную полосу. */
  .sps-visual { aspect-ratio: var(--portrait-ar, 4 / 5); min-height: 0; }

  /* Кадр, у которого есть вертикальная версия, заполняет рамку от верха:
     шапка экрана (логотип, первый заголовок) — то, ради чего кадр вертикальный. */
  .svs-media.has-portrait img,
  .cse-media.has-portrait img,
  .spv-frame.has-portrait .spv-media img,
  .sps-media > picture > img { object-position: center top; }

  /* Снимок телефона на тёмной плашке — это приём горизонтальной раскладки:
     там вертикальный кадр иначе не показать. В вертикальном окне рамка сама
     вертикальная, и снимок занимает её целиком. */
  .cse-media.is-phone.has-portrait img,
  .spv-frame.is-phone.has-portrait .spv-media img {
    position: static;
    width: 100%;
    height: 100%;
    max-width: none;
    transform: none;
    border-radius: 0;
    box-shadow: none;
    object-position: center top;
  }

  /* Состав вертикальной раскладки короче горизонтальной: у превью Lips by Lara
     широкий кадр и снимок телефона ведут к одному вертикальному файлу, и рядом
     встали бы две одинаковые картинки. Вторую убираем — только в вертикали. */
  .csp-frame.is-portrait-dup { display: none; }

  /* Заглушка. Места, для которых вертикального кадра ещё нет, не ждут файла и
     не остаются горизонтальными: рамка вертикальная, внутрь идёт широкий кадр,
     обрезанный по своей точке привязки (`is-focus-left` / `is-focus-center`
     выше по файлу, иначе верх). Появится вертикальный файл — строка в
     PORTRAIT (new-home/src/content.mjs), правил здесь менять не нужно. */
  .svs-media:not(.has-portrait):not(.is-tile) img,
  .cse-media:not(.has-portrait):not(.is-tile):not(.is-phone) img,
  .spv-frame:not(.has-portrait):not(.is-tile):not(.is-phone) .spv-media img { object-fit: cover; }

  /* Кадры галереи дилера, кроме первого, рисует канон (css/96-gallery.css) и
     привязывает вертикальный кадр к верху по ширине ≤719 — планшет стоя туда
     не попадает. Файл канона трогать нельзя, поэтому то же правило повторяется
     здесь по ориентации; значения по-прежнему приходят из js/home-gallery.js. */
  .sps-media .gal-frame:not(.gal-frame--native) > img,
  .sps-media .gal-frame:not(.gal-frame--native) > picture > img {
    object-position: var(--gal-mobile-object-position, var(--gal-object-position, center));
  }

  /* Планшет стоя. Кадр идёт во всю ширину карточки, как на телефоне, а не
     стоит полоской 460 по её центру (Alexa, 20.09.2026: «он должен нормально
     расширяться по размеру карточки»). Потолок 460 с `margin-inline: auto`
     оставлял по 138 пустоты с каждой стороны на 768 и по 210 на 953 — на
     телефоне такого никогда не было, там рамка всегда равна карточке.
     Вместе с потолком ушло и ограничение кнопки карточки кейса: она держала
     ту же меру 460 только потому, что по ней шёл кадр. Теперь мера одна —
     ширина карточки, — и закон «кнопка идёт по вертикали фотографии»
     выполняется сам. */
  @media (min-width: 720px) {
    /* `width: 100%` остаётся: рамка с `aspect-ratio` и абсолютными детьми
       считает ширину от содержимого, а содержимого у неё нет — без этой
       строки галерея дилера схлопывалась в 0×0 (замерено на 768×1024). */
    .sps-visual,
    .cse-media,
    .csp-frame--wide .spv-media { width: 100%; }
  }
}
