:root {
  /* Fixed dark palette — AstraSignos always uses its own scheme, NOT Telegram's
     theme (a light-mode client would otherwise give dark text on our dark cards). */
  --bg: #0f0c1d;
  --bg2: #1a1530;
  --card: #221a3d;
  --text: #f2eefb;
  --hint: #9b91c4;
  --accent: #b388ff;
  --accent2: #ff7eb6;
  --pers-title: #6fb0ff;   /* «Личность» card titles — explicit so the client's theme can't make them low-contrast (desktop was rendering them near-black) */
  --good: #5be3a7;
  --teal: #56c9c0;
  --warn: #ffd166;
  --bad: #ff6b8a;
  --gold: #ffd98a;   /* NIT-7: single source for the ~40 var(--gold,…) refs (were split #ffd98a/#ffd166 fallbacks) */
  /* paywall v2 tokens (paywall_spec.json · visual_spec). Роли ЖЁСТКО: золото = ценность
     (H1, герой-строка, юнит-цены, CTA-печать), magenta = ТОЛЬКО время/дефицит (промо-полоса,
     чип экономии), violet = тело. --pw-seal — тот же градиент печати, что tfx-gold (twin_fx.css). */
  --pw-gold:#F4C869;
  --pw-gold-hi:#ffd98a;
  --pw-seal:linear-gradient(178deg,#fff3d6 0%,#ffd98a 55%,#b8923e 100%);
  /* ХОЛОДНЫЙ сплав той же печати: тот же угол 178deg и та же трёхстопная огранка, только
     серебро-фиолет. Нужен всюду, где предмет остался печатью, но обещать премиум нельзя
     (буквица матрицы, лист «данных не хватает»). Заведён токеном, а не копипастой: два
     одинаковых на глаз градиента в разных местах файла расходятся на первой же правке. */
  /* Нижний стоп поднят #6f57b0 → #8c78cd (2026-08-03): на фоне листа #1a1530 старый давал
     3.07:1 — формально AA large при 800/19px, но с нулевым запасом, а на ДВУХСТРОЧНОМ
     титуле (de/nl на 320dp) вся вторая строка живёт именно в нижней половине градиента.
     #8c78cd = 4.76:1, то есть AA уже и для обычного текста. */
  --pw-seal-cold:linear-gradient(178deg,#efe6ff 0%,#b388ff 60%,#8c78cd 100%);
  --pw-ink-on-gold:#2a1c04;
  --pw-magenta:#FF5C8A;
  --pw-card:#2c2552;
  --pw-card-dim:#241e45;
  --pw-glow:rgba(255,217,138,.45);
  --line: rgba(255,255,255,0.08);
  --radius: 18px;
  /* iOS Dynamic Type (P3, путь A). Дефолт 1 → calc(px*1)===px, скриншот-дифф с базой
     pixel-identical; в Telegram/вебе класс html.native-app отсутствует, шим значение НЕ
     трогает → множитель навсегда 1 (нулевой регресс). На нативе tg-shim.readContentScale()
     ставит клампованный [0.9…1.30] масштаб на documentElement. Один источник, per-selector
     округлений/клампов НЕТ. */
  --font-scale: 1;
  /* «Личность» shared type scale — keeps the "same" heading identical across all 3 sub-tabs */
  --pers-card-title: calc(16.5px * var(--font-scale));        /* facet / karma-row / element-name / reco titles */
  --pers-section-head: calc(18px * var(--font-scale));        /* intro / karma-intro / upsell section heads */
}

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
html, body { margin: 0; padding: 0; height: 100%; overflow-x: hidden; overscroll-behavior: none; }
body {
  background: var(--bg);            /* solid base — no scroll seam */
  color: var(--text);
  font-size: calc(16px * var(--font-scale));   /* P3 Dynamic Type root; браузерный дефолт = 16px → scale=1 pixel-identical */
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  -webkit-font-smoothing: antialiased;
  overscroll-behavior: none;        /* no rubber-band drift down OR sideways */
}
/* top glow as a FIXED layer that fades fully to transparent, so scrolling never
   reveals a gradient "seam" mid-page (the old body radial ended at 55% height). */
body::before {
  content: ""; position: fixed; top: 0; left: 0; right: 0; height: 60vh; z-index: -1;
  background: radial-gradient(125% 100% at 50% 0%, #2a1f52 0%, rgba(15, 12, 29, 0) 78%);
  pointer-events: none;
}

#app { max-width: 520px; margin: 0 auto; min-height: 100%; display: flex; flex-direction: column; }
#screen { flex: 1; padding: 16px 16px 90px; }
/* Таббар = 8 + ~58 + 8 + нижняя safe-зона (на iPhone ~34px) — то есть выше 90px, и последняя
   строка любого экрана уходила под него (основатель 2026-10-11: «Коснись созвездия…» срезано).
   Запас под таббар считаем той же формулой, что и его padding-bottom. */
#screen { padding-bottom: calc(90px + var(--sab, env(safe-area-inset-bottom, 0px))); }
/* B16: render() moves focus to the screen heading (or the #screen wrapper) on each route change so
   keyboard/SR users aren't stranded. These targets are only ever focused PROGRAMMATICALLY (tabindex=-1,
   not in the tab order), so suppressing their outline keeps the view identical for mouse users without
   hiding any real keyboard focus ring. */
#screen:focus, #screen [tabindex="-1"]:focus, #topbar-title:focus { outline: none; }
.hidden { display: none !important; }

/* Top bar with back button */
.topbar {
  position: sticky; top: 0; z-index: 20; display: flex; align-items: center; gap: 6px;
  padding: 10px 12px calc(10px); min-height: 50px;
  background: rgba(20,16,40,0.92); -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px); border-bottom: 1px solid var(--line);
}
.backbtn {
  border: 0; background: var(--bg2); color: var(--text); width: 38px; height: 38px;
  border-radius: 12px; font-size: 26px; line-height: 1; cursor: pointer; flex: none;
  display: flex; align-items: center; justify-content: center; padding-bottom: 3px;
}
.backbtn:active { transform: scale(0.93); }
#topbar-title { font-weight: 700; font-size: 16px; }

/* Typography */
h1 { font-size: calc(26px * var(--font-scale)); margin: 0 0 6px; font-weight: 800; letter-spacing: -0.5px; }
h2 { font-size: calc(19px * var(--font-scale)); margin: 18px 0 10px; font-weight: 700; }
h3 { font-size: calc(16px * var(--font-scale)); margin: 0 0 4px; font-weight: 700; }
p { margin: 6px 0; line-height: 1.45; }
.hint { color: var(--hint); font-size: calc(14px * var(--font-scale)); }
.center { text-align: center; }

/* Cards */
.card {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 16px;
  margin: 12px 0;
}
.card.tap { cursor: pointer; transition: transform .08s; }
.card.tap:active { transform: scale(0.985); }
/* account self-card avatar (Telegram photo, else 👤/⭐ placeholder) */
.acc-ava { width: 52px; height: 52px; border-radius: 50%; flex: none; overflow: hidden;
  display: flex; align-items: center; justify-content: center;
  background: var(--bg2); border: 1px solid var(--line); }
.acc-ava img { width: 100%; height: 100%; object-fit: cover; display: block; }
.acc-ava-ph { font-size: 28px; line-height: 1; opacity: .9; }

/* Buttons */
.btn {
  display: block; width: 100%; border: 0; border-radius: 14px;
  padding: 16px; font-size: calc(16px * var(--font-scale)); font-weight: 700; cursor: pointer;
  background: linear-gradient(135deg, var(--accent), var(--accent2));
  color: #1a1030; margin-top: 12px;
}
.btn:disabled { opacity: .45; }
.btn.ghost { background: transparent; color: var(--text); border: 1px solid var(--line); }
.btn.small { padding: 10px 14px; font-size: calc(14px * var(--font-scale)); width: auto; display: inline-block; margin: 0; }
.btn.danger { background: transparent; color: var(--bad); border: 1px solid var(--bad); }

/* Form controls */
.field { margin: 14px 0; }
.field label { display: block; font-size: calc(14px * var(--font-scale)); color: var(--hint); margin-bottom: 7px; }
input[type=text], input[type=date], input[type=time], select {
  /* пол 16px: <16px триггерит iOS focus-zoom; вверх по Dynamic Type можно, вниз — нет */
  width: 100%; padding: 14px; font-size: max(16px, calc(16px * var(--font-scale))); color: var(--text);
  background: var(--bg2); border: 1px solid var(--line); border-radius: 12px;
}
input::placeholder { color: var(--hint); }

.date-grid { display: grid; grid-template-columns: minmax(0,1fr) minmax(0,1.4fr) minmax(0,1.2fr); gap: 10px; }
.date-grid select { text-align: center; }
/* US market: en picker is Month / Day / Year — the wide column follows the month select */
.date-grid.dp-mdy { grid-template-columns: minmax(0,1.4fr) minmax(0,1fr) minmax(0,1.2fr); }
.choice-grid { display: grid; grid-template-columns: repeat(2, minmax(0,1fr)); gap: 10px; }
.choice {
  padding: 16px; text-align: center; border-radius: 14px; font-weight: 600;
  background: var(--bg2); border: 2px solid transparent; cursor: pointer;
}
.choice.sel { border-color: var(--accent); background: rgba(179,136,255,0.14); }

.toggle-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 12px 0; }
/* Founder 2026-07-05: the WHOLE phrase toggles the switch (users tapped the text, not the 50px switch).
   The label is bound to the checkbox via for=, so tapping anywhere on it flips the switch natively. */
.toggle-row .tr-label { cursor: pointer; flex: 1; min-width: 0; }
.switch { position: relative; width: 50px; height: 30px; flex: none; }
/* A11Y-1 (R9): sr-only CLIP instead of display:none — the checkbox stays keyboard-focusable + in the a11y
   tree (announced via role=switch/aria-checked), while staying visually hidden behind the .track. */
.switch input { position: absolute; opacity: 0; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0,0,0,0); border: 0; white-space: nowrap; }
.switch .track { position: absolute; inset: 0; background: var(--bg2); border-radius: 30px; transition: .2s; border: 1px solid var(--line); }
.switch .track::after { content: ""; position: absolute; width: 24px; height: 24px; border-radius: 50%; background: #fff; top: 2px; left: 2px; transition: .2s; }
.switch input:checked + .track { background: var(--accent); }
.switch input:checked + .track::after { transform: translateX(20px); }
/* A11Y-1: visible focus ring on the track when the (clipped) checkbox is keyboard-focused */
.switch input:focus-visible + .track { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Onboarding nav buttons row (Back left, Continue right — different sizes) */
.nav-row { display: flex; gap: 10px; margin-top: 12px; }
.nav-row .btn { margin-top: 0; width: auto; }
/* value hook above the very first (name) field — replaces the removed welcome screen's value line */
.onb-hook { color:#c8bce8; font-size:calc(15.5px * var(--font-scale)); line-height:1.45; margin:-4px 0 20px; max-width:32ch; }
/* invited-user welcome bonus on the (first) name step — the reserved bottom space that replaced the welcome screen */
.onb-invite-foot { display:flex; align-items:center; justify-content:center; gap:9px; margin-top:34px;
  padding:13px 16px; border-radius:14px; text-align:center; font-size:14px; color:#d9ccf7;
  background:rgba(179,136,255,.10); border:1px solid rgba(179,136,255,.28); }
.onb-invite-foot .oif-gift { font-size:20px; line-height:1; }
.nav-row .btn.nav-back { flex: 0 0 auto; padding: 16px 20px; }
.nav-row .btn:not(.nav-back) { flex: 1; }

/* Onboarding progress */
.steps { display: flex; gap: 6px; margin-bottom: 18px; }
.steps .dot { flex: 1; height: 4px; border-radius: 4px; background: var(--line); }
.steps .dot.on { background: var(--accent); }

/* City search */
.city-list { margin-top: 8px; max-height: 260px; overflow-y: auto; }
.city-item { padding: 13px 12px; border-bottom: 1px solid var(--line); cursor: pointer; }
.city-item:active { background: var(--bg2); }
/* BUG-08: keyboard-active option in the ARIA listbox — same subtle wash as :active, no change for mouse users */
.city-item.active { background: var(--bg2); }
.city-item .cc { color: var(--hint); font-size: 13px; }
/* 2026-10-04: строка подсказки города = флаг + название + пояс. Флаг слева, чтобы страна
   читалась РАНЬШЕ названия (случай «Москва RU» против «Москва US/Айдахо»). */
.city-item { display: flex; align-items: baseline; gap: 9px; }
.city-item .city-flag { flex: 0 0 auto; font-size: 15px; line-height: 1.2; }
.city-item .city-tx { min-width: 0; }
.city-item .city-tz { display: block; color: var(--dim); font-size: 11.5px; margin-top: 1px; }

/* Profile selector chips */
.chips { display: flex; gap: 8px; overflow-x: auto; padding: 4px 0 10px; }
.chip {
  flex: none; padding: 8px 14px; border-radius: 20px; background: var(--bg2);
  border: 1px solid var(--line); font-size: 14px; font-weight: 600; cursor: pointer; white-space: nowrap;
}
.chip.sel { background: rgba(179,136,255,0.18); border-color: var(--accent); }

/* Top people switcher (forecast) */
/* Тоньше с 2026-08-03 (основатель: «эту область делаем уже»): полоса съедала 96px —
   четверть первого экрана на невысоком телефоне. Стало 78px. Верхние 9px оставлены
   намеренно: ниже скролл-бокс срежет золотое гало премиума (box-shadow 8px). */
.people-bar { display: flex; gap: 10px; overflow-x: auto; padding: 9px 11px 9px; scrollbar-width: none; }
.people-bar::-webkit-scrollbar { display: none; }
.person-chip { flex: none; background: none; border: 0; padding: 0; cursor: pointer;
  display: flex; flex-direction: column; align-items: center; gap: 4px; width: 52px; }
.ava-wrap { position: relative; display: inline-flex; }
.person-ava { width: 44px; height: 44px; border-radius: 50%; display: flex; align-items: center;
  justify-content: center; font-size: 21px; background: var(--bg2); border: 2px solid transparent; overflow: hidden; }
.person-ava .ava-img { width: 100%; height: 100%; object-fit: cover; }
/* Zodiac badge over a real avatar photo — sits where an online dot usually goes */
.ava-badge { position: absolute; right: -1px; bottom: -1px; width: 17px; height: 17px; box-sizing: border-box;
  border-radius: 50%; background: var(--accent); color: #fff; border: 2px solid var(--bg);
  display: flex; align-items: center; justify-content: center; font-size: 9.5px; line-height: 1; }
.person-chip.sel .person-ava { border-color: var(--accent2); box-shadow: 0 0 0 3px rgba(255,126,182,0.22); }
.person-chip.add .person-ava { border: 2px dashed var(--line); color: var(--hint); background: transparent; }
.person-nm { font-size: 10.5px; color: var(--hint); max-width: 52px; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }
.person-chip.sel .person-nm { color: var(--text); font-weight: 600; }

/* Forecast */
.hero { text-align: center; padding: 10px 0 4px; }
.hero .sign-emoji { font-size: 52px; }

/* Split hero: main sign on the left, key placements list on the right */
.hero-split { display: flex; flex-wrap: wrap; align-items: stretch; gap: 10px; padding: 12px 16px; }
.hero-main { flex: 0 0 31%; display: flex; flex-direction: column; align-items: center;
  justify-content: center; text-align: center; border-right: 1px solid var(--line); padding-right: 12px; }
.hero-main .sign-emoji { font-size: 52px; line-height: 1; }
/* B12 (R4): long sign names (Скорпион / Sagittarius / Capricórnio) overflowed the narrowed .hero-main (flex 31%);
   clamp the font + allow a graceful shrink so every localized sign fits without clipping. */
.hero-main .hero-sign { font-size: clamp(15px, 4.6vw, 20px); font-weight: 800; margin-top: 5px; letter-spacing: -0.3px; max-width: 100%; overflow-wrap: break-word; }
.hero-list { flex: 1; display: flex; flex-direction: column; justify-content: center; gap: 3px; min-width: 0; }
.pl-row { display: flex; align-items: center; gap: 6px; font-size: 14px; line-height: 1.15; min-width: 0; }
.pl-row.pl-missing { opacity: .8; }
.pl-row.pl-missing .pl-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.pl-unknown { color: var(--hint); font-style: italic; flex: none; white-space: nowrap; }
.missing-need { margin: 10px 0 16px; padding-left: 18px; color: var(--text); font-size: calc(14px * var(--font-scale)); }
.missing-need li { margin: 4px 0; }
.missing-feats { margin: 6px 0 12px; padding-left: 18px; color: var(--text); font-size: calc(14px * var(--font-scale)); }
.missing-feats li { margin: 4px 0; }
/* Subtle one-line "Approximate ›" footnote under the placements (approximate features
   stay shown elsewhere; this is just the optional honest hint). */
.pl-approx-hint { display: flex; align-items: center; gap: 6px; font-size: 12px; opacity: .7;
  margin-top: 2px; border-radius: 9px; padding: 2px 3px; transition: background .15s ease; }
.pl-approx-hint:active { background: rgba(179,136,255,0.12); }
.pl-approx-hint .pl-approx-word { color: var(--hint); font-style: italic; }
.pl-approx-hint .describe-cue { margin-left: 0; }
.missing-approx-item { margin: 10px 0 14px; }
.missing-approx-item .pl-unknown { font-size: 12px; }
.pl-row .pl-ico { width: 16px; text-align: center; font-size: 15px; flex: none; color: var(--accent); }
.pl-row .pl-name { color: var(--hint); flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pl-row .pl-sign { font-weight: 700; flex: none; white-space: nowrap; }
/* BOUNDED "probably X · maybe Y" placement: allow it to wrap so the 2nd candidate sign
   is never clipped by the nowrap/ellipsis column (B9), and it taps to show the % split (B10). */
.pl-row .pl-sign.pl-maybe { white-space: normal; overflow: visible; text-overflow: clip; font-weight: 600;
  line-height: 1.2; cursor: pointer; }
.pl-row .pl-sign.pl-maybe .pl-info { font-style: normal; color: var(--accent); font-size: 12px; opacity: .8; }
/* MI21a: the bounded Sun-sign ⓘ marker also rides on the hero sign line (.hero-sign-maybe), which
   the .pl-row selector above never reaches — give it the same accent/size treatment so it isn't a
   raw unstyled glyph. */
.hero-sign-maybe .pl-info { font-style: normal; color: var(--accent); font-size: 12px; opacity: .8; }
/* MI21b: near-cusp hedge line under a personality chip (was unstyled) — small muted hint. */
.pers-hedge-maybe { margin: 4px 0 0; font-size: 12px; color: var(--hint); opacity: .9; line-height: 1.3; }
.score-ring { font-size: 40px; font-weight: 800; }
/* ═══════════════════════════════════════════════════════════════════════════════
   ШКАЛЫ СФЕР — «ВЕРНЬЕР, ОТКАЛИБРОВАННЫЙ»
   Гравированный канал прибора: тёмный утоплённый жёлоб (#15102e — БАЙТ В БАЙТ
   .rings .ring-bg на этом же экране, styles.css:378), три золотые риски градуировки,
   столб света с мениском на границе значения. Вход — ОТЛИВ: тёмная вода уходит вправо.

   ЖЕЛЕЗНО: анимируется ТОЛЬКО transform. Свечение — СТАТИЧНЫМ градиентом.
   Ни filter, ни blur, ни анимируемого box-shadow, ни :has(), ни will-change,
   ни background-position, ни одной infinite. БАЗА = ФИНАЛ везде: сорвётся анимация —
   на экране остаётся ПРАВИЛЬНЫЙ кадр, а не пустая полоска.
   Reduced-motion для этого блока живёт ВНИЗУ ФАЙЛА, одним медиазапросом вместе с
   плашками дней (см. рядом с .f14-quick) — он обязан стоять ПОЗЖЕ обоих блоков,
   иначе `.f14-qseg{transition:none}` перебивается собственным поздним правилом.
   ═══════════════════════════════════════════════════════════════════════════════ */

/* ── 1. ПАЛИТРА СФЕР. Цвет УШЁЛ ИЗ ИНЛАЙНА в --sph на уже существующем data-focus
      (та же операция, которой кольца ушли на data-sphere). Пока цвет приезжал
      инлайном, правило .aspect .bar>i было мертво и многослойный фон был невозможен;
      теперь он возможен, и !important не нужен нигде.
      love/career/health/luck — БАЙТ В БАЙТ из .rings .ring-item[data-sphere]
      (styles.css ~320-323). Меняешь здесь — меняй и там: палитра обязана быть ОДНА.
      family: было #9b8cff — почти неотличим от --accent #b388ff и от luck.
      finance: было #ffd166 (= визуально ЗОЛОТО «Астры») на ЗАБЛОКИРОВАННОЙ сфере —
      читалось как премиум-сигнал и воровало роль у золота замка. Медь тёплая, но
      однозначно не золото. ОТКАТ обоих — по одной строке.
      Фоллбэк обязателен: придёт седьмой ключ — шкала не станет невидимой. */
.aspect-row{
  --sph:var(--accent,#b388ff); --sph-hi:#efe6ff; --sph-lit:rgba(179,136,255,.14);
  /* ГРАДУИРОВКА (три риски 25/50/75) СНЯТА по решению основателя 2026-08-02: «что за
     странные разделения на 4 части, совершенно не нравится». Идея была из концепта B
     («шкалу можно читать без числа»), но она делила полосу визуально на четыре куска и
     читалась как шум под текстом разбора, ради которого блок и раскрывают. Шкала снова
     непрерывная: тёмный жёлоб → столб света → мениск на границе значения.
     Золото осталось ровно в одном месте композиции — на премиум-замке. */
  position:relative; z-index:0;      /* стек-контекст для плёнки подсветки (::before, z-index:-1) */
  padding:12px 0; border-bottom:1px solid var(--line);
  /* transition:background .3s СНЯТ: это был paint-переход на всём прямоугольнике строки,
     шесть строк разом. Подсветка переехала на ::before/opacity (композитор). */
}
.aspect-row:last-child { border-bottom: 0; }
/* Второй селектор каждого правила — шторка «Сферы дня 2.0» (.sph-sheet): палитра сфер
   живёт ОДНИМ источником, копия в секции шторки разъехалась бы при первой правке. */
.aspect-row[data-focus="love"],    .sph-sheet[data-sphere="love"]   { --sph:#ff6b8a; --sph-hi:#ffdfe6; --sph-lit:rgba(255,107,138,.13); }
.aspect-row[data-focus="career"],  .sph-sheet[data-sphere="career"] { --sph:#4cc9f0; --sph-hi:#dff6ff; --sph-lit:rgba( 76,201,240,.11); }
.aspect-row[data-focus="health"],  .sph-sheet[data-sphere="health"] { --sph:#5be3a7; --sph-hi:#e0fff2; --sph-lit:rgba( 91,227,167,.10); }
.aspect-row[data-focus="luck"],    .sph-sheet[data-sphere="luck"]   { --sph:#c792ea; --sph-hi:#f2e2ff; --sph-lit:rgba(199,146,234,.13); }
.aspect-row[data-focus="family"],  .sph-sheet[data-sphere="family"] { --sph:#8f9cff; --sph-hi:#e6eaff; --sph-lit:rgba(143,156,255,.13); }
.aspect-row[data-focus="finance"], .sph-sheet[data-sphere="finance"]{ --sph:#f0a35e; --sph-hi:#ffe6cd; --sph-lit:rgba(240,163, 94,.12); }

.aspect { display: flex; align-items: center; gap: 12px; }
.aspect .pct { width: 42px; text-align: right; font-weight: 700; font-size: 14px; }

/* ── 2. ЖЁЛОБ = КАНАЛ ПРИБОРА. 8→12px: мениск обязан физически поместиться.
      Радиус 4px: у прибора КАНАЛ, а не лозенга — но и не прямоугольник (3px выводили
      шкалу из семьи с круглой оптикой экрана: кольца, натальное колесо).
      #15102e — БАЙТ В БАЙТ .rings .ring-bg, темнее --bg2 #1a1530: тот же приём
      «жёлоб темнее фона, чтобы свет вспыхивал сильнее».
      --trough объявлен ОДИН раз: его переиспользуют шторка отлива (::after) и замок.
      box-shadow СТАТИЧНА и не входит НИ В ОДИН transition/keyframe — доктрина
      запрещает АНИМИРУЕМУЮ тень, статичная inset легальна (прецедент .promo-badge).
      z-index:0 → .bar сам себе стек-контекст: слои 1/2/3 внутри не спорят с плёнкой
      строки (-1). +4px × 6 строк = +24px, целиком внутри #focus-more, который лежит
      НИЖЕ колец → окно света такта колец в туре «Проводник» не двигается. */
.aspect .bar{
  position:relative; z-index:0; flex:1; height:12px; border-radius:4px; overflow:hidden;
  --trough:
    radial-gradient(120% 200% at 50% -60%, rgba(255,243,214,.05) 0%, rgba(255,243,214,0) 62%),
    linear-gradient(180deg,#15102e 0%,#100c24 100%);
  background:var(--trough);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.045), inset 0 -1px 0 rgba(0,0,0,.35);
}

/* ── 3. ГРАДУИРОВКА УДАЛЕНА (основатель 2026-08-02). Здесь стоял ::before с тремя
      золотыми рисками на 25/50/75. Замысел был честный — «шкалу можно читать без
      числа», — но на живом экране три насечки РАЗРЕЗАЛИ полосу на четыре куска, и
      шесть таких строк подряд читались как шум под текстом разбора.
      Псевдоэлемент .bar::before больше НЕ ЗАНЯТ: если понадобится слой над столбом,
      он свободен. Замок (.bar[data-lock]) рисует свой пунктир СОБСТВЕННЫМ фоном и
      от этого правила никогда не зависел. */

/* ── 4. СТОЛБ СВЕТА. height:10px + margin:1px 0 → сверху и снизу остаётся ТЁМНАЯ ГУБА
      жёлоба ровно 1px: столб утоплен, как дуга в кольце (жёлоб 4.6 шире дуги 4.2).
      СЛЕВА ГУБЫ НЕТ — левый край есть ноль измерения и обязан быть заподлицо.
      Ширина остаётся ЧИСТЫМ % content-box (padding на .bar не ставим — он внёс бы
      ошибку измерения: длина заполнения и есть число).
      ПЯТЬ СЛОЁВ, ВСЕ СТАТИЧНЫ, НИ ОДНОГО ПСЕВДОЭЛЕМЕНТА, НИ ОДНОЙ АНИМАЦИИ:
        1 ядро-мениск: --sph-hi, привязан к ПРАВОМУ краю (at 100% 50%) → едет вместе
          с width БЕЗ единой строки JS и одинаково правилен на 3% и на 97%;
        2 кремовое гало вокруг ядра (#fff3d6 = «здесь стоит свет», тот же сигнал,
          что кремовая кромка отлива и кремовая линия активной плашки дня);
        3 блик сверху + 4 тень снизу = цилиндр, столб жидкости в трубке;
        5 сам цвет сферы.
      СЛОЙ 5 ОБЁРНУТ В linear-gradient НАМЕРЕННО: голый <color> в НЕпоследнем слое
      multi-layer background невалиден (CSS Backgrounds L3) — движок отбрасывает ВСЮ
      декларацию, и полоска исчезает. Это был живой QA-блокер ?v=389.
      НИКОГДА не переставлять слои и не «упрощать» последний. */
.aspect .bar > i{
  position:relative; z-index:1; display:block; height:10px; margin:1px 0; border-radius:3px;
  background:
    radial-gradient(var(--core-w,10px) 14px at 100% 50%, var(--sph-hi) 0%, rgba(255,255,255,0) 100%),
    radial-gradient(var(--core-w2,22px) 16px at 100% 50%, rgba(255,243,214,var(--core-a,.34)) 0%, rgba(255,243,214,0) 100%),
    linear-gradient(180deg, rgba(255,255,255,.26) 0%, rgba(255,255,255,.05) 46%, rgba(0,0,0,0) 56%),
    linear-gradient(180deg, rgba(0,0,0,0) 58%, rgba(10,7,24,.24) 100%),
    linear-gradient(var(--sph), var(--sph));
}

/* ── 5. ЗАМОК. НЕ :empty (он ловит и «данных нет», и один случайный пробел его убивает) —
      явный data-lock="1", который JS ставит СТРОГО по lockNum.
      Пустой жёлоб врёт «ноль»; пунктир говорит правду: «линия измерения проведена
      от края до края, значение за печатью». Пунктир 2/5 — пересчитанный под габарит
      рецепт .fcr-orb (.8 3). Высота 1.2px по центру — он физически не может быть
      спутан с 10-пиксельным цветным столбом.
      Это ВТОРОЕ и последнее золото композиции, и оно лежит РОВНО НА ЗАМКЕ:
      доктрина «золото = ценность/премиум» не «не нарушена», а впервые показана. */
.aspect .bar[data-lock]{
  background:
    repeating-linear-gradient(90deg, rgba(255,217,138,.16) 0 2px, rgba(255,217,138,0) 2px 7px)
      0 50%/100% 1.2px no-repeat,
    var(--trough);
}

/* ── 6. НИЗКАЯ УВЕРЕННОСТЬ. ДЛИНА СОХРАНЯЕТСЯ ВСЕГДА — она и есть число (закон колец,
      п.13); пунктиром во всю ширину заменять нельзя.
      Сигнал — РАЗМЫТЫЙ МЕНИСК (шире, тусклее): на реальном приборе неточное показание
      выглядит именно так. Это принципиально ДРУГОЕ сообщение, чем простое приглушение
      («менее важно»): здесь сказано «менее ТОЧНО». Три токена, ни одного нового узла.
      Глиф «≈» в .pct не тронут НИ БАЙТОМ — i18n не меняется. */
/* ОБЯЗАТЕЛЬНО СО СКОУПОМ: сама анимация объявлена под #focus-more/#fc-far-more (ID),
   и голое `/* ЗНАЧОК «ПРИМЕРНО» СНЯТ ЦЕЛИКОМ (основатель 2026-08-02: «эти нюансы уже излишние»).
   Здесь стояли правила soft-состояния: глиф «≈» перед числом, приглушение дуги и
   свечения, погашенный мениск. Карты с низкой уверенностью теперь показываются РОВНО
   как обычные — одним и тем же оформлением.
   ВАЖНО, что при этом НЕ изменилось: подавление того, что посчитать нельзя.
   Асцендент без времени рождения по-прежнему не рисуется, отсутствующее число не
   подставляется. Снята пометка о ТОЧНОСТИ, а не запрет на выдумывание. */
/* (хвост снятого блока: правило .aspect-row.fc-soft .bar::after удалено вместе
   со значком «примерно» — комментарий закрывался строкой выше) */

/* ── 7. ОТЛИВ = ВХОД + «ПЕРЕЛИВ» ОДНИМ УЗЛОМ. width анимировать нельзя; scaleX
      деформировал бы мениск и градуировку — поэтому едет ШТОРКА цвета жёлоба:
      тёмная вода отступает вправо и оставляет освещённый канал. У шторки КРЕМОВАЯ
      ПЕРЕДНЯЯ КРОМКА — это и есть перелив: свет проходит по шкале ровно один раз.
      ПОЧЕМУ ИМЕННО ТАК: шторка — САМЫЙ ВЕРХНИЙ узел (z-index:3), над движущимся слоем
      не красится НИЧЕГО, поэтому композитор не может снять поддерево с ускорения.
      Ни один другой узел шкалы не анимируется вовсе.
      БАЗА = ФИНАЛ: покой = шторка уже за правым краем. */
.aspect .bar::after{
  content:""; position:absolute; inset:0; z-index:3; border-radius:inherit; pointer-events:none;
  background:
    linear-gradient(90deg, rgba(255,243,214,.34) 0 1.5px, rgba(255,243,214,.10) 4px, rgba(255,243,214,0) 12px),
    var(--trough);
  transform:translateX(100%);
}
/* СКОУП: анимация живёт ТОЛЬКО внутри двух блоков разбора. Если .bar когда-нибудь
   переиспользуют в другом компоненте — он получит статику, и ничего не сломается. */
#focus-more .aspect .bar::after,
#fc-far-more .aspect .bar::after{
  animation:fca-ebb .66s cubic-bezier(.20,.75,.25,1) var(--fcb-d,0ms) both;
}
/* СЛАБОЕ УСТРОЙСТВО (_fcrCalm(): deviceMemory≤3 | hardwareConcurrency≤3 | FPS<42).
   Класс уже считается для .rings; здесь он приезжает на сам блок разбора.
   На дешёвом Android движения нет вовсе — картинка сразу финальная.
   IO-хук не нужен: блок лежит под .hidden{display:none} и раскрывается ТАПОМ,
   то есть по построению находится в поле зрения. */
#focus-more.fcr-calm .aspect .bar::after,
#fc-far-more.fcr-calm .aspect .bar::after{ animation:none; }

/* КАСКАД 45мс — отлив катится по списку сверху вниз, а не мигает разом.
   nth-of-TYPE, а НЕ nth-child: в #fc-far-more первым ребёнком стоит <p class="hint">,
   а .aspect-row — div; в #focus-more последним ребёнком идёт <button class="focus-unlock">
   — тоже не сдвигает счёт. Один набор правил обслуживает оба блока. */
.aspect-row:nth-of-type(1){ --fcb-d:0ms; }   .aspect-row:nth-of-type(2){ --fcb-d:45ms; }
.aspect-row:nth-of-type(3){ --fcb-d:90ms; }  .aspect-row:nth-of-type(4){ --fcb-d:135ms; }
.aspect-row:nth-of-type(5){ --fcb-d:180ms; } .aspect-row:nth-of-type(6){ --fcb-d:225ms; }

/* ── 8. ТАП ПО КОЛЬЦУ ЗАЖИГАЕТ СТРОКУ (fcRingsLight/fcRevealRow, снимается через 900 мс).
      Было: background прямо на строке + transition:background .3s — общий фиолет и paint.
      Стало: плёнка на псевдоэлементе, ведущая opacity, В ЦВЕТЕ ТОЙ САМОЙ СФЕРЫ —
      тапнул синее кольцо «Карьера», внизу синим вспыхнула именно её строка.
      Дефолт --sph-lit равен прежнему rgba(179,136,255,.14) байт в байт.
      z-index:-1 внутри стек-контекста строки → ложится под текст и НИКОГДА не поверх. */
.aspect-row::before{
  content:""; position:absolute; z-index:-1; inset:2px -9px; border-radius:12px;
  background:var(--sph-lit); opacity:0; transition:opacity .3s ease; pointer-events:none;
}
.aspect-row.fc-row-lit::before{ opacity:1; }
/* градуировка тронутой строки загорается цветом сферы — дословная калька
   .rings .ring-item.is-lit .fcr-orb{stroke:var(--sph)}. МГНОВЕННО, без перехода — как там. */
/* .fc-row-lit больше не перекрашивает риски — их нет; подсветка строки живёт плёнкой --sph-lit ниже */

@keyframes fca-ebb{ from{ transform:translateX(0); } }   /* to = база = за правым краем */

/* Yesterday / Today / Tomorrow day switcher */
.day-tabs { display: flex; gap: 4px; margin: 14px 0 6px; border-bottom: 1px solid var(--line); }
.day-tab { flex: 1; background: none; border: 0; color: var(--hint); font-size: 15px; font-weight: 600;
  padding: 4px 0 6px; cursor: pointer; border-bottom: 2px solid transparent; margin-bottom: -1px; }
.day-tab.active { color: var(--text); border-bottom-color: var(--accent); }
.day-tab:active { opacity: 0.7; }

/* Focus & Mood rings */
/* ВНИМАНИЕ: следующие ЧЕТЫРЕ правила — ОБЩИЕ. Ими живёт не только ряд сфер дня, но и
   .pers-gauge на «Личности» (см. persGaugeHtml в app.js) — там та же разметка
   .ring-wrap/.ring-bg/.ring-fg.
   Поэтому здесь НИ ОДНОГО байта менять нельзя: вся новая оптика «Орбиты дня» написана
   ниже и ЦЕЛИКОМ заскоуплена под .rings. */
.ring-wrap { position: relative; width: 62px; height: 62px; }
.ring-wrap > svg { width: 62px; height: 62px; transform: rotate(-90deg); }   /* DIRECT child only — never the element icon svg inside .eg-tri (it must not rotate) */
.ring-bg { fill: none; stroke: var(--bg2); stroke-width: 3.2; }
.ring-fg { fill: none; stroke-width: 3.2; stroke-linecap: round; transition: stroke-dasharray .5s ease; }

/* ═══════════════════════════════════════════════════════════════════════════
   КОЛЬЦА СФЕР ДНЯ · «ОРБИТА ДНЯ»  (экран «Прогноз», карточка «Фокус и настроение»)

   ЖЕЛЕЗНО: анимируем ТОЛЬКО opacity / transform / stroke-dashoffset — это
   единственные свойства, которые дешёвый LatAm/Африка-Android (88–93% аудитории)
   тянет на композиторе, не гоняя layout. НЕТ filter/blur/backdrop-filter/
   drop-shadow, НЕТ анимируемого box-shadow, НЕТ :has(), НЕТ анимации
   width/height/top/left, НЕТ will-change НИГДЕ (бюджет слоёв экрана «Прогноз»
   уже выбран ротором натального колеса и ~10 гало).
   Свечение получено СТЕКОМ ОБВОДОК и статичным radial-gradient — не тенью.

   ВСЁ СКОУПЛЕНО ПОД .rings. Глобальные .ring-wrap / .ring-wrap>svg / .ring-bg /
   .ring-fg (выше) принадлежат ТАКЖЕ .pers-gauge («Личность → Стихии») и остаются
   нетронутыми — ни одно правило отсюда туда протечь не должно.
   Namespace: .fcr-* и @keyframes fcr-*. @keyframes ring-fill — ОБЩИЙ с двумя
   экранами совместимости, не трогать.

   БАЗА = ФИНАЛ: инлайновые stroke-dashoffset уже финальные, кейфреймы идут
   `from{...}`. Снятие анимаций (reduced-motion, сбой, пауза вне вьюпорта)
   оставляет ПРАВИЛЬНУЮ картинку, а не пустые кольца.

   Классы .ring-item / .ring-pct / .ring-lbl НЕ переименовываются и НЕ теряют
   живой текст: их читает тур «Проводник» (app.js ~11509) и по ним же аналитика
   считает тапы (element_id 'el.ring-item').
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── 1. Палитра сферы. Альфы гармонизированы ПО СВЕТЛОТЕ, а не по номиналу:
      career/health на фоне #0f0c1d визуально громче love/luck, поэтому их tint
      прижат сильнее. Не «выравнивать» обратно — ряд обязан читаться как один
      комплект. Fallback обязателен: придёт пятый ключ — дуга не станет невидимой. */
.rings .ring-item{
  --sph:var(--accent); --sph-hi:#efe6ff; --sph-tint:rgba(179,136,255,.18); --halo:.17;
  /* ФЛИП-ТОКЕН: золото здесь — ЧЕРТЁЖ (тот же волосок, что .fcw-ring-o натального
     колеса на ЭТОМ ЖЕ экране), а не премиум-сигнал. Если основатель прочитает его
     как замок — заменить ОДНО значение на rgba(255,255,255,.075), больше ничего. */
  --fcr-orb:rgba(255,217,138,.20);
}
.rings .ring-item[data-sphere="love"]  { --sph:#ff6b8a; --sph-hi:#ffdfe6; --sph-tint:rgba(255,107,138,.20); }
.rings .ring-item[data-sphere="career"]{ --sph:#4cc9f0; --sph-hi:#dff6ff; --sph-tint:rgba( 76,201,240,.16); }
.rings .ring-item[data-sphere="health"]{ --sph:#5be3a7; --sph-hi:#e0fff2; --sph-tint:rgba( 91,227,167,.14); }
.rings .ring-item[data-sphere="luck"]  { --sph:#c792ea; --sph-hi:#f2e2ff; --sph-tint:rgba(199,146,234,.19); }
/* Кольца сегодня рендерятся ТОЛЬКО для 4 бесплатных сфер (ringKeys, app.js ~5338),
   поэтому эти две строки сейчас не срабатывают ни разу. Они стоят здесь, чтобы палитра
   сфер была ОДНА: если ряд колец когда-нибудь станет шестичленным, family/finance
   не уедут на фиолетовый дефолт. Значения = .aspect-row[data-focus] (styles.css ~290). */
.rings .ring-item[data-sphere="family"] { --sph:#8f9cff; --sph-hi:#e6eaff; --sph-tint:rgba(143,156,255,.16); }
.rings .ring-item[data-sphere="finance"]{ --sph:#f0a35e; --sph-hi:#ffe6cd; --sph-tint:rgba(240,163, 94,.15); }

/* ХАРАКТЕР ПО ЗНАЧЕНИЮ — СТАТИКОЙ. Сильная сфера физически светит ярче, слабая
   тише, но НИКОГДА не мертво. Разные ПЕРИОДЫ пульса запрещены законом
   синхронности «Астры»: четыре мигалки вразнобой читаются как ёлочная гирлянда. */
.rings .ring-item[data-b="high"]{ --halo:.22; }
.rings .ring-item[data-b="mid"] { --halo:.17; }
/* СЛАБАЯ СФЕРА ТИШЕ, НО НЕ НЕВИДИМА. Раньше здесь стояло --sph-hi:var(--sph) — ядро
   красилось в цвет дуги и переставало отличаться от её круглого капа. bucketOf: low —
   это ВСЁ, что ниже 55, а живой ряд обычного дня сидит в 29–47, то есть сигнатурная
   голова пропадала на трёх кольцах из четырёх. Приглушаем не цветом, а РАЗМЕРОМ ядра
   (stroke-width статичен, ничего не анимируется) плюс самой тусклой короной. */
.rings .ring-item[data-b="low"] { --halo:.12; }
.rings .ring-item[data-b="low"] .fcr-body{ stroke-width:4.6; }

/* ── 2. Ряд. Горизонтальный padding = 0: на 320px запаса нет.
      min-width:0 + перенос подписи чинят ЖИВОЙ баг переполнения на id/de/vi/th
      (сегодня «Keberuntungan» разносит ряд на ~84px за карточку). */
.rings{ display:flex; align-items:flex-start; justify-content:space-between;
        gap:6px; margin-top:2px; padding:6px 0 2px; }
.rings .ring-item{ position:relative; display:flex; flex-direction:column; align-items:center;
        gap:7px; flex:1 1 0; min-width:0; transition:opacity .3s ease; }
.rings .ring-wrap{ width:62px; height:62px; }
/* ПОРЯДОК ПОКРАСКИ — НЕ УДАЛЯТЬ: ::before и ::after позиционированы, и без
   z-index у svg они красятся ПОВЕРХ него — диск накроет дугу и голову.
   z0 атмосфера → z1 svg → z2 ударная волна → z3 число.
   overflow:visible выпускает корону на 1.7px наружу (в gap ряда, внутри карточки). */
.rings .ring-wrap > svg{ position:relative; z-index:1; overflow:visible; }

/* ── 3. АТМОСФЕРА (z0). Фирменная формула продукта — источник света сверху-слева
      на 30%/24% (та же, что у #twinfx .fx-disc и .pers-gauge). Полностью статична. */
.rings .ring-wrap::before{ content:""; position:absolute; inset:5px; border-radius:50%;
  z-index:0; pointer-events:none;
  background:
    radial-gradient(112% 112% at 30% 24%, var(--sph-tint) 0%, rgba(0,0,0,0) 54%),
    radial-gradient(circle at 50% 64%, rgba(10,7,24,.55) 0%, rgba(10,7,24,0) 78%),
    linear-gradient(162deg,#241c46 0%,#1a1435 58%,#141028 100%); }

/* ── 4. УДАРНАЯ ВОЛНА ТАПА (z2). В покое стоит РОВНО НОЛЬ: opacity:0, без анимации —
      узел, который ничего не анимирует, ничего и не стоит.
      Родня #twinfx .fx-ring; кривая — --ez-burst из twin_fx.css.
      scale ограничен 1.15 (62→71px), чтобы волна не вылезала из окна света тура. */
.rings .ring-wrap::after{ content:""; position:absolute; inset:0; border-radius:50%;
  z-index:2; pointer-events:none; border:1px solid var(--sph); opacity:0; }
.rings .ring-item.fcr-pulse .ring-wrap::after{
  animation:fcr-pulse .5s cubic-bezier(.16,1,.30,1); }

/* ── 5. ГРАВЮРНАЯ ОРБИТА. Волосок .7 при альфе .20 — минимум, который выживает
      на DPR 1/1.5 (массовый LatAm-Android). Тоньше — муар вместо гравюры. */
.rings .fcr-orb{ fill:none; stroke:var(--fcr-orb); stroke-width:.7;
                 stroke-dasharray:.8 3; stroke-linecap:round; }

/* ── 6. ЖЁЛОБ. Темнее --bg2, чтобы дуга вспыхивала сильнее, и ШИРЕ дуги на .4 unit
      → по обе стороны остаётся тёмная губа: дуга читается УТОПЛЕННОЙ в жёлоб,
      а не нарисованной поверх. Хардкод оправдан только здесь и только под .rings. */
.rings .ring-bg{ stroke:#15102e; stroke-width:4.6; }

/* ── 7. ДУГА ПРОЙДЕННОГО. 3.2 → 4.2: вес — самый дешёвый премиум, стоит ноль,
      габарит не растёт (15.5+2.1 = 17.6 < 18, клиппинга нет).
      transition:none глушит глобальный transition:stroke-dasharray (он всё равно
      никогда не срабатывал — узлы всегда создаются заново через innerHTML). */
.rings .ring-fg{ stroke:var(--sph); stroke-width:4.2; stroke-linecap:round; transition:none; }
.rings .fcr-arc{ animation:fcr-arc .9s cubic-bezier(.22,.9,.3,1) both; }
.rings .ring-item[data-z] .ring-fg{ stroke-linecap:butt; }   /* score 0 → без точки-призрака */

/* ── 8. ГОЛОВА ДУГИ. dasharray .01 100 + round cap = ТОЧКА ровно на конце дуги;
      --bof = -score двигает её вместе с дугой БЕЗ тригонометрии, поэтому голова
      физически не может рассинхрониться с числом.
      Свечение получено ВТОРОЙ ОБВОДКОЙ (корона), а не filter/box-shadow. */
.rings .fcr-halo, .rings .fcr-body{ fill:none; stroke-linecap:round;
  stroke-dasharray:.01 100; stroke-dashoffset:var(--bof,0);
  animation:fcr-orbit .9s cubic-bezier(.22,.9,.3,1) both; }
.rings .fcr-halo{ stroke:var(--sph);    stroke-width:7;   opacity:var(--halo); }
.rings .fcr-body{ stroke:var(--sph-hi); stroke-width:5.4;
  animation:fcr-orbit .9s cubic-bezier(.22,.9,.3,1) both,
            fcr-tw 4.6s ease-in-out .9s 12; }   /* мерцание стартует ПОСЛЕ входа */

/* ── 9. ЧИСЛО (z3). ЖИВОЙ ТЕКСТ — тур читает .ring-pct и парсит /\d+/, поэтому
      число НИКОГДА не уезжает в content:/<text>/aria-label/canvas.
      tabular-nums обязателен: без него счётчик 0→N дёргает ширину и гонит layout.
      Тень ТОЛЬКО тёмная (контраст), без «света под штрихом» — на дешёвых
      экранах светлая подложка под штрихом даёт мыло, а не гравюру. */
.rings .ring-pct{ position:absolute; inset:0; z-index:3; display:flex;
  align-items:center; justify-content:center; padding-left:4px;   /* оптическая компенсация «%» */
  font-size:16px; font-weight:800; letter-spacing:-.4px; color:#fff;
  font-variant-numeric:tabular-nums; text-shadow:0 1px 2px rgba(8,5,20,.55); }
.rings .ring-pct i{ font-style:normal; font-size:9.5px; font-weight:700; opacity:.5;
  margin-left:1.5px; transform:translateY(-3px); }

/* ── 10. ПОДПИСЬ. ЖИВОЙ ТЕКСТ (её тоже цитирует тур). НЕ анимируется вообще: ряд
      переклеивается на каждый тап по дню, а тур читает подпись из живого DOM —
      она обязана быть читаемой с нулевого кадра.
      Двухстрочная подпись (id/de/vi/th) — штатное состояние, не баг.
      ПЕРЕХОДА НЕТ НИ ОДНОГО: color вне разрешённого доктриной набора (opacity/transform/
      stroke-dashoffset), а перекраска подписи и без него читается нормально. */
.rings .ring-lbl{ font-size:11.5px; line-height:1.2; color:var(--hint); text-align:center;
  max-width:100%; overflow-wrap:anywhere; hyphens:auto; }

/* ── 11. ТАП: физическое вдавливание, только transform. */
.rings .ring-item:active .ring-wrap{ transform:scale(.95); transition:transform .1s ease; }

/* ── 12. «Я ТРОГАЛ ЭТОТ КРУГ». Канон продукта — подсвечиваем ЗАТЕМНЕНИЕМ соседей
      (.fcw-stage.selecting), но ТРАНЗИЕНТНО: .fcr-sel снимается JS через 900 мс.
      Ряд существует ради СРАВНЕНИЯ сфер — залипшее затемнение отбирает его смысл.
      Метка тронутого кольца (цвет подписи) остаётся до схлопывания блока. */
.rings.fcr-sel .ring-item:not(.is-lit){ opacity:.58; }
/* ── 12b. ОТВЕЧАЕТ ВЕСЬ РЯД (fcRingsWave). Тап по абзацу дня, который не называет ни
      одной сферы (ровный день, карта низкой уверенности), ведёт не к одному кругу, а
      ко всему ряду: подписи на 900 мс берут цвет своих сфер, а по кругам проходит одна
      волна ударного кольца со сдвигом 70 мс (та же ::after, что у одиночного тапа —
      новых слоёв не заводим). Затемнения тут нет: гасить нечего и не за что.
      Это правило — ЕДИНСТВЕННОЕ, что делает ответ видимым под reduced-motion: пульс
      там выключен, а цвет подписи статичен и приходит мгновенно. */
.rings.fcr-wave .ring-lbl{ color:var(--sph); }
.rings .ring-item.is-lit .ring-lbl{ color:var(--sph); }
.rings .ring-item.is-lit .fcr-orb{ stroke:var(--sph); stroke-opacity:.45; }

/* ── 13. ЧЕСТНОСТЬ: НИЗКАЯ УВЕРЕННОСТЬ (ringSoft/farSoft). Правило железное:
      ДЛИНА ДУГИ СОХРАНЯЕТСЯ ВСЕГДА — она и есть число. Пунктиром по всей
      окружности заменять её НЕЛЬЗЯ: это нарисует 100% под числом «41%».
      Сигнал — АБСОЛЮТНЫЙ (глиф «≈», работает и когда мягкие все четыре сразу,
      что при fcConfLow — самый частый случай), плюс приглушение и ПОЛНАЯ
      остановка: голова не рисуется, дуга не едет. Число остаётся точным
      (решение основателя 2026-07-05). Ноль новых i18n-строк.
      «≈» — CSS-псевдоэлемент: textContent остаётся «62%», тур не задет ни на байт.
      Пунктир 4 4 не занимаем — он принадлежит .pers-gauge--approx. */

/* ── 14. СЛАБОЕ УСТРОЙСТВО. Класс ставится В РАЗМЕТКЕ (навешивание после рендера
      перезапускало бы анимацию и давало видимый скачок). Вход остаётся — он
      одноразовый и дешёвый; снимается ТОЛЬКО долгоживущее мерцание.
      Порядок правил важен: ниже базового объявления .fcr-body. */
.rings.fcr-calm .fcr-body{ animation:fcr-orbit .9s cubic-bezier(.22,.9,.3,1) both; }

/* ── 15. ВНЕ ВЬЮПОРТА — пауза (IntersectionObserver). Кольца стоят ВЫШЕ колеса:
      без этого они перерисовываются в главном потоке во время скролла и
      конкурируют с растеризацией тайлов.
      СПИСОК ИЗ ДВУХ ЗНАЧЕНИЙ ОБЯЗАТЕЛЕН: у .fcr-body в band A ДВЕ анимации
      (fcr-orbit — вход, fcr-tw — дыхание), и одиночное `paused` вставало на ОБЕ.
      Тогда за экраном замирал ВХОД: гало (у которого пауза не стоит) уезжало на
      кончик дуги, а белое ядро оставалось на 12 часах и выползало отдельно —
      голова физически отрывалась от дуги. Паузим ТОЛЬКО дыхание.
      У .rings.sm и .rings.fcr-calm анимация одна — лишнее второе значение по
      спецификации игнорируется, эти ветки не задеты. */
.rings.fcr-off .fcr-body{ animation-play-state:running, paused; }

/* ── 15b. ВХОД ПРИДЕРЖАН ДО ПЕРВОГО ПОКАЗА РЯДА ГЛАЗАМ (класс ставит fcRingsMount
      синхронно, ДО первого пейнта; снимает первое пересечение либо страховка 6с).
      Ряд лежит ниже сгиба почти всегда — без этого вся церемония (12 анимаций +
      счётчик) отыгрывала за экраном, и доскроллившему доставалась голая статика.
      Правило стоит НИЖЕ fcr-off намеренно: пока вход придержан, паузить дыхание
      нечем и нечего, и hold обязан выигрывать при равной специфичности. */
.rings.fcr-hold .fcr-arc,
.rings.fcr-hold .fcr-halo,
.rings.fcr-hold .fcr-body{ animation-play-state:paused; }

/* ── 16. KEYFRAMES. Все в namespace fcr-*; ни один не пересекается с ring-fill,
      fcw-*, pg-*. `to` у fcr-arc/fcr-orbit = ИНЛАЙНОВАЯ БАЗА (= финал), поэтому
      кейфрейм задаёт только `from` — и любая остановка честна. */
@keyframes fcr-arc  { from{ stroke-dashoffset:100 } }
@keyframes fcr-orbit{ from{ stroke-dashoffset:0   } }
/* «дыхание, не мигание»: opacity никогда не идёт к нулю. 4.6s = 0.217 Гц —
   в 14 раз ниже порога WCAG 2.3.1. ЗАКОН СИНХРОННОСТИ: delay одинаковый у всех
   четырёх, никакого stagger. 12 циклов (~55 с) → остановка на кадре 0%, т.е. на
   ПОЛНОЙ яркости; дальше экран статичен навсегда до следующего рендера. */
@keyframes fcr-tw   { 0%,100%{ opacity:1 } 50%{ opacity:.62 } }
@keyframes fcr-pulse{ from{ opacity:.5; transform:scale(1) } to{ opacity:0; transform:scale(1.15) } }

/* ── 17. КОМПАКТ (band B/C, дальние дни, 44px). Не «то же меньше», а ИНДЕКС дня:
      с чертежа снята вся оптика. space-around + nowrap + flex:1 1 0 — потому что
      scoredFar реально отдаёт 1..4 кольца, и левый комок читался бы как баг вёрстки.
      Замер 320px: 4×44 + 3×6 = 194 при inner 254 — запас 60px. */
.rings.sm{ justify-content:space-around; flex-wrap:nowrap; gap:6px; margin-top:2px; padding:4px 0 0; }
.rings.sm .ring-item{ flex:1 1 0; min-width:0; gap:5px; }
.rings.sm .ring-wrap, .rings.sm .ring-wrap > svg{ width:44px; height:44px; }
.rings.sm .ring-wrap::before{ inset:4px; background:
    radial-gradient(112% 112% at 30% 24%, var(--sph-tint) 0%, rgba(0,0,0,0) 56%),
    linear-gradient(162deg,#231b44 0%,#141028 100%); }   /* один слой снят: на 43px он грязь */
.rings.sm .fcr-orb{ display:none; }        /* .7 при 44px = 0.6 физ.px → муар */
.rings.sm .ring-bg{ stroke-width:4.2; }
.rings.sm .ring-fg{ stroke-width:3.8; animation-duration:.62s; }   /* вес дуги на 44px */
.rings.sm .fcr-halo{ stroke-width:6.4; opacity:.14; animation-duration:.62s; }
.rings.sm .fcr-body{ stroke-width:4.8;
  animation:fcr-orbit .62s cubic-bezier(.22,.9,.3,1) both; }       /* МЕРЦАНИЯ НЕТ: 0 узлов в покое */
.rings.sm .ring-pct{ font-size:11.5px; padding-left:3px; }
.rings.sm .ring-pct i{ font-size:7.5px; opacity:.45; transform:translateY(-2px); }
.rings.sm .ring-lbl{ font-size:11px; }

/* ── 18. REDUCED-MOTION: не «выключено», а СПРОЕКТИРОВАННЫЙ СТОП-КАДР.
      Работает потому, что база dashoffset = финалу. Статика КОМПЕНСИРУЕТ потерю
      движения (приём .fcw-aspect, который в rm поднимает opacity с .05 до .28):
      корона ярче, ядро на полной яркости. Счётчик отсекается в JS. */
@media (prefers-reduced-motion:reduce){
  .rings .fcr-arc, .rings .fcr-halo, .rings .fcr-body,
  .rings .ring-item.fcr-pulse .ring-wrap::after{ animation:none !important; }
  .rings .ring-item:active .ring-wrap{ transition:none; }
  .rings .ring-item, .rings .ring-lbl{ transition:none; }
  .rings .fcr-halo{ opacity:calc(var(--halo) + .06); }
  /* .rings.sm .fcr-halo (0,3,0) перебивает строку выше (0,2,0) — без этой строки
     компакт молча оставался без rm-компенсации яркости, ради которой приём и введён. */
  .rings.sm .fcr-halo{ opacity:.20; }
  .rings .fcr-body{ opacity:1; }
}

/* Premium-locked rows */
.premium-row { color: var(--accent); cursor: pointer; }
.aspect-row.premium-row { opacity: 0.85; }
/* redacted "hidden premium text" line — same dots language as the locked compat score */
.redacted .rd-dots { color: var(--hint); letter-spacing: 3px; opacity: .6; }
.redacted .rd-lock { margin-left: 7px; letter-spacing: 0; }  /* астра НЕ затемняется (opacity убрана); размер = .pg--inline 14px */
.pct-lock { cursor: pointer; }

/* Completeness card (graceful-degradation, Doctrine §7): a tier chip, honest reason
   notes, and the gentle add-year / add-country onboarding asks (B1/B33). */
.completeness-card { display: flex; flex-direction: column; gap: 6px; }
.completeness-card .row { align-items: center; gap: 10px; }
.completeness-card .chip { color: #fff; padding: 5px 11px; border-radius: 20px; font-size: 13px;
  font-weight: 700; flex: none; border: 0; }
.chip-sun  { background: linear-gradient(90deg, #ffb74d, #ff8a65); }
.chip-core { background: linear-gradient(90deg, #4cc9f0, #9b8cff); }
.chip-full { background: linear-gradient(90deg, #5be3a7, #4cc9f0); }
.degrade-notes { list-style: none; margin: 4px 0 0; padding: 0; display: flex; flex-direction: column; gap: 5px; }
.degrade-notes li { position: relative; padding-left: 16px; line-height: 1.35; font-size: 13px; }
.degrade-notes li::before { content: "•"; position: absolute; left: 4px; color: var(--accent); }
/* Sky notes: lunar nodes + void-of-course + out-of-bounds Moon (CONTRACT a/b/c).
   Reuses the dark card surface; each note is an icon + label + sub-line. */
.sky-notes { display: flex; flex-direction: column; gap: 12px; }
.sky-note { display: flex; align-items: flex-start; gap: 11px; }
.sky-note + .sky-note { border-top: 1px solid var(--line); padding-top: 12px; }
.sky-note .sky-ico { flex: none; width: 22px; text-align: center; font-size: 17px;
  line-height: 1.25; color: var(--accent); }
.sky-note .sky-body { min-width: 0; flex: 1; }
.sky-note .sky-lbl { font-size: 13px; font-weight: 700; letter-spacing: -0.1px; }
.sky-note .sky-val { font-size: 13px; color: var(--text); margin-top: 2px; line-height: 1.35; }
.sky-note .sky-val.sky-sub { color: var(--hint); }
.sky-note .sky-dot { color: var(--hint); opacity: .7; margin: 0 2px; }
.sky-note.sky-voc .sky-ico { color: var(--accent2); }
.sky-note.sky-oob .sky-ico { color: var(--warn); }
/* Lunar nodes tucked inside the Moon placement sheet (was a space-hungry standalone note). */
.moon-nodes { margin-top: 14px; padding-top: 13px; border-top: 1px solid var(--line); }
.moon-nodes .sky-lbl { font-size: 13px; font-weight: 700; }
.moon-nodes .sky-val { font-size: 13px; color: var(--text); margin-top: 3px; line-height: 1.35; }
.moon-nodes .sky-dot { color: var(--hint); opacity: .7; margin: 0 2px; }
.ask-row { flex-wrap: wrap; }
.ask-chip { display: inline-flex; align-items: center; gap: 4px; background: rgba(179,136,255,0.12);
  border: 1px solid var(--accent); border-radius: 18px; padding: 7px 13px; font-size: 13px;
  font-weight: 600; color: var(--accent); cursor: pointer; }
.ask-chip:active { opacity: .7; }
.ask-form select { margin-right: 8px; }
.btn.sm { width: auto; display: inline-block; margin: 0; padding: 9px 16px; font-size: calc(14px * var(--font-scale)); }

/* «Кто ты» — FREE personality HOOK card on the forecast (deep-links into Личность → Характер).
   Dark-violet card w/ the element accent (data-el → --el / --el-soft / --el-glow, falling back to
   the app accent when the sign/element is unknown). One tasteful card, styled like the other
   forecast cards. */
.fc-who-card { position: relative; overflow: hidden;
  background: linear-gradient(160deg, var(--el-soft, rgba(179,136,255,.10)), var(--card) 62%);
  border-color: color-mix(in srgb, var(--el, var(--accent)) 34%, var(--line)); }
.fc-who-card::before { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 3px;
  background: linear-gradient(var(--el, var(--accent)), transparent); opacity: .85; }
.who-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; }
.who-eyebrow { font-size: 12px; font-weight: 800; letter-spacing: .12em; text-transform: uppercase;
  color: var(--el, var(--accent)); }
.who-share { display: inline-flex; align-items: center; justify-content: center; width: 30px; height: 30px;
  border-radius: 50%; border: 1px solid var(--line); background: rgba(255,255,255,.04);
  color: var(--el, var(--accent)); cursor: pointer; padding: 0; flex: none; }
.who-share:active { opacity: .6; }
.who-share-ico { font-size: 15px; line-height: 1; }
.who-line { display: flex; gap: 12px; align-items: flex-start; cursor: pointer; }
.who-ico { flex: none; width: 34px; height: 34px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center; font-size: 18px;
  background: var(--el-soft, rgba(179,136,255,.14)); color: var(--el, var(--accent));
  box-shadow: 0 0 14px 1px var(--el-glow, rgba(179,136,255,.30)); }
.who-body { min-width: 0; flex: 1; }
.who-title { font-size: calc(16px * var(--font-scale)); font-weight: 700; color: var(--text); line-height: 1.25; }
.who-sum { margin: 4px 0 0; font-size: calc(14.5px * var(--font-scale)); line-height: 1.45; color: var(--text); opacity: .92; }
.who-cta { display: flex; align-items: center; justify-content: center; gap: 8px; width: 100%;
  margin: 13px 0 0; padding: 11px; border: 1px solid color-mix(in srgb, var(--el, var(--accent)) 45%, var(--line));
  border-radius: 12px; background: var(--el-soft, rgba(179,136,255,.10));
  color: var(--el, var(--accent)); font-size: 14px; font-weight: 700; cursor: pointer; }
.who-cta:active { opacity: .7; }
.who-cta .describe-cue { background: transparent; color: inherit; width: auto; height: auto; }

/* «Зеркало» — the top-of-forecast daily greeting line (name + today's real Moon theme). A light
   accented line, NOT a card: it should read as a soft hero, distinct from the «Кто ты» card below. */
.fc-mirror { display: flex; align-items: baseline; gap: 9px; margin: 2px 2px 14px;
  padding: 0 2px; font-size: calc(15.5px * var(--font-scale)); line-height: 1.4; color: var(--text); }
.fc-mirror-ico { flex: none; font-size: 15px; line-height: 1; color: var(--accent);
  text-shadow: 0 0 10px rgba(179,136,255,.55); transform: translateY(1px); }
.fc-mirror-tx { min-width: 0; opacity: .96; }

/* Expandable day forecast */
.fc-text.clamped { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.fc-toggle { display: flex; align-items: center; justify-content: center; gap: 10px; width: 100%; margin-top: 10px; font-size: 14px; }
.fc-toggle .fc-chev { opacity: .6; font-size: 15px; line-height: 1; }

.rec-cols { display: grid; grid-template-columns: repeat(2,minmax(0,1fr)); gap: 14px; margin-top: 4px; }
/* N9: the reco column headers are bare <h4> — give them a real column-header style */
.rec-cols h4 { font-size: 13px; font-weight: 800; margin: 0 0 6px; color: var(--text); }
.rec-list { list-style: none; padding: 0; margin: 8px 0 0; }
.rec-list li { position: relative; padding-left: 20px; margin: 7px 0; font-size: calc(14px * var(--font-scale)); line-height: 1.35; color: var(--text); }
.rec-list li::before { position: absolute; left: 0; top: 0; font-weight: 800; }
.rec-list.good li::before { content: "✓"; color: var(--good); }
.rec-list.bad li::before { content: "✕"; color: var(--bad); }

/* Compatibility type selector */
.type-select { display: flex; gap: 8px; }
.type-opt { flex: 1; padding: 11px 4px; border-radius: 12px; background: var(--bg2); border: 2px solid transparent;
  color: var(--text); font-size: 13px; font-weight: 600; cursor: pointer; white-space: nowrap; }
.type-opt.sel { border-color: var(--accent); background: rgba(179,136,255,0.14); }
.type-opt:active { transform: scale(0.97); }

/* Compatibility picker divider */
.vs-divider { display: flex; align-items: center; text-align: center; margin: 12px 0; color: var(--hint); }
.vs-divider::before, .vs-divider::after { content: ""; flex: 1; height: 1px; background: var(--line); }
.vs-divider span { padding: 0 12px; font-size: 20px; }

/* Compatibility result */
.couple { display: flex; align-items: center; justify-content: center; gap: 14px; margin: 8px 0; }
.couple .person { text-align: center; }
.couple .person .em { font-size: 40px; }
.couple .heart { font-size: 30px; }
.big-score {
  text-align: center; font-size: 64px; font-weight: 900; margin: 6px 0 0;
  background: linear-gradient(135deg, var(--accent), var(--accent2));
  -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent;
}
.compat-summary { font-size: calc(15px * var(--font-scale)); line-height: 1.45; margin: 10px 6px 2px; text-align: center; }
.teasers { display:flex; flex-direction:column; gap:8px; margin-top:10px; }
.teaser { width:100%; box-sizing:border-box; font-size:13.5px; padding:13px 15px; border-radius:16px;
  background:var(--bg2); border:1px solid var(--line); color:var(--hint);
  display:flex; align-items:center; gap:12px; }
.teaser .tq { flex:1; min-width:0; line-height:1.3; }
.teaser .ta { flex:1.15; min-width:0; text-align:right; line-height:1.3; color:var(--accent); font-weight:700; }
/* «Астра»: .tlock — контейнер svg-глифа .pg--inline; полная яркость (дыхание pg-breathe само
   притемняет глиф), никакого opacity на контейнере. */
.teaser .tlock { margin-left:auto; flex:none; display:inline-flex; align-items:center; }
.teaser.answered { color:var(--text); border-color:var(--accent); background:rgba(179,136,255,0.12); }
/* Приглушаем ТОЛЬКО контент ряда, НЕ астру (основатель 2026-07-18: «символ за затемнением
   тоже затемнён — не затемняй»). opacity на контейнере нельзя перебить у ребёнка → дробим:
   dim на всех прямых детях КРОМЕ астры (.pg/.prem-tag/.lock-badge), астра остаётся 100%. */
.dim-row.lock > :not(.lock-badge),
.karma-row.lock > :not(.pg):not(.prem-tag) { opacity: .58; }
/* (схлопнуто «Астрой»: legacy .lock-badge{float:right} удалён — бейдж рендерится только внутри
   .dim-row.lock и позиционируется абсолютной 44×44-хит-зоной ниже, в блоке compat result) */

/* Tab bar */
/* R1-BLOCKER-16: the bar had NO z-index (auto = 0), so ANY screen whose container creates a layer
   above it swallowed every tab tap — the profile editor (.onb-redesign .onb-content{z-index:1}) was
   the first screen to pair that shell with a VISIBLE tabbar, and taps landed in the content behind:
   .ro-val opened the correction sheet, .del-link asked to delete a person. Fixed bottom chrome must
   sit above page content by definition. 30 stays BELOW every real overlay: sticky screen headers 20,
   twin toast 55, sheets 60, toasts 80. */
.tabbar {
  position: fixed; bottom: 0; left: 0; right: 0; max-width: 520px; margin: 0 auto; z-index: 30;
  display: flex; background: rgba(20,16,40,0.92); -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px);
  border-top: 1px solid var(--line); padding: 8px 0 calc(8px + var(--sab, env(safe-area-inset-bottom)));
}
.tab { flex: 1; background: none; border: 0; color: #a79ecb; display: flex; flex-direction: column;
  align-items: center; gap: 3px; font-size: 11px; font-weight: 600; cursor: pointer; }
/* Высота коробки иконки задана ЯВНО и одинаково для всех вкладок. Иначе её определяет
   шрифт: у эмодзи строчная коробка выходила 26px, у SVG-иконки «Матрицы» — 23px, и её
   подпись сидела на 3px выше трёх соседних (замерено). Метрики эмодзи вдобавок разные
   на iOS и Android, так что без фиксации перекос был бы ещё и платформозависимым. */
/* ВСЕ ЧЕТЫРЕ иконки — векторные (2026-08-03). Эмодзи убраны намеренно: они приносили
   чужую палитру, по-разному метрились на iOS/Android и на Linux рисовались набором Noto,
   который основатель точно назвал «линуксовым». Apple в таббарах эмодзи не использует
   вовсе. filter:grayscale снят — для одноцветной фигуры он ничего не делал, гашение даёт
   сам color: var(--hint). */
.tab .tab-ico { position: relative; display: grid; place-items: center; height: 26px; }
/* СВЕЧЕНИЕ РАЗДЕЛА (вариант C, выбран основателем 2026-08-03). Делается ГОТОВЫМ
   radial-gradient, а НЕ filter/blur/box-shadow — те три запрещены перф-доктриной и роняют
   кадры на дешёвом Android. Тот же приём уже носят гало планет на колесе (.fcw-halo), так
   что таббар говорит с главным экраном на одном языке.
   Цвет берётся из --ic, своего у каждой вкладки: это не украшение, а вторая подсказка,
   куда ты жмёшь. Состояние несёт ТОЛЬКО opacity —她 разрешена к анимации. */
.tab .tab-ico::before { content: ""; position: absolute; width: 36px; height: 36px;
  border-radius: 50%; pointer-events: none;
  background: radial-gradient(circle, var(--ic, #B388FF) 0%, transparent 68%);
  opacity: .42; transition: opacity .18s ease; }
.tab.active .tab-ico::before { opacity: 1; }
.tab .tab-ico svg { position: relative; width: 26px; height: 26px; display: block; fill: none;
  stroke: currentColor; stroke-width: 2.3; stroke-linecap: round; stroke-linejoin: round; }
/* Палитра по разделам. Маджента #FF5C8A СОЗНАТЕЛЬНО не взята: в системе она означает
   только время и дефицит (таймер промо). Совместимости отдан --accent2 — тот же розовый,
   которым уже обведена выбранная карточка человека. */
.tab[data-tab="forecast"]     .tab-ico { --ic: #FFD98A; }   /* золото — солнце дня */
.tab[data-tab="matrix"]       .tab-ico { --ic: #B388FF; }   /* фиолетовый — цвет раздела */
.tab[data-tab="personality"]  .tab-ico { --ic: #CFE0FF; }   /* лунно-белый — «ты сам» */
.tab[data-tab="compat"]       .tab-ico { --ic: #FF7EB6; }   /* розовый accent2 — люди */
/* «Матрица» носит собственный знак раздела (та же розетка, что на двери), а не эмодзи:
   эмодзи здесь приносили чужой цвет — ✳️ рисовался зелёным при фиолетово-золотой палитре.
   SVG берёт currentColor, поэтому гаснет и зажигается вместе с остальными вкладками сам,
   без filter:grayscale, который для одноцветной фигуры всё равно ничего не делает. */
.tab .tab-ico--mx { filter:none; }   /* исторический класс, стиль теперь общий выше */
/* 26px против прежних 23 (основатель: «иконку можно чуть крупнее»). Контурная фигура
   при равном размере читается мельче заливной эмодзи, поэтому она догоняет их по
   ВНЕШНЕМУ габариту, а не по номиналу. Толщина штриха подросла пропорционально. */
.tab .tab-ico--mx svg { width:26px; height:26px; display:block; fill:none;
  stroke:currentColor; stroke-width:2.3; }
.tab .tab-ico--mx circle,
.tab .tab-ico .ico-dot { fill:currentColor; stroke:none; }
.tab.active { color: var(--text); }
.tab.active .tab-ico { filter: none; }

/* Misc */
.spinner { width: 44px; height: 44px; border: 4px solid var(--line); border-top-color: var(--accent);
  border-radius: 50%; animation: spin 0.8s linear infinite; margin: 40px auto; }
@keyframes spin { to { transform: rotate(360deg); } }

/* On-brand astrology loader: a pulsing zodiac core with two planets in orbit */
.astro-loader { position: relative; width: 132px; height: 132px; margin: 18px auto 28px; }
.astro-loader .al-core {
  position: absolute; top: 50%; left: 50%; width: 30px; height: 30px; margin: -15px 0 0 -15px;
  border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, #fff 0%, var(--accent2) 40%, var(--accent) 100%);
  box-shadow: 0 0 18px 4px rgba(179,136,255,0.55), 0 0 34px 8px rgba(255,126,182,0.35);
  animation: al-pulse 2.2s ease-in-out infinite;
}
.astro-loader .al-ring {
  position: absolute; top: 50%; left: 50%; border-radius: 50%;
  border: 1px solid rgba(179,136,255,0.22); transform: translate(-50%, -50%);
}
.astro-loader .al-ring.r1 { width: 84px; height: 84px; }
.astro-loader .al-ring.r2 { width: 132px; height: 132px; border-color: rgba(255,126,182,0.16); border-style: dashed; }
/* Orbit wrappers spin; the planet sits on the orbit edge */
.astro-loader .al-orbit { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); }
.astro-loader .al-orbit.o1 { width: 84px; height: 84px; animation: spin 3.4s linear infinite; }
.astro-loader .al-orbit.o2 { width: 132px; height: 132px; animation: spin 6.2s linear infinite reverse; }
.astro-loader .al-planet {
  position: absolute; top: -5px; left: 50%; width: 12px; height: 12px; margin-left: -6px;
  border-radius: 50%;
}
.astro-loader .al-orbit.o1 .al-planet { background: var(--accent2); box-shadow: 0 0 10px 2px rgba(255,126,182,0.7); }
.astro-loader .al-orbit.o2 .al-planet { width: 9px; height: 9px; margin-left: -4.5px; background: var(--accent); box-shadow: 0 0 9px 2px rgba(179,136,255,0.7); }
/* Tiny twinkling stars in the field */
.astro-loader .al-star { position: absolute; width: 3px; height: 3px; border-radius: 50%; background: #fff; opacity: .6; animation: al-twinkle 1.8s ease-in-out infinite; }
.astro-loader .al-star.s1 { top: 8px; left: 22px; animation-delay: .1s; }
.astro-loader .al-star.s2 { top: 26px; right: 10px; animation-delay: .7s; }
.astro-loader .al-star.s3 { bottom: 14px; left: 14px; animation-delay: 1.2s; }
.astro-loader .al-star.s4 { bottom: 26px; right: 24px; animation-delay: .4s; }
@keyframes al-pulse {
  0%, 100% { transform: scale(1); box-shadow: 0 0 18px 4px rgba(179,136,255,0.55), 0 0 34px 8px rgba(255,126,182,0.35); }
  50% { transform: scale(1.18); box-shadow: 0 0 26px 7px rgba(179,136,255,0.7), 0 0 48px 12px rgba(255,126,182,0.5); }
}
@keyframes al-twinkle { 0%, 100% { opacity: .25; transform: scale(.7); } 50% { opacity: 1; transform: scale(1.15); } }
/* A11Y-2 (R9): honor prefers-reduced-motion for the base spinner + the astro loader's orbits/core/stars */
@media (prefers-reduced-motion: reduce) {
  .spinner, .astro-loader .al-orbit, .astro-loader .al-core, .astro-loader .al-star { animation: none !important; }
}

/* ── natal-chart "wheel assembling" loader (birth-chart compute) ─────────── */
.natal-loader { position: relative; width: 150px; height: 150px; margin: 14px auto 30px; }
.natal-loader > span { position: absolute; top: 50%; left: 50%; }
.natal-loader .nl-rim {
  width: 150px; height: 150px; margin: -75px 0 0 -75px; border-radius: 50%;
  border: 1.5px solid var(--lt-soft); box-shadow: 0 0 22px var(--lt-glow) inset, 0 0 16px -4px var(--lt-glow);
}
/* 12 zodiac ticks in a thin ring, slowly turning */
.natal-loader .nl-wheel {
  width: 150px; height: 150px; margin: -75px 0 0 -75px; border-radius: 50%;
  background: repeating-conic-gradient(from 0deg, var(--lt) 0 1deg, transparent 1deg 30deg);
  -webkit-mask: radial-gradient(circle, transparent 60px, #000 61px, #000 70px, transparent 71px);
          mask: radial-gradient(circle, transparent 60px, #000 61px, #000 70px, transparent 71px);
  opacity: .5; animation: spin 26s linear infinite;
}
/* astrolabe sweep — a wedge of light scanning the wheel (the "computing" beat) */
.natal-loader .nl-sweep {
  width: 150px; height: 150px; margin: -75px 0 0 -75px; border-radius: 50%;
  background: conic-gradient(from 0deg, transparent 0deg, var(--lt-glow) 36deg, var(--lt2) 52deg, transparent 64deg);
  -webkit-mask: radial-gradient(circle, transparent 13px, #000 15px, #000 71px, transparent 73px);
          mask: radial-gradient(circle, transparent 13px, #000 15px, #000 71px, transparent 73px);
  opacity: .85; animation: spin 2.4s linear infinite;
}
/* aspect lines — a slow rotating geometric figure through the centre */
.natal-loader .nl-aspects { width: 132px; height: 132px; margin: -66px 0 0 -66px; animation: spin 14s linear infinite reverse; }
.natal-loader .nl-aspects::before, .natal-loader .nl-aspects::after {
  content: ""; position: absolute; top: 50%; left: 6%; right: 6%; height: 1px; margin-top: -.5px;
  background: linear-gradient(90deg, transparent, var(--lt-soft) 30%, var(--lt-soft) 70%, transparent);
}
.natal-loader .nl-aspects::before { transform: rotate(60deg); }
.natal-loader .nl-aspects::after { transform: rotate(-60deg); }
/* orbiting planets */
.natal-loader .nl-orbit.o1 { width: 78px;  height: 78px;  margin: -39px 0 0 -39px; animation: spin 3.6s linear infinite; }
.natal-loader .nl-orbit.o2 { width: 116px; height: 116px; margin: -58px 0 0 -58px; animation: spin 6s linear infinite reverse; }
.natal-loader .nl-orbit.o3 { width: 150px; height: 150px; margin: -75px 0 0 -75px; animation: spin 9s linear infinite; }
.natal-loader .nl-planet { position: absolute; top: -4px; left: 50%; width: 8px; height: 8px; margin-left: -4px; border-radius: 50%; }
.natal-loader .nl-orbit.o1 .nl-planet { background: var(--lt2); box-shadow: 0 0 10px 2px var(--lt-glow); }
.natal-loader .nl-orbit.o2 .nl-planet { width: 6px; height: 6px; margin-left: -3px; background: var(--lt); box-shadow: 0 0 9px 2px var(--lt-glow); }
.natal-loader .nl-orbit.o3 .nl-planet { width: 5px; height: 5px; margin-left: -2.5px; background: #fff; box-shadow: 0 0 8px 2px var(--lt2); }
/* pulsing core */
.natal-loader .nl-core {
  width: 16px; height: 16px; margin: -8px 0 0 -8px; border-radius: 50%;
  background: radial-gradient(circle at 40% 35%, #fff, var(--lt2) 45%, var(--lt) 100%);
  box-shadow: 0 0 18px 4px var(--lt-glow); animation: nl-pulse 1.8s ease-in-out infinite;
}
.natal-loader .nl-star { width: 2.5px; height: 2.5px; border-radius: 50%; background: #fff; opacity: .5; margin: 0; animation: al-twinkle 2s ease-in-out infinite; }
.natal-loader .nl-star.s1 { top: 6%;  left: 18%; animation-delay: .1s; }
.natal-loader .nl-star.s2 { top: 16%; left: 84%; animation-delay: .7s; }
.natal-loader .nl-star.s3 { top: 82%; left: 12%; animation-delay: 1.2s; }
.natal-loader .nl-star.s4 { top: 88%; left: 76%; animation-delay: .4s; }
.natal-loader .nl-star.s5 { top: 50%; left: 96%; animation-delay: 1.6s; }
@keyframes nl-pulse { 0%,100% { transform: scale(.85); opacity: .8; } 50% { transform: scale(1.12); opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .natal-loader .nl-wheel, .natal-loader .nl-sweep, .natal-loader .nl-aspects, .natal-loader .nl-orbit { animation: none; } .natal-loader .nl-core, .natal-loader .nl-star { animation: none !important; } }   /* MIN-31: the pulsing core + twinkling stars also honor reduced-motion */

.fade-in { animation: fade .25s ease; }
@keyframes fade { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
.row { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.muted-link { color: var(--accent); font-weight: 600; cursor: pointer; }
.pill { display:inline-block; font-size: 12px; padding: 3px 9px; border-radius: 12px; background: rgba(179,136,255,0.18); color: var(--accent); font-weight: 700; }

/* ===========================================================================
   COMPATIBILITY REDESIGN — per-line themed selection + result screens.
   Everything visual is scoped under .compat-screen so unrelated screens keep
   the static palette. The four per-line tokens (--lt/--lt2/--lt-soft/--lt-glow)
   are set by data-line on the wrapper (and on each .line-opt chip / recent row).
   Source of truth: design/theme.css + design/compat_prototype.html.
   =========================================================================== */

/* per-line tokens (set data-line on the screen wrapper) */
:root { --lt:#b388ff; --lt2:#ff7eb6; --lt-soft:rgba(179,136,255,.16); --lt-glow:rgba(179,136,255,.38); }
[data-line="romance"]    { --lt:#ff7eb6; --lt2:#b388ff; --lt-soft:rgba(255,126,182,.16); --lt-glow:rgba(255,126,182,.40); }
[data-line="friendship"] { --lt:#5be3a7; --lt2:#7ec8ff; --lt-soft:rgba(91,227,167,.16);  --lt-glow:rgba(91,227,167,.38); }
[data-line="family"]     { --lt:#ffd166; --lt2:#ff7eb6; --lt-soft:rgba(255,209,102,.16); --lt-glow:rgba(255,209,102,.36); }
/* Cosmic Gift — the invite screen / card theme (violet → sky), mirrors render_invite THEME */
[data-line="invite"]     { --lt:#b388ff; --lt2:#7ec8ff; --lt-soft:rgba(179,136,255,.16); --lt-glow:rgba(179,136,255,.42); }

/* bucket -> colour (high>=75 good · mid>=55 warn · low bad) */
.compat-screen .b-high { color: var(--good); }
.compat-screen .b-mid  { color: var(--warn); }
.compat-screen .b-low  { color: var(--bad);  }
.compat-screen .stroke-line { stroke: var(--lt); }

/* line-themed CTA + share (per-line gradient, not the static accent gradient) */
.compat-screen .btn { display:flex; align-items:center; justify-content:center; gap:8px;
  background: linear-gradient(135deg, var(--lt), var(--lt2)); color:#1a1030; transition: transform .08s, opacity .15s; }
.compat-screen .btn:active { transform: scale(.99); }
.compat-screen .btn.ghost { background: transparent; color: var(--text); border: 1px solid var(--line); }
.compat-screen .btn-row { display:flex; gap:10px; margin-top:10px; }
.compat-screen .btn-row .btn { margin-top:0; }

/* ===== RESULT · sticky SHARE DOCK (the k-factor lever) =====================
   Inherits per-line --lt/--lt2/--lt-glow from [data-line] → pink/mint/gold for
   free. Glued to the thumb zone, in view the entire read. */
.compat-screen.result-screen { padding-bottom: 24px; }
.compat-screen .share-dock {
  position: sticky; bottom: 0; z-index: 20;
  margin: 22px -16px 0;
  padding: 14px 16px calc(14px + var(--sab, env(safe-area-inset-bottom)));
  background: linear-gradient(to top, var(--bg) 36%, rgba(15,12,29,.82) 70%, rgba(15,12,29,0) 100%);
  backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
  cursor: pointer;   /* founder 2026-07-05: the WHOLE dock shares (users tapped the sub-text / dock, not just the button) */
}
.compat-screen .share-dock .share-sub { cursor: pointer; }
/* ОБЩИЙ фикс гигантского подвала (основатель 2026-07-23, волна 2): 90px низа #screen — это
   запас под fixed таб-бар; на ЛЮБОМ экране со скрытым таб-баром (результат совместимости,
   пейвол из глубоких контекстов и т.п.) он превращается в мёртвую пустоту.
   Было `body:has(#tabbar.hidden)` — единственный живой :has() в проекте и нарушение
   перф-доктрины: структурный селектор на body пересчитывается движком при каждой смене
   классов у #tabbar, а старые LatAm-вебвью его не знают вовсе. Класс-хук ставят
   tabbarShow()/tabbarHide() в app.js — тот же приём, что описан в styles.css:2757. */
body.tabbar-hidden #screen{ padding-bottom: 16px; }
/* призрачный центр совместимости — теперь тап-триггер, приглашаем курсором */
.pick-score.ghost.is-ready{ cursor: pointer; -webkit-tap-highlight-color: transparent; }
.pick-score.ghost.is-ready:active{ transform: scale(.94); }
/* Non-disabled "preparing the card" state: keeps the button actionable (no dead taps), the JS in-flight guard
   prevents a double dialog. Just a subtle dim so the tap feels acknowledged while the ≤1.8s warm races. */
.btn.share-cta.sharing, .lil-share.sharing { opacity: .68; }
.compat-screen .btn.share-cta {
  position: relative; overflow: hidden; width: 100%; margin: 0;
  min-height: 58px; border-radius: 18px; padding: 12px 16px;
  display: grid; grid-template-columns: auto minmax(0,1fr) auto; align-items: center; gap: 12px;
  background: linear-gradient(135deg, var(--lt) 0%, var(--lt2) 100%);
  color: #1a1030;
  box-shadow: 0 0 0 1px var(--lt-soft), 0 12px 30px -6px var(--lt-glow), 0 2px 0 rgba(255,255,255,.22) inset;
  transition: transform .12s ease, box-shadow .2s ease;
}
.compat-screen .btn.share-cta .sc-ic { font-size: 22px; line-height: 1; filter: drop-shadow(0 1px 2px rgba(0,0,0,.18)); }
.compat-screen .btn.share-cta .sc-tx { text-align: center; font-size: 17px; font-weight: 800; letter-spacing: -.2px; }
.compat-screen .btn.share-cta .sc-score {
  font-size: 15px; font-weight: 900; padding: 4px 11px; border-radius: 20px;
  background: rgba(26,16,48,.16); color: #1a1030;
}
.compat-screen .share-sub { text-align: center; margin: 9px 0 0; font-size: 12.5px; font-weight: 700; color: var(--text); opacity: .9; }
.compat-screen .btn.share-cta:active {
  transform: scale(.985);
  box-shadow: 0 0 0 1px var(--lt-soft), 0 6px 18px -8px var(--lt-glow), 0 2px 0 rgba(255,255,255,.22) inset;
}
/* one soft light-bar shimmer sweeps the face ~once / 5.5s */
.compat-screen .btn.share-cta::after {
  content: ""; position: absolute; top: 0; bottom: 0; left: -45%; width: 40%;
  background: linear-gradient(100deg, rgba(255,255,255,0) 0%, rgba(255,255,255,.38) 50%, rgba(255,255,255,0) 100%);
  transform: skewX(-18deg); animation: shareShine 5.5s ease-in-out infinite; pointer-events: none;
}
@keyframes shareShine { 0%, 62% { left: -45%; } 86%, 100% { left: 130%; } }
/* DELETE: demoted, owner-only, revealed only at the very bottom of scroll */
.compat-screen .compat-del-link {
  display: block; width: max-content; margin: 18px auto 4px; padding: 8px 12px;
  background: none; border: 0; font-size: 13px; font-weight: 600; color: var(--hint); opacity: .6; cursor: pointer;
}
.compat-screen .compat-del-link:active { color: var(--bad); opacity: 1; }
@media (prefers-reduced-motion: reduce) { .compat-screen .btn.share-cta::after { animation: none; display: none; } }

/* RESULT · topbar QUICK-SHARE orb — round glassy accent-ring (complements the
   dock without cloning it: round+hollow+line-art vs wide+solid+emoji). */
.compat-screen .topbar .tb-quickshare {
  flex: none; position: relative;
  width: 38px; height: 38px; border-radius: 50%;
  display: grid; place-items: center; padding: 0;
  cursor: pointer; -webkit-tap-highlight-color: transparent;
  color: var(--lt);
  background: radial-gradient(120% 120% at 50% 0%, var(--lt-soft) 0%, rgba(20,16,40,0) 72%), var(--bg2);
  border: 1px solid var(--lt);
  box-shadow: 0 0 0 3px var(--lt-soft), 0 5px 16px -5px var(--lt-glow);
  transition: transform .14s cubic-bezier(.2,.8,.3,1.4), box-shadow .2s ease, background .2s ease;
  animation: tbShareOrbPop .42s cubic-bezier(.2,.9,.25,1.5) both .1s;
}
.compat-screen .topbar .tb-quickshare svg { width: 18px; height: 18px; display: block; filter: drop-shadow(0 0 5px var(--lt-glow)); }
.compat-screen .topbar .tb-quickshare::before { content: ""; position: absolute; inset: -4px; border-radius: 50%; }
.compat-screen .topbar .tb-quickshare:active {
  transform: scale(.9); background: var(--lt-soft);
  box-shadow: 0 0 0 4px var(--lt-glow), 0 2px 8px -3px var(--lt-glow);
}
@keyframes tbShareOrbPop { 0% { transform: scale(.4); opacity: 0; } 60% { transform: scale(1.12); opacity: 1; } 100% { transform: scale(1); } }
@media (prefers-reduced-motion: reduce) { .compat-screen .topbar .tb-quickshare { animation: none; } }

/* ---- HERO (dark cosmos + per-line radial glow + pure-CSS motif) ---- */
.compat-hero { position:relative; overflow:hidden; border-radius:20px; padding:12px 16px 13px; margin:4px 0 2px;
  text-align:center; border:1px solid var(--line);
  background:
    radial-gradient(120% 100% at 50% -18%, var(--lt-soft) 0%, rgba(34,26,61,0) 60%),
    linear-gradient(165deg,#2a2150 0%, var(--card) 70%);
  transition: background .25s ease; }
.compat-hero .pairs-badge { position:absolute; top:14px; right:14px; display:flex; align-items:center; gap:5px;
  background:rgba(15,12,29,.55); border:1px solid var(--line); border-radius:20px;
  padding:5px 11px; font-size:12px; font-weight:700; color:var(--text); -webkit-backdrop-filter:blur(6px); backdrop-filter:blur(6px); }
.compat-hero .pairs-badge b { color:var(--lt); }
.compat-hero h1 { margin-bottom:1px; font-size:21px; }
.compat-hero .hero-sub { color:var(--hint); font-size:13px; margin:0; }
.hero-motif { position:relative; width:60px; height:60px; margin:0 auto 6px; }
.hero-motif .halo { position:absolute; inset:0; border-radius:50%; border:1px solid var(--lt); opacity:.30; }
.hero-motif .halo.h2 { inset:-9px; border-style:dashed; opacity:.16; }
.hero-motif .glyph { position:absolute; inset:0; display:flex; align-items:center; justify-content:center;
  font-size:30px; filter:drop-shadow(0 0 10px var(--lt-glow)); animation:floaty 4s ease-in-out infinite; }
.hero-motif .orbit { position:absolute; top:50%; left:50%; width:60px; height:60px; margin:-30px 0 0 -30px;
  animation:spin 9s linear infinite; }
.hero-motif .orbit .dot { position:absolute; top:-3px; left:50%; width:7px; height:7px; margin-left:-3.5px; border-radius:50%;
  background:var(--lt); box-shadow:0 0 8px 2px var(--lt-glow); }
.hero-motif .star { position:absolute; width:3px; height:3px; border-radius:50%; background:#fff; opacity:.6; animation:tw 2s ease-in-out infinite; }
.hero-motif .star.s1 { top:6px; left:12px; animation-delay:.2s; }
.hero-motif .star.s2 { bottom:8px; right:6px; animation-delay:.9s; }
.hero-motif .star.s3 { bottom:18px; left:2px; animation-delay:1.4s; }
@keyframes floaty { 0%,100% { transform:translateY(0); } 50% { transform:translateY(-6px); } }
@keyframes tw { 0%,100% { opacity:.25; transform:scale(.7); } 50% { opacity:1; transform:scale(1.15); } }

/* ---- LINE SELECTOR (prominent, drives theming) ---- */
.line-select { display:flex; gap:8px; margin:14px 0 6px; }
.line-opt { flex:1; border:2px solid transparent; background:var(--bg2); border-radius:16px; padding:12px 4px;
  cursor:pointer; color:var(--hint); display:flex; flex-direction:column; align-items:center; gap:5px;
  font-size:13px; font-weight:700; transition:transform .08s, border-color .15s, background .15s, color .15s; }
.line-opt .lo-ico { font-size:23px; line-height:1; filter:grayscale(.45); transition:filter .15s; }
.line-opt:active { transform:scale(.97); }
.line-opt.sel { color:var(--text); border-color:var(--lt); background:var(--lt-soft); }
.line-opt.sel .lo-ico { filter:none; }

/* ---- PROFILE PICKERS (avatar card + transparent native <select> + connector) ---- */
.pick-row { display:flex; align-items:center; gap:8px; margin-top:4px; }
.picker { flex:1; min-width:0; background:var(--bg2); border:1px solid var(--line); border-radius:16px;
  padding:14px 10px 12px; text-align:center; cursor:pointer; transition:transform .08s; position:relative; }
.picker:active { transform:scale(.98); }
.picker .pk-ava { width:60px; height:60px; border-radius:50%; margin:0 auto 8px; display:flex; align-items:center;
  justify-content:center; font-size:30px; background:var(--card); border:2px solid var(--lt); position:relative; }
/* Real avatar photo (self only) inside a compat avatar circle + its zodiac badge.
   Glyph-only avatars (no photo) get NO badge — the glyph already IS the sign. */
.c-ava-img { width:100%; height:100%; border-radius:50%; object-fit:cover; }
.compat-screen .zbadge, .recent-card .zbadge { position:absolute; right:-2px; bottom:-2px; width:20px; height:20px; box-sizing:border-box;
  border-radius:50%; background:var(--lt); color:#fff; border:2px solid var(--bg); display:flex; align-items:center; justify-content:center;
  font-size:11px; line-height:1; }
.picker .pk-name { font-weight:700; font-size:15px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.picker .pk-date { color:var(--hint); font-size:12px; margin-top:2px; }
.picker .pk-chev { position:absolute; top:10px; right:11px; color:var(--hint); font-size:16px; z-index:1; }
.picker .pk-select { position:absolute; inset:0; width:100%; height:100%; opacity:0; border:0; padding:0; margin:0; cursor:pointer; }
.picker.add { border-style:dashed; color:var(--hint); }
.picker.add .pk-ava { border-style:dashed; border-color:var(--line); color:var(--hint); font-size:26px; }
.pick-link { flex:0 0 auto; width:40px; height:40px; border-radius:50%; display:flex; align-items:center; justify-content:center;
  font-size:18px; background:var(--card); border:1px solid var(--lt); color:var(--lt); box-shadow:0 0 12px var(--lt-glow); }
/* ready pair: the centre motif is itself the calc trigger (founder 2026-07-22) — invite the tap */
.pick-link.is-ready { cursor:pointer; -webkit-tap-highlight-color:transparent; animation:pickReady 2s ease-in-out infinite; }
.pick-link.is-ready:active { transform:scale(.92); }
@keyframes pickReady { 0%,100%{ box-shadow:0 0 12px var(--lt-glow); } 50%{ box-shadow:0 0 20px var(--lt-glow), 0 0 0 3px rgba(179,136,255,.12); } }
@media (prefers-reduced-motion:reduce){ .pick-link.is-ready{ animation:none; } }

/* ---- RECENT list (avatar — themed mini-ring — avatar + line chip) ---- */
.compat-screen .recent-card { display:flex; align-items:center; gap:12px; padding:12px 14px; }
.recent-card .ra { width:40px; height:40px; border-radius:50%; background:var(--bg2); border:1px solid var(--line);
  display:flex; align-items:center; justify-content:center; font-size:20px; flex:none; position:relative; }
.recent-card .rmid { flex:1; display:flex; align-items:center; justify-content:center; gap:8px; min-width:0; }
.recent-card .rname { font-size:13px; color:var(--hint); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; flex:1; max-width:74px; }
.recent-card .rname.l { text-align:right; } .recent-card .rname.r { text-align:left; }
.mini-ring { position:relative; width:44px; height:44px; flex:none; }
.mini-ring svg { transform:rotate(-90deg); }
.mini-ring .mr-pct { position:absolute; inset:0; display:flex; align-items:center; justify-content:center; font-size:12px; font-weight:800; }
.rline-chip { flex:none; width:30px; height:30px; border-radius:50%; display:flex; align-items:center; justify-content:center;
  font-size:15px; border:1px solid var(--line); }
.rline-chip.romance { background:rgba(255,126,182,.14); }
.rline-chip.friendship { background:rgba(91,227,167,.14); }
.rline-chip.family { background:rgba(255,209,102,.14); }
.recent-card .rchev { color:var(--hint); font-size:18px; flex:none; }

/* ---- RESULT · in-content themed topbar ---- */
.compat-screen .topbar { position:sticky; top:0; z-index:20; display:flex; align-items:center; gap:8px;
  padding:10px 16px; min-height:54px; margin:-16px -16px 0;
  background:rgba(20,16,40,.92); -webkit-backdrop-filter:blur(12px); backdrop-filter:blur(12px); border-bottom:1px solid var(--line); }
.compat-screen .topbar .backbtn { background:var(--bg2); color:var(--text); width:38px; height:38px; border-radius:12px;
  font-size:24px; flex:none; }
.compat-screen .topbar .tb-title { font-weight:700; font-size:16px; flex:1; display:flex; align-items:center; gap:7px; }
.compat-screen .topbar .tb-title .tdot { width:9px; height:9px; border-radius:50%; background:var(--lt); box-shadow:0 0 8px var(--lt-glow); }
.compat-screen .topbar .tb-share { border:0; background:var(--bg2); color:var(--text); width:38px; height:38px; border-radius:12px;
  font-size:17px; cursor:pointer; flex:none; }
.compat-screen .topbar .tb-spacer { width:38px; flex:none; }

/* ---- RESULT · hero (couple + centered themed score ring) ---- */
.compat-screen .result-hero { text-align:center; padding:14px 0 2px; position:relative; overflow:hidden; }
.compat-screen .result-hero::before { content:""; position:absolute; top:-40px; left:50%; width:260px; height:200px; margin-left:-130px;
  background:radial-gradient(60% 60% at 50% 50%, var(--lt-glow) 0%, rgba(0,0,0,0) 70%); opacity:.5; pointer-events:none; }
.compat-screen .couple { display:flex; align-items:center; justify-content:center; gap:12px; margin:2px 0 0; position:relative; z-index:1; }
.compat-screen .couple .cp { display:flex; flex-direction:column; align-items:center; gap:7px; width:74px; }
.compat-screen .couple .cp .em { width:60px; height:60px; border-radius:50%; background:var(--card); border:2px solid var(--lt);
  display:flex; align-items:center; justify-content:center; font-size:30px; box-shadow:0 0 16px var(--lt-glow); position:relative; }
.compat-screen .couple .cp .nm { font-size:13px; font-weight:600; line-height:1.1; }
.compat-screen .couple .cp .sg { font-size:11px; color:var(--hint); }
.compat-screen .score-ring { position:relative; width:140px; height:140px; flex:none; font-size:0; }
.compat-screen .score-ring svg { transform:rotate(-90deg); }
.compat-screen .score-ring .sr-fg { stroke-linecap:round; stroke-dasharray:327; stroke-dashoffset:327;
  animation:ring-fill 1.3s cubic-bezier(.22,.9,.3,1) forwards .15s; }
.compat-screen .score-ring .sr-grad-from { stop-color:var(--lt); }
.compat-screen .score-ring .sr-grad-to   { stop-color:var(--lt2); }
@keyframes ring-fill { to { stroke-dashoffset:var(--off); } }
.compat-screen .score-ring .sr-num { position:absolute; inset:0; display:flex; flex-direction:column; align-items:center; justify-content:center; }
.compat-screen .score-ring .sr-num b { font-size:42px; font-weight:900; line-height:1;
  background:linear-gradient(135deg,var(--lt),var(--lt2)); -webkit-background-clip:text; background-clip:text; -webkit-text-fill-color:transparent; }
.compat-screen .score-ring .sr-num span { font-size:8.5px; color:var(--hint); text-transform:uppercase; letter-spacing:0.5px; margin-top:3px;
  max-width:88px; white-space:nowrap; overflow:hidden; text-overflow:clip; text-align:center; }
.compat-screen .verdict { font-size:calc(21px * var(--font-scale)); font-weight:800; margin:14px 0 2px; letter-spacing:-.3px; position:relative; z-index:1; }
.compat-screen .verdict .vbucket { display:inline-block; font-size:11px; font-weight:800; text-transform:uppercase; letter-spacing:1px;
  vertical-align:middle; margin-left:8px; padding:3px 9px; border-radius:20px; background:var(--lt-soft); color:var(--lt); }
.compat-screen .compat-summary { font-size:calc(14.5px * var(--font-scale)); line-height:1.5; color:var(--text); margin:8px 8px 2px; text-align:center; position:relative; z-index:1; }

/* ---- RESULT · dimension rows ---- */
.dim-legend { display:flex; align-items:center; justify-content:space-between; margin:22px 2px 8px; }
.dim-legend h2 { margin:0; }
.dim-legend .lg { font-size:11px; color:var(--warn); display:flex; align-items:center; gap:5px; }
.dim-legend .lg i { width:13px; height:13px; border-radius:4px; border:1.5px dashed var(--warn); display:inline-block; }
.dim-legend .lg[hidden] { display:none; }
.dim-list { display:flex; flex-direction:column; gap:9px; }
.dim-row { display:flex; align-items:center; gap:13px; background:var(--card); border:1px solid var(--line);
  border-radius:14px; padding:13px 14px; cursor:pointer; transition:transform .08s; position:relative; }
.dim-row:active { transform:scale(.99); }
.dim-ico { flex:none; width:40px; height:40px; border-radius:12px; background:var(--lt-soft);
  display:flex; align-items:center; justify-content:center; font-size:20px; }
.dim-main { flex:1; min-width:0; }
.dim-main .dl { font-size:15px; font-weight:700; }
.dim-main .db { font-size:12px; color:var(--hint); margin-top:1px; line-height:1.3; }
.dim-score { flex:none; display:flex; align-items:center; gap:10px; }
.dim-score .num-wrap { text-align:right; display:flex; flex-direction:column; align-items:flex-end; gap:3px; }
.dim-score .dn { font-size:17px; font-weight:800; line-height:1; }
.dim-score .bkt { font-size:9.5px; font-weight:800; text-transform:uppercase; letter-spacing:.6px; padding:2px 7px; border-radius:10px; }
.dim-score .chev { color:var(--hint); font-size:20px; }
.compat-screen .bkt.b-high { background:rgba(91,227,167,.15); }
.compat-screen .bkt.b-mid  { background:rgba(255,209,102,.15); }
.compat-screen .bkt.b-low  { background:rgba(255,107,138,.15); }
/* TENSION dim — fixed gold/dashed meaning (never line-coloured) */
.dim-row.tension .dim-ico { background:transparent; border:1.5px dashed var(--warn); color:var(--warn); }
.dim-row.tension .db { color:var(--warn); opacity:.9; }
/* premium-locked row — blurred preview + lock overlay */
.dim-row.lock .dim-ico { filter:grayscale(.4); opacity:.85; }
.dim-row.lock .dl { opacity:.8; }
.dim-row.lock .num-wrap { user-select:none; }
.locked-dots { font-size:20px; font-weight:800; line-height:1; color:var(--hint); letter-spacing:2px; }
/* «Астра»: .lock-badge стал ПРОЗРАЧНОЙ right-anchored хит-зоной ≥44×44 (a11y, спек sizes) —
   визуал несёт содержимое: кольцо-«печать» .pg--badge 26px, либо якорная капсула .prem-tag
   «✦ PREMIUM» на ПЕРВОМ залоченном ряду (счётчик по факту locked, MAJ-7 server-redaction).
   right:3px + padding:9px ⇒ правый край глифа на прежних 12px; 26+9×2 = 44. */
.dim-row.lock .lock-badge { position:absolute; right:3px; top:50%; transform:translateY(-50%);
  min-width:44px; min-height:44px; box-sizing:border-box; padding:9px;
  display:flex; align-items:center; justify-content:flex-end;
  background:none; border:0; font-size:0; }
.dim-row.lock .chev { visibility:hidden; }

/* ---- RESULT · teasers ---- */
/* Uniform full-width Q&A cards (was inconsistent wrap-pills of varying length). */
.compat-screen .teasers { display:flex; flex-direction:column; gap:8px; margin-top:0; }
.compat-screen .teaser { width:100%; box-sizing:border-box; font-size:13.5px; padding:13px 15px; border-radius:16px;
  background:var(--bg2); border:1px solid var(--line); color:var(--hint);
  display:flex; align-items:center; gap:12px; cursor:pointer; }
.compat-screen .teaser .tq { flex:1; min-width:0; line-height:1.3; }
.compat-screen .teaser .ta { flex:1.15; min-width:0; text-align:right; line-height:1.3; color:var(--lt); font-weight:700; }
.compat-screen .teaser .tlock { margin-left:auto; flex:none; display:inline-flex; align-items:center; }
.compat-screen .teaser.answered { border-color:var(--lt); background:var(--lt-soft); }
.compat-screen .teaser.answered .tq { color:var(--text); }

/* ---- RESULT · key dynamics ---- */
.dyn-card { background:var(--card); border:1px solid var(--line); border-radius:var(--radius); padding:6px 16px; }
.dyn { display:flex; align-items:center; gap:11px; padding:11px 0; border-bottom:1px solid var(--line); }
.dyn:last-child { border-bottom:0; }
.dyn .dyn-ico { width:32px; height:32px; border-radius:50%; background:var(--lt-soft); color:var(--lt);
  display:flex; align-items:center; justify-content:center; font-size:15px; flex:none; }
.dyn .dyn-tx { flex:1; font-size:13.5px; line-height:1.3; }
.dyn .dyn-tag { font-size:12px; font-weight:800; color:var(--lt); flex:none; }

/* ---- DIMENSION DETAIL view ---- */
.dim-detail .dd-head { display:flex; align-items:center; justify-content:space-between; margin:18px 2px 6px; }
.dim-detail .dd-head .dim-ico { width:56px; height:56px; border-radius:16px; font-size:28px; }
.dim-detail .dd-head .dim-ico.tension-ico { background:transparent; border:1.5px dashed var(--warn); color:var(--warn); }
.dim-detail .dd-score { display:flex; flex-direction:column; align-items:flex-end; gap:5px; }
.dim-detail .dd-score b { font-size:34px; font-weight:900; line-height:1; }
.dim-detail .dd-tension { color:var(--warn); font-size:13px; font-weight:600; margin:2px 2px 8px; }
.dim-detail .dd-desc { font-size:calc(15px * var(--font-scale)); line-height:1.55; color:var(--text); margin:8px 2px; }

/* content-api: tappable placement chips + (body,sign)/(line,dim,bucket) descriptions */
.describe-chip { cursor:pointer; }
.describe-chip:active { transform:scale(.99); }
/* tappable cue = filled accent "open" ring (was a .5-opacity ghost › users missed);
   base rule = appearance only → upgrades EVERY .describe-cue (placements, hero, missing, approx) */
.describe-cue { display:inline-flex; align-items:center; justify-content:center; width:18px; height:18px;
  border-radius:50%; flex:none; background:rgba(179,136,255,0.14); color:var(--accent);
  font-size:12px; font-weight:700; line-height:1; opacity:1; }
.pl-row .describe-cue { margin-left:auto; }
.pl-row.describe-chip { border-radius:10px; padding:2px 6px; margin:0 -6px; transition:background .15s ease; }
.pl-row.describe-chip:active { background:rgba(179,136,255,0.12); }   /* was var(--card) === card bg === invisible press */
.hero-main.describe-chip { border-radius:14px; padding:6px 2px; margin:-6px 0; }
.hero-main .describe-cue { width:16px; height:16px; font-size:11px; vertical-align:middle; margin-left:4px; }
/* first-run teach: one caption + a 3-cycle pulse on the first cue, retired on first reading opened */
/* gold, centered, gently beckoning pill — this is a ONE-TIME nudge (removed on the first
   reading opened), so it can afford to stand out from the purple chrome. */
/* full card width, wrapped onto its own row BELOW the two hero columns but still INSIDE
   the card — so the gold pill is clearly part of the block and fits one line in any locale. */
.pl-tap-hint-row { flex-basis:100%; width:100%; text-align:center; margin:2px 0 0; }
.pl-tap-hint { display:inline-flex; align-items:center; gap:6px; padding:6px 14px;
  font-size:11.5px; font-weight:700; letter-spacing:.2px; line-height:1.2;
  color:var(--credit); background:var(--credit-soft); border:1px solid rgba(255,217,138,.34);
  border-radius:999px; box-shadow:0 0 0 0 var(--credit-glow);
  animation:pl-hint-bob 2.4s ease-in-out infinite; }
.pl-tap-hint .describe-cue { display:inline-flex; align-items:center; justify-content:center;
  width:16px; height:16px; margin-left:0; font-size:11px; font-weight:800;
  color:var(--bg); background:var(--credit); border-radius:50%; box-shadow:0 0 6px var(--credit-glow); }
@keyframes pl-hint-bob {
  0%,100% { transform:translateY(0);    box-shadow:0 0 0 0 rgba(255,217,138,0); }
  50%     { transform:translateY(-3px); box-shadow:0 4px 16px var(--credit-glow); }
}
@media (prefers-reduced-motion: reduce) {
  .pl-tap-hint { animation:none; transform:none; box-shadow:0 2px 10px var(--credit-glow); }
}
@keyframes cuePulse { 0%,100% { box-shadow:0 0 0 0 rgba(179,136,255,0); } 50% { box-shadow:0 0 0 5px rgba(179,136,255,0.20); } }
.describe-cue.cue-nudge { animation:cuePulse 1.6s ease-in-out 3; }
@media (prefers-reduced-motion: reduce) { .describe-cue.cue-nudge { animation:none; } }
.describe-body { min-height:64px; }
.describe-title { font-size:16px; font-weight:800; text-align:center; margin:0 0 10px; color:var(--lt,var(--accent)); }
.describe-text { font-size:calc(15px * var(--font-scale)); line-height:1.6; color:var(--text); }
.describe-text p { margin:0 0 10px; }
.describe-text p:last-child { margin-bottom:0; }
.sheet-spinner { width:30px; height:30px; border-width:3px; margin:18px auto; }
.dim-detail .dd-deeper { margin:6px 2px 0; }
.dim-detail .dd-deeper .describe-title { text-align:left; margin-bottom:6px; }
.dim-detail .dd-deeper .describe-text { color:var(--text); }

/* honor reduced motion */
@media (prefers-reduced-motion:reduce) {
  .hero-motif .glyph, .hero-motif .orbit, .hero-motif .star, .compat-screen .score-ring .sr-fg { animation:none; }
  .compat-screen .score-ring .sr-fg { stroke-dashoffset:var(--off); }
}

/* =========================================================================
   «САМОЦВЕТ-ПЕЧАТЬ» — премиальный разбор-шит планеты (openPlacementSheet).
   Заголовок = ИКОНКА-ПЕЧАТЬ: «подушечный» самоцвет (индиго+фиолет ядро, статичные
   грани, top-left блик), двойной ЗОЛОТОЙ ободок (box-shadow), крупный глиф планеты
   золотой гравировкой (var(--pw-seal) + background-clip:text), знак — медальоном в
   углу. Под ним стихийный чип, золотой ТИТУЛ, делитель-астра, текст-МАНУСКРИПТ (serif,
   золотая буквица). Ядро печати ВСЕГДА бренд-фиолет+золото («фиолетовая нам надо»);
   стихия (.seal-sheet[data-el]) красит ТОЛЬКО ауру, внутр. свет камня, глиф знака, чип.
   ЖЕЛЕЗНО: без backdrop-filter/blur/filter/:has; анимации только opacity/transform;
   свечение — статичный radial-gradient/::before; reduced-motion гасит движение.
   Переиспользуем существующий бренд-токен --pw-seal (печать паспорта/пейвола), не плодим.
   ========================================================================= */
/* глифы — монохром-текст, чтобы старый Android не подставил цветной эмодзи */
.seal-sheet .glyph{ font-variant-emoji:text;
  font-family:"Segoe UI Symbol","Noto Sans Symbols2","Apple Symbols",serif; line-height:1; }

.seal-hero{ position:relative; display:flex; flex-direction:column; align-items:center; padding:20px 0 6px; }
/* статичная стихийная АУРА за печатью (radial, НЕ анимируется) */
.seal-hero::before{ content:""; position:absolute; top:-6px; left:50%;
  width:250px; height:250px; transform:translateX(-50%); pointer-events:none;
  background:radial-gradient(circle at 50% 42%,
     var(--el-glow,rgba(179,136,255,.30)) 0%, rgba(179,136,255,.10) 34%, rgba(15,12,29,0) 66%); }

/* сам камень — «подушечная» огранка индиго+фиолет, двойной золотой ободок */
.seal-hero .gem{ position:relative; width:132px; height:132px; border-radius:34px;
  background:
     radial-gradient(120% 120% at 30% 22%, rgba(255,255,255,.22) 0%, rgba(255,255,255,0) 30%),
     radial-gradient(140% 120% at 72% 84%, var(--el-tint,rgba(179,136,255,.30)) 0%, rgba(0,0,0,0) 46%),
     linear-gradient(158deg,#4a3690 0%,#2c2154 44%,#1a1338 100%);
  border:1px solid rgba(255,225,170,.35);
  box-shadow:
     0 0 0 5px rgba(15,12,29,.9),
     0 0 0 6px rgba(255,217,138,.55),
     0 18px 34px -12px rgba(0,0,0,.75),
     inset 0 1px 1px rgba(255,255,255,.28),
     inset 0 -14px 26px -10px rgba(0,0,0,.6);
  display:grid; place-items:center;
  animation:gemIn .6s cubic-bezier(.2,.8,.25,1) both; }
/* грани огранки — статичные диагонали (без filter) */
.seal-hero .gem::before{ content:""; position:absolute; inset:0; border-radius:33px; pointer-events:none;
  background:
     linear-gradient(135deg, rgba(255,255,255,.10) 0%, rgba(255,255,255,0) 26%),
     linear-gradient(315deg, rgba(255,255,255,.07) 0%, rgba(255,255,255,0) 24%),
     linear-gradient(45deg,  rgba(0,0,0,.16) 0%, rgba(0,0,0,0) 30%);
  mix-blend-mode:screen; opacity:.9; }
/* внутренний гравировальный кант */
.seal-hero .gem::after{ content:""; position:absolute; inset:9px; border-radius:26px; pointer-events:none;
  border:1px solid rgba(255,217,138,.20); }
/* глиф планеты — крупный, золотой, «выгравирован» (бренд, НЕ зависит от стихии) */
.seal-hero .gem .pl{ font-size:60px; position:relative; z-index:2;
  background:var(--pw-seal); -webkit-background-clip:text; background-clip:text; color:transparent;
  text-shadow:0 1px 0 rgba(0,0,0,.35); }

/* знак — маленький самоцвет-медальон в правом-нижнем углу печати */
.seal-hero .sign-badge{ position:absolute; right:-6px; bottom:-6px; width:46px; height:46px; border-radius:50%;
  background:
     radial-gradient(120% 120% at 32% 26%, rgba(255,255,255,.24), rgba(255,255,255,0) 40%),
     linear-gradient(160deg,#3a2c74,#221a44);
  border:1px solid rgba(255,217,138,.5);
  box-shadow:0 0 0 3px var(--bg),0 8px 16px -6px rgba(0,0,0,.7),
     inset 0 -6px 12px -6px rgba(0,0,0,.55);
  display:grid; place-items:center; z-index:3;
  animation:badgeIn .5s cubic-bezier(.2,.9,.3,1) .22s both; }
.seal-hero .sign-badge .sg{ font-size:22px;
  background:linear-gradient(180deg,#fff,var(--el,#cdb8ff) 120%);
  -webkit-background-clip:text; background-clip:text; color:transparent; }

/* стихийный чип-подпись под печатью */
.seal-sheet .el-chip{ margin-top:16px; display:inline-flex; align-items:center; gap:7px;
  padding:5px 13px 5px 9px; border-radius:999px;
  background:linear-gradient(180deg,rgba(255,255,255,.05),rgba(255,255,255,.02));
  border:1px solid var(--el-line,rgba(179,136,255,.28));
  font-size:11.5px; font-weight:700; letter-spacing:.02em; color:var(--text);
  animation:fadeUp .5s ease .3s both; }
.seal-sheet .el-chip .dot{ width:8px; height:8px; border-radius:50%;
  background:var(--el,var(--accent)); box-shadow:0 0 8px var(--el,var(--accent)); }
.seal-sheet .el-chip .sub{ color:var(--hint); font-weight:600; }

/* выгравированный золотой ТИТУЛ (перебивает .sheet h2 своей специфичностью) */
.seal-sheet h2.seal-title{ margin:16px 0 0; text-align:center;
  font-size:24px; line-height:1.16; font-weight:800; letter-spacing:.005em;
  background:var(--pw-seal); -webkit-background-clip:text; background-clip:text; color:transparent;
  text-shadow:0 1px 0 rgba(0,0,0,.28);
  animation:fadeUp .55s ease .34s both; }

/* золотой волосяной делитель со звёздочкой-астрой */
.seal-sheet .rule{ display:flex; align-items:center; justify-content:center; gap:10px; margin:16px 2px 4px;
  animation:fadeUp .55s ease .42s both; }
.seal-sheet .rule i{ height:1px; flex:1;
  background:linear-gradient(90deg,rgba(255,217,138,0),rgba(255,217,138,.45),rgba(255,217,138,0)); }
.seal-sheet .rule b{ color:var(--gold); font-size:11px; line-height:1; }

/* МАНУСКРИПТ — тело разбора: serif, золотая буквица; размер масштабируется --font-scale */
.seal-sheet .manuscript{ margin:8px 2px 0;
  font-family:Georgia,"Times New Roman",serif;
  font-size:calc(15.5px * var(--font-scale)); line-height:1.72; color:#e9e2fb;
  animation:fadeUp .6s ease .46s both; }
.seal-sheet .manuscript p{ margin:0 0 12px; }
.seal-sheet .manuscript p:last-child{ margin-bottom:0; }
.seal-sheet .manuscript p.lead::first-letter{
  font-size:46px; line-height:.86; font-weight:700; float:left; margin:4px 9px -2px 0;
  background:var(--pw-seal); -webkit-background-clip:text; background-clip:text; color:transparent;
  font-family:Georgia,serif; }

/* ТЕМИЗАЦИЯ ПО СТИХИИ — аура/свет/акцент; ядро печати остаётся бренд-фиолетом.
   Специфичность .seal-sheet[data-el] перебивает глобальный [data-el] (--el-glow там .40). */
.seal-sheet[data-el="air"]{   --el:var(--el-air);   --el-glow:rgba(111,208,255,.24); --el-tint:rgba(111,208,255,.34); --el-line:rgba(111,208,255,.30); }
.seal-sheet[data-el="fire"]{  --el:var(--el-fire);  --el-glow:rgba(255,138,92,.26);  --el-tint:rgba(255,138,92,.36);  --el-line:rgba(255,138,92,.30); }
.seal-sheet[data-el="water"]{ --el:var(--el-water); --el-glow:rgba(91,140,255,.26);  --el-tint:rgba(91,140,255,.36);  --el-line:rgba(91,140,255,.30); }
.seal-sheet[data-el="earth"]{ --el:var(--el-earth); --el-glow:rgba(91,227,167,.24);  --el-tint:rgba(91,227,167,.34);  --el-line:rgba(91,227,167,.30); }

/* АНИМАЦИИ — только opacity/transform */
@keyframes gemIn{ from{ opacity:0; transform:translateY(10px) scale(.86); } to{ opacity:1; transform:none; } }
@keyframes badgeIn{ from{ opacity:0; transform:scale(.4); } to{ opacity:1; transform:none; } }
@keyframes fadeUp{ from{ opacity:0; transform:translateY(8px); } to{ opacity:1; transform:none; } }
@media (prefers-reduced-motion:reduce){
  .seal-hero .gem, .seal-hero .sign-badge, .seal-sheet .el-chip,
  .seal-sheet h2.seal-title, .seal-sheet .rule, .seal-sheet .manuscript{ animation:none; }
}

/* =========================================================================
   CHECKS ECONOMY — foundation + components (§1–§10, CHECKS_DESIGN.md)
   ========================================================================= */
:root{
  --credit:#ffd98a;                 /* the ✨ currency colour (warm gold) */
  --credit-soft:rgba(255,217,138,.14);
  --credit-glow:rgba(255,217,138,.42);
  /* ── Лилит / Чёрная Луна — eclipse: garnet ember on an un-lit moon, cold-silver waning rim ── */
  --lil:        #d8466e;            /* THE Lilith accent — garnet-rose (NOT gold, NOT pink, NOT --bad) */
  --lil-2:      #e85d86;            /* brighter garnet for glints / icon glow */
  --lil-deep:   #6f1d40;            /* oxblood — the shadow body */
  --lil-core:   #0b0712;            /* eclipse black (below --bg so it recedes) */
  --lil-moon:   #cdd6f0;            /* cold silver — the waning lit rim */
  --lil-soft:   rgba(216,70,110,.14);
  --lil-glow:   rgba(216,70,110,.42);
  --credit-low:var(--warn);
  --credit-zero:var(--bad);
  --sheet-ease:cubic-bezier(.2,.9,.25,1.25);
}

/* A · BOTTOM SHEET — money moments keep context; chrome themed per line */
.sheet-back{position:fixed;inset:0;z-index:60;background:rgba(8,6,18,.62);
  backdrop-filter:blur(3px);-webkit-backdrop-filter:blur(3px);
  display:flex;align-items:flex-end;justify-content:center;
  opacity:0;animation:sheetBackIn .22s ease forwards;}
.sheet-back.closing{animation:sheetBackOut .2s ease forwards;}
.sheet{width:100%;max-width:520px;
  background:linear-gradient(180deg,var(--bg2) 0%,var(--bg) 70%);
  border:1px solid var(--line);border-bottom:0;border-radius:24px 24px 0 0;
  padding:8px 18px calc(20px + var(--sab, env(safe-area-inset-bottom)));
  box-shadow:0 -18px 50px -12px rgba(0,0,0,.6),0 0 0 1px var(--lt-soft);
  transform:translateY(102%);animation:sheetUp .32s var(--sheet-ease) forwards;
  max-height:92vh;overflow-y:auto;position:relative;}
.sheet-back.closing .sheet{animation:sheetDown .2s ease forwards;}
.sheet::before{content:"";display:block;width:38px;height:4px;border-radius:4px;
  background:var(--line);margin:6px auto 12px;}
.sheet h2{margin:2px 0 2px;text-align:center;font-size:20px;}
.sheet .sheet-sub{text-align:center;color:var(--hint);font-size:13.5px;margin:0 0 14px;}
/* Purchase-recovery sheet: honest "how to get ⭐" steps + a p1 down-sell + retry. */
.recov-steps{list-style:none;counter-reset:rs;padding:0;margin:0 0 16px;display:flex;flex-direction:column;gap:9px;}
.recov-steps li{counter-increment:rs;position:relative;padding-left:32px;font-size:13.5px;line-height:1.35;color:var(--text);}
.recov-steps li::before{content:counter(rs);position:absolute;left:0;top:-1px;width:22px;height:22px;border-radius:50%;
  background:var(--bg2);color:var(--lt);font-size:12px;font-weight:800;display:grid;place-items:center;}
.recov-ds{display:flex;flex-direction:column;gap:2px;align-items:center;}
.recov-ds .recov-ds-top{font-size:15px;font-weight:800;}
.recov-ds .recov-ds-sub{font-size:11.5px;font-weight:600;opacity:.85;}
.recov-retry{margin-top:10px;}
/* Крестик закрытия — аккуратный стеклянный кружок, ВИДИМЫЙ на любом фоне. Был
   background:var(--bg2) (тёмный) → на тёмном премиум-шите сливался, оставался голый ✕
   (основатель 2026-08-02). Полупрозрачная заливка + тонкая рамка читаются везде. */
/* Просьба о разрешении писать — свой экран перед нативным окном Telegram (текст того
   окна задаёт Telegram и поменять его нельзя). Никакого blur/filter: только opacity. */
.wa-prompt{text-align:center;padding:6px 4px 2px;}
.wa-prompt .wa-emoji{font-size:40px;line-height:1;margin-bottom:10px;}
.wa-prompt h2{margin:0 0 8px;}
.wa-prompt .hint{margin:0 0 18px;}
.wa-row{display:flex;flex-direction:column;gap:10px;}
.wa-row .btn{width:100%;}
/* КРЕСТИК ВСЕГДА ВЫШЕ СОДЕРЖИМОГО ШИТА. Без z-index он проигрывал любому позиционированному
   блоку, идущему ПОЗЖЕ в DOM: в разборе планеты .seal-hero (position:relative) накрывала
   нижнюю половину кнопки, и закрытие срабатывало только по верхней части и глифу — ровно
   та жалоба, что вчерашний фикс хит-зоны не снял (проверял на обычном шите, где hero нет).
   Замер elementFromPoint по кольцу: низ и левый-нижний угол возвращали 'seal-hero'. */
.sheet-x{position:absolute;top:10px;right:10px;width:36px;height:36px;border-radius:50%;z-index:6;
  border:1px solid rgba(255,255,255,.14); background:rgba(255,255,255,.06);
  color:var(--text);font-size:15px;line-height:1;cursor:pointer;display:grid;place-items:center;
  -webkit-tap-highlight-color:transparent;transition:background .15s ease, transform .08s ease;}
/* ЗАКРЫВАЕТ ВСЯ ПИЛЮЛЯ, А НЕ ТОЛЬКО ГЛИФ. Круглая кнопка 36px кликалась лишь вписанным
   кругом — палец, целясь «в пилюлю», попадал в угол за пределами круга (или чуть мимо
   мелкой цели) и лист не закрывался. Невидимая КВАДРАТНАЯ хит-зона расширяет тап до ~52px
   во все стороны, включая углы: событие с ::before приходит на саму кнопку → dismissSheet.
   Зона в самом углу листа (drag-ручка и контент далеко) — ни на что не наезжает. */
.sheet-x::before{content:"";position:absolute;inset:-8px;}
.sheet-x:active{transform:scale(.9);background:rgba(255,255,255,.13);}
@keyframes sheetBackIn{to{opacity:1}} @keyframes sheetBackOut{to{opacity:0}}
/* sheetDown ОБЯЗАН иметь from{transform:none}: базовый transform у .sheet = translateY(102%),
   открытое состояние держится только fill-ом sheetUp; при смене animation-name на sheetDown
   этот fill сбрасывается, и без from шит мгновенно падает на 102% и «анимирует» 102%→102%
   (телепорт вместо слайда — ночной QA 2026-07). */
@keyframes sheetUp{to{transform:none}} @keyframes sheetDown{from{transform:none}to{transform:translateY(102%)}}

/* B · TOAST — gold reward feedback, drops from the top, auto-dismiss */
.toast-wrap{position:fixed;top:0;left:0;right:0;z-index:80;display:flex;flex-direction:column;
  align-items:center;gap:8px;padding:calc(10px + var(--sat, env(safe-area-inset-top))) 12px 0;pointer-events:none;}
.toast{pointer-events:auto;display:flex;align-items:center;gap:11px;max-width:440px;
  width:max-content;padding:12px 16px 12px 13px;border-radius:16px;
  background:linear-gradient(135deg,#2a2150,var(--card));
  border:1px solid var(--credit-soft);color:var(--text);font-weight:700;font-size:14px;
  box-shadow:0 0 0 1px var(--credit-soft),0 14px 34px -10px rgba(0,0,0,.6),0 0 22px -6px var(--credit-glow);
  animation:toastIn .34s var(--sheet-ease),toastOut .3s ease 3.2s forwards;}
.toast .tt-ic{position:relative;width:38px;height:38px;border-radius:11px;flex:none;display:grid;
  place-items:center;font-size:20px;background:var(--credit-soft);}
.toast .tt-ic::after{content:"";position:absolute;inset:-3px;border-radius:13px;
  box-shadow:0 0 16px var(--credit-glow);animation:al-pulse 2s ease-in-out infinite;}
.toast .tt-amt{font-size:15px;font-weight:900;color:var(--credit);font-variant-numeric:tabular-nums;line-height:1.1;}
.toast .tt-tx{font-size:12.5px;color:var(--hint);margin-top:1px;line-height:1.25;}
.toast .tt-emoji{font-size:19px;flex:none;}
/* M10: settings-save-failed toast — amber warning tint, tap-to-retry, no auto-fade (JS removes it) */
.toast.err{background:linear-gradient(135deg,#3a2340,var(--card));border-color:rgba(255,138,92,.5);cursor:pointer;
  box-shadow:0 0 0 1px rgba(255,138,92,.35),0 14px 34px -10px rgba(0,0,0,.6);
  animation:toastIn .34s var(--sheet-ease);}
.toast.err .tt-ic{background:rgba(255,138,92,.18);}
.toast.err .tt-ic::after{animation:none;box-shadow:none;}
@keyframes toastIn{from{transform:translateY(-130%);opacity:0}to{transform:none;opacity:1}}
@keyframes toastOut{to{transform:translateY(-130%);opacity:0}}

@media (prefers-reduced-motion:reduce){
  .sheet,.sheet-back{animation-duration:.001s}
  .toast{animation:toastIn .2s ease forwards}.toast .tt-ic::after{animation:none}
}

/* ===== 1 · CHECKS COUNTER PILL ===== */
.checks-pill{display:inline-flex;align-items:center;gap:6px;cursor:pointer;
  padding:6px 12px 6px 9px;border-radius:22px;line-height:1;
  background:radial-gradient(120% 140% at 30% 0%,var(--credit-soft) 0%,rgba(15,12,29,0) 70%),rgba(15,12,29,.55);
  border:1px solid var(--credit-soft);-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);
  font-size:14px;font-weight:800;color:var(--text);
  box-shadow:0 1px 0 rgba(255,255,255,.05) inset;
  transition:transform .12s ease,box-shadow .2s ease,border-color .2s ease;}
.checks-pill:active{transform:scale(.94);}
.checks-pill .cp-ico{font-size:15px;filter:drop-shadow(0 0 6px var(--credit-glow));}
.checks-pill .cp-n{font-size:15px;letter-spacing:-.3px;font-variant-numeric:tabular-nums;color:var(--credit);}
.checks-pill .cp-star{font-size:11px;margin-right:-2px;filter:drop-shadow(0 0 5px var(--credit-glow));}
/* iOS: вместо ⭐ (символ Telegram Stars) — золотая астра «Астра» pg--badge, ужатая под пилюлю */
.checks-pill .cp-star .pg--badge{width:16px;height:16px;vertical-align:middle;}
.checks-pill .cp-star .pg--badge svg{width:14px;height:14px;}
/* placements */
.compat-hero .checks-pill{position:absolute;top:13px;right:13px;}
.compat-screen .topbar .checks-pill{padding:5px 11px 5px 8px;font-size:13px;}
/* states */
.checks-pill.low{border-color:rgba(255,209,102,.5);animation:checksLowPulse 2.4s ease-in-out infinite;}
.checks-pill.low .cp-n{color:var(--credit-low);}
.checks-pill.zero{border-color:rgba(255,107,138,.55);background:rgba(255,107,138,.10);}
.checks-pill.zero .cp-ico{filter:none;opacity:.7;}.checks-pill.zero .cp-n{color:var(--credit-zero);}
.checks-pill.premium{border-color:var(--credit);
  box-shadow:0 0 0 1px var(--credit-soft),0 4px 14px -6px var(--credit-glow);}
/* motion */
@keyframes checksLowPulse{0%,100%{box-shadow:0 0 0 0 rgba(255,209,102,0)}50%{box-shadow:0 0 0 4px rgba(255,209,102,.16)}}
.checks-pill.tick .cp-n{animation:checksTick .42s var(--sheet-ease);}
@keyframes checksTick{0%{transform:translateY(-8px) scale(.6);opacity:0}60%{transform:translateY(2px) scale(1.18);opacity:1}100%{transform:none}}
@media (prefers-reduced-motion:reduce){.checks-pill.low{animation:none}.checks-pill.tick .cp-n{animation:none}}

/* ===== 2 · CHECK BUTTON COST ===== */
.compat-screen .btn.check-cta{display:flex;align-items:center;justify-content:center;gap:10px;}
.check-cta .cc-div{width:1px;height:16px;background:rgba(26,16,48,.25);}
.check-cost{display:inline-flex;align-items:center;gap:4px;font-size:13px;font-weight:800;
  padding:3px 9px;border-radius:14px;background:rgba(26,16,48,.18);color:#1a1030;}
.check-cost .cc-ico{font-size:12px;}
.check-cost.free{background:rgba(26,16,48,.14);}
.btn.check-cta.broke .check-cost{background:rgba(255,107,138,.22);color:#5a1020;}

/* ===== 3 · OUT-OF-CREDITS WALL ===== */
.oc-exits{display:flex;flex-direction:column;gap:10px;margin-top:4px;}
.oc-exit{display:flex;align-items:center;gap:13px;width:100%;text-align:left;padding:14px;border-radius:16px;
  border:1px solid rgba(255,255,255,.13);background:#2c2552;cursor:pointer;transition:transform .08s,border-color .15s;}
.oc-exit:active{transform:scale(.985);}
.oc-exit .oc-ic{flex:none;width:44px;height:44px;border-radius:13px;display:grid;place-items:center;
  font-size:22px;background:var(--lt-soft);}
.oc-exit .oc-main{flex:1;min-width:0;}
.oc-exit .oc-t{font-size:15px;font-weight:800;}
.oc-exit .oc-s{font-size:12.5px;color:rgba(242,238,251,.72);margin-top:2px;line-height:1.3;}
.oc-exit .oc-cta{flex:none;font-size:13px;font-weight:800;color:var(--lt);white-space:nowrap;}
/* ① INVITE — filled line gradient + shimmer */
.oc-exit.primary{position:relative;overflow:hidden;border:0;color:#1a1030;padding:16px 14px;
  background:linear-gradient(135deg,var(--lt),var(--lt2));
  box-shadow:0 12px 30px -8px var(--lt-glow),0 2px 0 rgba(255,255,255,.22) inset;}
.oc-exit.primary .oc-ic{background:rgba(26,16,48,.16);}
.oc-exit.primary .oc-s{color:#1a1030;opacity:.82;}.oc-exit.primary .oc-cta{color:#1a1030;}
.oc-exit.primary::after{content:"";position:absolute;top:0;bottom:0;left:-45%;width:40%;
  background:linear-gradient(100deg,rgba(255,255,255,0),rgba(255,255,255,.4) 50%,rgba(255,255,255,0));
  transform:skewX(-18deg);animation:shareShine 5.5s ease-in-out infinite;pointer-events:none;}
/* ② BUY-1 — outlined in line colour */
.oc-exit.buy1{border-color:var(--lt);}
.oc-exit.buy1 .oc-cta{padding:7px 13px;border-radius:13px;background:var(--lt-soft);}
/* premium upsell strip beneath ③ */
.oc-prem{display:flex;align-items:center;gap:10px;margin-top:14px;padding:12px 14px;border-radius:16px;
  border:1px solid var(--credit-soft);
  background:radial-gradient(140% 120% at 0% 0%,var(--credit-soft),rgba(15,12,29,0) 70%),var(--card);cursor:pointer;}
.oc-prem .pm-ico{font-size:20px;filter:drop-shadow(0 0 6px var(--credit-glow));}
.oc-prem .pm-tx{flex:1;font-size:13px;font-weight:700;line-height:1.3;}
.oc-prem .pm-go{flex:none;color:var(--credit);font-weight:800;font-size:18px;}
/* Small, classy, centered gold pill — inline premium upsell at the foot of the
   expanded Focus & Mood breakdown. A quieter, shrink-wrapped sibling of .oc-prem. */
/* красивая премиум-CTA (основатель 2026-07-18): градиент-кайма золото→фиолет как у карточек,
   тёплая «свеча» сверху-справа, стеклянный блик, золотое свечение — не плоский тёмный прямоугольник */
.focus-unlock{
  display:flex;align-items:center;gap:12px;
  width:100%;max-width:100%;margin:14px 0 2px;box-sizing:border-box;
  padding:13px 15px;border-radius:16px;cursor:pointer;
  font-family:inherit;-webkit-appearance:none;appearance:none;text-align:left;
  border:1px solid transparent;
  background:
    radial-gradient(120% 170% at 84% -25%, rgba(244,200,105,.20), rgba(244,200,105,0) 55%) padding-box,
    linear-gradient(180deg, rgba(53,41,88,.92), rgba(33,26,61,.95)) padding-box,
    linear-gradient(122deg, #ffe9b8 0%, #F4C869 42%, #A78BFA 120%) border-box;
  box-shadow:0 0 22px -6px rgba(244,200,105,.42), inset 0 1px 0 rgba(255,246,220,.16);
  transition:transform .12s ease, box-shadow .2s ease;
}
/* астра-иконка ярче именно в этой CTA */
.focus-unlock>.pg{filter:drop-shadow(0 0 7px rgba(244,200,105,.55));}
.focus-unlock .fu-tx{display:flex;flex-direction:column;gap:1px;min-width:0;}
/* text-wrap:balance — если длинный перевод (машинные локали) всё же переносится на 2 строки,
   балансируем их, чтобы одно слово не повисало орфаном (основатель 2026-07-18, «Focus» одиноко). */
.focus-unlock .fu-lbl{font-size:13.5px;font-weight:800;letter-spacing:-.2px;line-height:1.25;color:#fff;
  text-wrap:balance;overflow-wrap:break-word;}
.focus-unlock .fu-sub{font-size:10.5px;font-weight:600;line-height:1.2;color:var(--credit);opacity:.88;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
.focus-unlock .fu-go{flex:none;margin-left:2px;font-size:17px;font-weight:800;line-height:1;color:var(--gold,#ffd98a);}
.focus-unlock:active{transform:scale(.98);}
@media(hover:hover){.focus-unlock:hover{box-shadow:0 0 28px -5px rgba(244,200,105,.5),inset 0 1px 0 rgba(255,246,220,.2);}}
@media (prefers-reduced-motion:reduce){.oc-exit.primary::after{display:none}}

/* ===== «АСТРА» · premium glyph system (.pg) =====================================
   Единый премиум-глиф ✦ (SVG-спрайт #pg-star) вместо эмодзи-замков. Свечение — ТОЛЬКО
   статичный ::before radial-gradient; filter/drop-shadow ЗАПРЕЩЕНЫ (перф бюджетных
   Android) — в ревью проверять, что никто не «улучшил» на filter.
   ЗАКОН СИНХРОННОСТИ: stagger/волны/random-delay ЗАПРЕЩЕНЫ — все глифы экрана дышат
   синхронно, animation-delay:0 у всех .pg без исключений («волна» при ре-рендере
   таба выглядит как баг-гирлянда). */
.pg{display:inline-block;line-height:1;position:relative;
  animation:pg-breathe 3.2s ease-in-out 24;} /* 24 цикла (~77s) → стоп на 0%-кадре = полная яркость */
.pg::before{content:"";position:absolute;inset:-35%;z-index:-1;border-radius:50%;pointer-events:none;
  background:radial-gradient(circle,rgba(244,200,105,.25),transparent 60%);} /* статичный glow, НЕ анимируется */
.pg svg{width:100%;height:100%;display:block;}
/* (1) badge — БЕЗ КОЛЬЦА (основатель 2026-07-18, финально: тёмный кружок вокруг астры читался
   «тускло и не по центру», сколько его ни ярчи; убрали совсем). Теперь это просто крупная
   яркая светящаяся астра, как инлайн-звёздочки, которые нравятся. Свечение — static ::before. */
.pg--badge{width:26px;height:26px;flex:none;
  display:inline-flex;align-items:center;justify-content:center;}
.pg--badge svg{width:20px;height:20px;}
.pg--badge::before{inset:-20%;background:radial-gradient(circle,rgba(244,200,105,.45),transparent 60%);}
.pct-lock .pg--badge{width:22px;height:22px;} /* слот процента Focus&Mood */
.pct-lock .pg--badge svg{width:17px;height:17px;}
/* (2) inline 14px — после точек ••••, в compat-тизерах, микростроке превью-шита; без кольца */
.pg--inline{width:14px;height:14px;vertical-align:-0.12em;}
/* (3) ribbon 18px — префикс золотых лент/пилюль (.f14-unlock, .focus-unlock, .pack-prem, My-Checks) */
.pg--ribbon{width:18px;height:18px;flex:none;}
/* (4) corner 16px — угол карточки будущей главы .tf-cell.locked, перк acc-prem */
.pg--corner{width:16px;height:16px;}
/* (5) капсула-якорь «✦ PREMIUM» — слово латиницей во ВСЕХ локалях, не переводится */
.prem-tag{display:inline-flex;align-items:center;gap:4px;height:18px;padding:2px 7px;
  border-radius:9px;border:1px solid rgba(244,200,105,.35);background:rgba(244,200,105,.13);
  font-size:10px;font-weight:700;letter-spacing:.06em;line-height:1;color:#ffd98a;white-space:nowrap;
  text-transform:uppercase;} /* спек sizes(5): капсула показывает «PREMIUM»; i18n-ключ остаётся «Premium» */
.pg--tag{width:10px;height:10px;}
/* тёмная подложка-чип для цветных поверхностей (розовый hero Лилит, violet-апселлы) — WCAG 1.4.11 */
/* мягкий тёмный ОРЕОЛ (не жёсткий диск-кольцо) под астрой на светлом фоне — розовый hero Лилит:
   голое золото на розовом < 3:1 (WCAG 1.4.11); радиал-фон span'а даёт контраст без резкого круга,
   SVG-астра — дочерний элемент, рисуется поверх этого фона */
.pg--dark{background:radial-gradient(circle,rgba(12,9,26,.82) 40%,rgba(12,9,26,0) 72%);}
/* «дыхание, не мигание»: opacity никогда к нулю; 3.2s ≈ 0.31 Гц — в 10 раз ниже порога WCAG 2.3.1 */
@keyframes pg-breathe{0%,100%{opacity:1;transform:scale(1)}50%{opacity:.72;transform:scale(.96)}}
/* тап-вспышка: параллельно paywall(ctx), не блокирует переход; та же вспышка на печати пейвола */
.pg-burst,.pg.pg-burst{animation:pg-burst .24s ease-out;}
@keyframes pg-burst{0%{transform:scale(1) rotate(0deg)}50%{transform:scale(1.3) rotate(30deg)}100%{transform:scale(1) rotate(0deg)}}
/* фокус-кольцо интерактивных залоченных рядов (role="button" tabindex="0" ставит JS, класс .pg-row) */
.pg-row:focus-visible{outline:2px solid #F4C869;outline-offset:2px;}
/* reduced-motion: деградация К ПОЛНОЙ ЯРКОСТИ (иначе locked неотличим от disabled) */
@media (prefers-reduced-motion:reduce){.pg{animation:none;opacity:1}.pg-burst,.pg.pg-burst{animation:none}}

/* ===== 4 · PACKS ===== */
/* 3 vertical columns, lighter cards (the old stacked rows looked dark + the big
   number collided with the title). */
.pack-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:9px;margin:10px 0 14px;}
.pack{position:relative;display:flex;flex-direction:column;align-items:center;justify-content:flex-start;
  gap:3px;padding:18px 6px 14px;border-radius:16px;cursor:pointer;text-align:center;
  border:1.5px solid rgba(255,255,255,.10);background:#2c2552;
  transition:transform .1s,border-color .15s,background .15s,box-shadow .15s;}
.pack:active{transform:scale(.97);}
.pack.sel{border-color:var(--lt);background:var(--lt-soft);
  box-shadow:0 0 0 1px var(--lt),0 10px 26px -10px var(--lt-glow);}
.pack .pk-n{font-size:30px;font-weight:900;line-height:1;color:var(--credit);}
.pack .pk-u{font-size:10.5px;color:var(--hint);text-transform:uppercase;letter-spacing:.4px;}
.pack .pk-price{margin-top:7px;font-size:15px;font-weight:800;color:var(--text);white-space:nowrap;}
.pack .pk-tag{position:absolute;top:-9px;left:50%;transform:translateX(-50%);white-space:nowrap;
  font-size:9px;font-weight:800;text-transform:uppercase;letter-spacing:.3px;padding:3px 8px;border-radius:9px;
  color:#1a1030;background:linear-gradient(135deg,var(--lt),var(--lt2));}
.pack-prem{margin-top:12px;display:flex;align-items:center;gap:12px;padding:13px 14px;border-radius:16px;
  border:1px solid rgba(255,209,102,.4);cursor:pointer;
  background:linear-gradient(135deg,rgba(255,209,102,.14),var(--card));}
/* .pp-ic (эмодзи ⭐) удалён вместе с разметкой — префикс футера теперь астра premGlyph('ribbon');
   ⭐ остаётся ТОЛЬКО в ценах .pk-price (валюта XTR). */
.pack-prem>.pg{flex:none;}.pack-prem .pp-main{flex:1;}
.pack-prem .pp-t{font-size:14.5px;font-weight:800;}.pack-prem .pp-s{font-size:12px;color:var(--hint);}
.pack-prem .pp-cta{font-size:13px;font-weight:800;color:var(--warn);}

/* ===== 5 · INVITE SCREEN ===== */
.inv-hero{text-align:center;padding:6px 0 2px;}
.inv-hero .ih-glyph{font-size:46px;filter:drop-shadow(0 0 14px var(--lt-glow));}
.inv-hero h1{margin:8px 0 4px;}
.inv-earned{display:flex;align-items:center;justify-content:center;gap:12px;margin:14px 0;padding:16px;
  border-radius:18px;border:1px solid var(--credit-soft);
  background:radial-gradient(140% 120% at 0% 0%,var(--credit-soft),rgba(15,12,29,0) 65%),var(--card);}
.inv-earned .ie-n{font-size:30px;font-weight:900;color:var(--credit);
  filter:drop-shadow(0 0 8px var(--credit-glow));font-variant-numeric:tabular-nums;}
.inv-earned .ie-l{font-size:13px;color:var(--text);text-align:left;line-height:1.25;max-width:180px;}
.inv-steps{display:flex;flex-direction:column;gap:10px;margin:16px 0;}
.inv-step{display:flex;align-items:center;gap:12px;font-size:14px;}
.inv-step .is-ic{flex:none;width:34px;height:34px;border-radius:10px;display:grid;place-items:center;
  background:var(--lt-soft);font-size:17px;}
.inv-share{margin-top:8px;}
/* invite CTA reads UNMISTAKABLY as a button: verb-first stacked label, leading
   send icon, trailing arrow, and a gentle breathing glow that draws the eye.
   Scoped to .inv-share so the compat-result share button is untouched. */
.compat-screen .btn.share-cta.inv-share .sc-tx{
  display:flex;flex-direction:column;align-items:flex-start;text-align:left;gap:1px;line-height:1.12;}
.compat-screen .btn.share-cta.inv-share .sc-tx b{font-size:17px;font-weight:900;letter-spacing:-.2px;}
.compat-screen .btn.share-cta.inv-share .sc-tx i{font-style:normal;font-size:13px;font-weight:700;opacity:.82;}
.compat-screen .btn.share-cta.inv-share .sc-go{font-size:23px;font-weight:900;line-height:1;transition:transform .15s ease;}
.compat-screen .btn.share-cta.inv-share:active .sc-go{transform:translateX(4px);}
@keyframes invPulse{
  0%,100%{box-shadow:0 0 0 1px var(--lt-soft),0 12px 30px -6px var(--lt-glow),0 2px 0 rgba(255,255,255,.22) inset;}
  50%{box-shadow:0 0 0 1px var(--lt-soft),0 16px 40px -4px var(--lt-glow),0 0 24px 2px var(--lt-glow),0 2px 0 rgba(255,255,255,.22) inset;}}
.compat-screen .btn.share-cta.inv-share{animation:invPulse 2.4s ease-in-out infinite;}
.compat-screen .share-sub.inv-tap{color:var(--lt);opacity:1;font-weight:800;}
@media (prefers-reduced-motion: reduce){.compat-screen .btn.share-cta.inv-share{animation:none;}}
/* the unmissable gold gift banner — recipient's reward, directly under the hero */
/* flat INFO panel (not elevated) so the CTA button is the clear action */
.inv-gift{display:flex;align-items:center;gap:12px;margin:12px 0;padding:13px 16px;border-radius:14px;
  border:1px solid var(--credit-soft);
  background:radial-gradient(150% 130% at 100% 0%,var(--credit-soft),rgba(15,12,29,0) 62%),var(--card);}
.inv-gift .ig-n{flex:none;font-size:22px;font-weight:900;color:var(--credit);
  filter:drop-shadow(0 0 8px var(--credit-glow));font-variant-numeric:tabular-nums;white-space:nowrap;}
.inv-gift .ig-l{font-size:13.5px;font-weight:700;color:var(--text);line-height:1.3;}
/* tappable preview of the exact card the friend receives */
.inv-card-prev{position:relative;display:block;margin:14px 0;border-radius:16px;overflow:hidden;
  border:1px solid var(--lt-soft);box-shadow:0 8px 24px -10px var(--lt-glow);cursor:pointer;
  transition:transform .12s ease;}
.inv-card-prev:active{transform:scale(.99);}
.inv-card-prev img{display:block;width:100%;height:auto;}
.inv-card-prev .icp-hint{position:absolute;left:0;right:0;bottom:0;padding:10px 12px;
  font-size:12.5px;font-weight:800;color:#fff;text-align:center;
  background:linear-gradient(to top,rgba(15,12,29,.86) 30%,rgba(15,12,29,0));}

/* ===== 6 · REFERRED WELCOME ===== */
.welcome-gift{text-align:center;margin-top:7vh;}
.welcome-gift .wg-box{font-size:60px;filter:drop-shadow(0 0 18px var(--lt-glow));animation:al-pulse 2.6s ease-in-out infinite;}
.welcome-gift .wg-checks{display:inline-flex;align-items:center;gap:8px;margin:16px 0 6px;padding:8px 18px;
  border-radius:24px;background:var(--credit-soft);border:1px solid var(--credit);
  font-size:26px;font-weight:900;color:var(--credit);filter:drop-shadow(0 0 8px var(--credit-glow));}
.welcome-gift h1{margin:6px 14px 4px;}
.welcome-gift h1 b{color:var(--credit);}
@media (prefers-reduced-motion:reduce){.welcome-gift .wg-box{animation:none}}

/* ===== 7 · MY CHECKS SHEET ===== */
.mc-bal{text-align:center;margin:4px 0 4px;}
.mc-bal .mb-n{font-size:48px;font-weight:900;line-height:1;color:var(--credit);
  display:inline-flex;align-items:center;gap:8px;font-variant-numeric:tabular-nums;
  filter:drop-shadow(0 0 12px var(--credit-glow));}
.mc-bal .mb-l{font-size:13px;color:var(--hint);margin-top:4px;}
.mc-ways{display:flex;flex-direction:column;gap:9px;margin-top:14px;}
.mc-way{display:flex;align-items:center;gap:12px;padding:13px 14px;border-radius:14px;
  background:var(--bg2);border:1px solid var(--line);cursor:pointer;}
.mc-way .mw-ic{width:38px;height:38px;border-radius:12px;display:grid;place-items:center;
  font-size:19px;background:var(--lt-soft);flex:none;}
/* Premium-ряд My-Checks: тайл несёт астру (premGlyph ribbon) на золотой подложке вместо violet —
   эмодзи ⭐ здесь читалась как «стоит звёзд»; ⭐ остаётся только в ценах (XTR). Тайл сохранён,
   чтобы иконки рядов (🎁/✨/астра) держали одну колонку. */
.mc-way .mw-ic.prem{background:rgba(244,200,105,.13);border:1px solid rgba(244,200,105,.35);}
.mc-way .mw-t{flex:1;font-size:14.5px;font-weight:700;}
.mc-way .mw-sub{font-size:12px;color:var(--hint);}
.mc-way .mw-go{color:var(--hint);font-size:18px;}
.mc-daily{text-align:center;font-size:12.5px;color:var(--credit-low);font-weight:700;margin-top:12px;}
.mc-daily.prem{color:var(--credit);}

/* ===== 9 · PREMIUM PERKS ===== */
/* DEPRECATED (paywall v2, 2026-07): .prem-perks/.prem-perk/.pp-ic жили ТОЛЬКО в renderPaywall
   (проверено grep: account-карточка использует .ap-perk) — v2 заменяет блок на .pw2-feats
   «Что ещё внутри». Правила оставлены до вычистки разметки (build note 1: классы не удаляем). */
.prem-perks{display:flex;flex-direction:column;gap:11px;margin:14px 0 18px;}
.prem-perk{display:flex;align-items:center;gap:12px;font-size:14.5px;color:var(--text);}
.prem-perk .pp-ic{flex:none;width:30px;height:30px;border-radius:9px;display:grid;place-items:center;
  background:var(--credit-soft);color:var(--credit);font-size:16px;}
/* Account premium upsell — gold, glowing, perk-rich, sales-y (sits high in the tab). */
.acc-prem{position:relative;overflow:hidden;border-radius:20px;padding:18px 16px 16px;margin:14px 0 6px;cursor:pointer;
  border:1px solid rgba(255,209,102,.45);
  background:linear-gradient(150deg,rgba(255,209,102,.22),rgba(255,170,90,.07) 42%,var(--card) 80%);
  box-shadow:0 14px 34px -14px rgba(255,180,80,.45),0 1px 0 rgba(255,255,255,.10) inset;transition:transform .1s;}
.acc-prem:active{transform:scale(.99);}
/* filter:blur(6px) снят (2026-08-03): это буквальный filter из запретного списка, каждый
   такой слой = отдельный проход растеризации на дешёвом Android. Свечение и так радиальный
   градиент — размытие имитируется промежуточным стопом, разница на глаз нулевая. */
.acc-prem .ap-glow{position:absolute;top:-60px;right:-40px;width:180px;height:180px;pointer-events:none;
  background:radial-gradient(circle,rgba(255,209,102,.40) 0%,rgba(255,209,102,.22) 40%,rgba(255,209,102,.07) 56%,transparent 72%);}
.acc-prem .ap-head{position:relative;display:flex;align-items:center;gap:12px;}
/* Шапка acc-prem: большая астра-«печать» 40px (premGlyph('seal')) вместо эмодзи ⭐ —
   пятилучевая путалась с валютой Stars; печать замыкает бренд-петлю с печатью пейвола.
   Glow — статичный ::before (НЕ filter/drop-shadow: перф на бюджетных Android);
   специфичность .pg.pg--seal::before выше базового .pg::before — свечения не двоятся. */
.pg.pg--seal{position:relative;width:40px;height:40px;flex:none;}
.pg.pg--seal svg{display:block;width:40px;height:40px;}
.pg.pg--seal::before{content:"";position:absolute;top:-26%;left:-26%;right:-26%;bottom:-26%;
  border-radius:50%;pointer-events:none;
  background:radial-gradient(circle,rgba(244,200,105,.30),transparent 62%);}
/* Активная карта подписчика: печать — статус, не приглашение → не дышит
   (движение = эксклюзивный маркер премиум-инвайта; и «premium-паспорт»-QA чист по анимации). */
.acc-prem.active .pg{animation:none;}
.acc-prem .ap-ttl{flex:1;min-width:0;}
.acc-prem .ap-ttl h3{font-size:18px;font-weight:900;letter-spacing:.2px;}
.acc-prem .ap-ttl p{font-size:13px;color:rgba(242,238,251,.82);margin-top:2px;line-height:1.3;}
.acc-prem .ap-on{flex:none;width:30px;height:30px;border-radius:50%;display:grid;place-items:center;font-weight:900;
  color:#1a1030;background:linear-gradient(135deg,var(--credit),#ffb84d);}
.acc-prem .ap-perks{position:relative;display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px 10px;margin:14px 0 15px;}
.acc-prem .ap-perk{display:flex;align-items:center;gap:7px;font-size:12.5px;font-weight:600;color:var(--text);}
/* <i> перка держит и эмодзи, и астру (perk feat_depth = premGlyph('corner')):
   inline-flex центрирует svg без baseline-зазора. */
.acc-prem .ap-perk i{font-style:normal;font-size:14px;flex:none;display:inline-flex;align-items:center;}
.acc-prem .ap-cta{position:relative;width:100%;border:0;border-radius:14px;padding:13px;cursor:pointer;
  font-size:15px;font-weight:900;letter-spacing:.2px;color:#1a1030;
  background:linear-gradient(135deg,var(--credit),#ffb84d);box-shadow:0 8px 22px -8px rgba(255,180,80,.7);}
.acc-prem.active{cursor:pointer;}
/* ===== PREMIUM AVATAR GLOW — gold halo ONLY around the self avatar circle.
   Tight + intense (not far-reaching) so the peopleBar scroll box doesn't clip it
   into a square; .people-bar gets matching padding for headroom. */
.prem-ring{border-color:var(--credit) !important;
  box-shadow:0 0 8px 0 rgba(255,217,138,.9), 0 0 3px 0 rgba(255,217,138,.95) !important;}
/* Account invite card — pretty but calm (the gold premium card is the loud one). */
.acc-invite{position:relative;overflow:hidden;border-radius:20px;padding:16px;margin:14px 0 6px;
  border:1px solid rgba(167,139,250,.30);
  background:radial-gradient(130% 120% at 100% 0%,rgba(167,139,250,.18),rgba(236,124,193,.06) 45%,var(--card) 78%);}
.acc-invite .ai-head{display:flex;align-items:center;gap:13px;margin-bottom:13px;}
.acc-invite .ai-ic{flex:none;width:46px;height:46px;border-radius:14px;display:grid;place-items:center;font-size:24px;
  background:rgba(167,139,250,.16);filter:drop-shadow(0 0 8px rgba(167,139,250,.40));}
.acc-invite .ai-tx{flex:1;min-width:0;}
.acc-invite .ai-tx h3{font-size:16.5px;font-weight:800;}
.acc-invite .ai-tx p{font-size:13px;color:rgba(242,238,251,.78);margin-top:2px;line-height:1.3;}
.acc-invite .ai-cta{width:100%;border:0;border-radius:14px;padding:13px;cursor:pointer;
  display:flex;align-items:center;justify-content:center;gap:8px;font-size:15px;font-weight:800;color:#1a1030;
  background:linear-gradient(135deg,var(--lt),var(--lt2));
  box-shadow:0 8px 22px -10px var(--lt-glow),0 1px 0 rgba(255,255,255,.22) inset;transition:transform .1s;}
.acc-invite .ai-cta:active{transform:scale(.99);}
/* Append-only profile editor (others): locked birth-data shown read-only. */
.ro-val{padding:11px 13px;border-radius:12px;font-size:15px;color:var(--text);
  background:rgba(255,255,255,.04);border:1px solid rgba(255,255,255,.08);}
/* a locked birth field that opens the one-time correction on tap (founder 2026-07-03) */
.ro-val.ro-tap{display:flex;align-items:center;justify-content:space-between;gap:10px;cursor:pointer;
  border-color:rgba(179,136,255,.28);}
/* R1-MIN-3: an unbreakable 58-char toponym (Llanfairpwllgwyngyll… — a REAL gazetteer row) refused to
   shrink and pushed «✎ Исправить ›» clean off the right edge, i.e. hid the ONLY entry into the date
   correction. A flex item won't shrink below its content without min-width:0, and a single long word
   needs an explicit break opportunity. */
.ro-val.ro-tap > span:first-child{min-width:0;flex:1 1 auto;overflow-wrap:anywhere;word-break:break-word;}
.ro-val.ro-tap:active{background:rgba(179,136,255,.10);}
.ro-cue{color:var(--accent);font-size:13px;font-weight:600;white-space:nowrap;flex:0 0 auto;}
.lock-note{display:flex;gap:6px;align-items:flex-start;margin:6px 2px 12px;
  color:var(--hint);font-size:12.5px;line-height:1.35;}
/* ============================================================================
   PAYWALL v2 «Это уже твоё — осталось открыть» — вертикальные СТРОКИ-РАДИО
   вместо колонок (paywall_spec.json · пакет pw3-css-plans). Классы plan-grid /
   plan-card ЖИВУТ: гварды 410-флоу и Promo-resync (app.js) ищут .plan-grid в
   DOM, клик-каталог аналитики знает .plan-card. Контракт разметки (ФАКТИЧЕСКИЙ pw2,
   сведён CTO 2026-07-17 — имена ниже соответствуют renderPaywall):
     <div class="pw2[ pw2-cascade]">                   ← корень экрана
       <h1 class="pw2-h1">✦ …</h1><p class="pw2-sub">…</p>   ← .pw2-sub = САБХЕД экрана
       <div class="pw2-wm" aria-hidden="true"></div>   ← watermark-печать (пустой)
       <div class="plan-grid pw2-plans[ pw2-promo]">   ← pw2-promo при _promoActive()
         [<div class="pw-promo-strip">−60% · … <span id="pw-promo-timer"/></div>]
         <div class="plan-card pw-row[ pw-week][ sel][ pw-breathe(3m)]" role="button">
           [<span class="pw-badge">ОПТИМУМ</span>]     ← бейдж ТОЛЬКО у героя 3m
           <span class="pw-radio"></span>
           <span class="pw-row-main"><b class="pl-name">12 месяцев</b>
             [<span class="pw-chip[ pw-chip-save]">−44% к помесячной</span>]
             [<span class="pw-chip-note">дешевле всего за месяц</span>]</span>
           <span class="pw-row-price">
             [<span class="pw-unit">≈ 33 ⭐/мес</span>] ← юнит-цена; у недели НЕ рендерится
             <span class="pw-bill[ pw-bill-week]">400 ⭐ · <s class="pl-old">1000</s> · ≈ 45 ₽/мес</span>
           </span>
         </div>…
       </div>
       <button class="btn pw-cta">…</button> + .pw-under-cta / .pw-trust / details.pw-stars-how
       <div class="pw-feats"><p class="pw-feats-title">Что ещё внутри</p>
         <div class="pw-feat[ hot]"><span class="pw-feat-orb">(svg)</span><span class="pw-feat-txt">…</span></div>…</div>
     </div>
   BUILD NOTE 10 (закон): text-overflow:ellipsis ЗАПРЕЩЁН по всей money-цепочке —
   цена/процент/якорь/бейдж при OS font-scale и длинных валютах (VND/IDR)
   ПЕРЕНОСЯТСЯ, строка растёт вниз (min-height, не height) — урок промо-капсулы. */
.plan-grid{position:relative;z-index:1;display:flex;flex-direction:column;gap:8px;margin:6px 0 14px;
  /* overflow:visible — бейдж героя (top:-9px) и промо-язычок (top:-13px) не резать */
  overflow:visible;}
/* при АКТИВНОМ промо (класс ставит разметка pw2): «рамка, которая горит» вокруг лестницы —
   язычок-пилюля «−60% · сгорит через MM:SS» (.pw-promo-timer/.pw-promo-strip, стили у pw4/pw5)
   вплавлен в верхний край top:-13px: margin-top даёт ему воздух, верхний паддинг — отступ строкам;
   гаснет тем же 410-ре-рендером, что убирает язычок и .pl-old (владелец — _promo410Flow) */
.plan-grid.pw2-promo-live{margin-top:13px;padding:16px 8px 8px;border-radius:18px;
  border:1px solid rgba(255,92,138,.22);background:rgba(255,92,138,.04);}
/* строка-радио: вся строка = tap-зона, radio слева, юнит-цена справа */
.plan-card{position:relative;display:flex;align-items:center;gap:8px;min-height:64px;
  padding:13px 14px;border-radius:16px;cursor:pointer;text-align:left;
  border:1.5px solid rgba(255,255,255,.13);background:var(--pw-card-dim);
  -webkit-text-size-adjust:100%;text-size-adjust:100%;   /* урок капсулы: iOS-инфляция текста — первоисточник обрезаний */
  transition:transform .1s,border-color .16s,background .16s,box-shadow .16s;}
.plan-card:active{transform:scale(.97);}
/* выбранная: контур ЧИСТО золотой (градиентный контур gold→magenta ЗАПРЕЩЁН спеком) + halo */
.plan-card.sel{border:1.5px solid var(--pw-gold);background:var(--pw-card);
  box-shadow:0 0 22px -6px var(--pw-glow);}
/* radio-кружок — чистый CSS, без <input> (строка сама role=radio) */
.pw-radio{flex:none;width:20px;height:20px;border-radius:50%;position:relative;
  border:1.5px solid rgba(255,255,255,.3);transition:border-color .16s;}
.plan-card.sel .pw-radio{border-color:var(--pw-gold);}
.plan-card.sel .pw-radio::after{content:"";position:absolute;inset:3.5px;border-radius:50%;
  background:var(--pw-gold);}
/* левая колонка (одна flex-wrap строка: имя + чип; note уходит второй строкой basis:100%);
   min-width:0 разрешает переносы имени */
.pw-row-main{flex:1;min-width:0;display:flex;flex-wrap:wrap;align-items:center;gap:4px 6px;}
.plan-card .pl-name{font-size:15px;font-weight:600;line-height:1.2;
  /* QA device-matrix: длинное слово («Попробовать», «месяц») при OS font-scale шире
     колонки — БЕЗ переносов оно вытекало поверх money-строки правой колонки (билл-цена
     нечитаема). break-word (не anywhere!): перенос по границам слов, разрыв внутри слова —
     только когда слово одно не влезает (anywhere резал «Попробов/ать» на обычной 393px) */
  min-width:0;overflow-wrap:break-word;word-break:break-word;}
/* правая колонка: юнит-цена сверху, billed-строка под ней; НЕ сжимается (сжимается имя),
   но capped max-width — длинные валюты переносятся ВНУТРИ колонки, карточка растёт вниз */
.pw-row-price{flex:none;max-width:62%;display:flex;flex-direction:column;align-items:flex-end;
  gap:2px;text-align:right;}
/* юнит-цена «≈ 33 ⭐/мес» — 20/800 золото, НЕ ellipsis */
.pw-unit{font-size:20px;font-weight:800;color:var(--pw-gold);
  white-space:normal;text-align:right;line-height:1.1;font-variant-numeric:tabular-nums;
  overflow:visible;text-overflow:clip;}
/* строка 2: «400 ⭐ · было 1000 · ≈ 45 ₽/мес» — переносится, карточка растёт;
   overflow-wrap:anywhere — фиат-якорь VND/IDR рвётся внутри токена, ellipsis запрещён */
.pw-bill{font-size:12px;font-weight:600;color:rgba(255,255,255,.55);line-height:1.3;
  white-space:normal;overflow:visible;text-overflow:clip;overflow-wrap:anywhere;}
/* у недели billed-строка = единственная строка цены (кофе-якорь) — кеглем чуть крупнее */
.pw-bill-week{font-size:13px;}
/* зачёркнутая старая цена ВНУТРИ строки 2: правило владеет пакет pw5 — bare .pl-old
   (inline, кегль inherit, nowrap-токен без overflow:hidden) в промо-секции ниже по файлу */
/* .brl-hint здесь = выход starsPriceHint (у недели), приведён к инлайну строки 2 */
.plan-card .pw-bill .brl-hint{display:inline;margin:0;font-size:inherit;
  font-weight:600;color:inherit;white-space:normal;letter-spacing:0;overflow-wrap:anywhere;}
/* чип выгоды (ровно одна цифра на строку): база «−44% к помесячной» — мягкое золото.
   QA device-matrix: nowrap при font-scale ×2 выталкивал ⭐ из пилюли на юнит-цену —
   white-space:normal+anywhere: в норме однострочен (min-content = слово), в тесноте
   пилюля переносится и растёт вниз (закон BUILD NOTE 10 — переносим, не клипуем) */
.pw-chip{display:inline-block;flex:none;max-width:100%;padding:2.5px 7px;border-radius:8px;
  font-size:10.5px;font-weight:800;letter-spacing:.2px;line-height:1.2;
  white-space:normal;overflow-wrap:anywhere;
  background:rgba(255,217,138,.12);color:var(--pw-gold-hi);overflow:visible;text-overflow:clip;}
/* промо-чип «экономия 600 ⭐»: magenta = ТОЛЬКО время/дефицит — живёт и умирает с таймером */
.pw-chip-save{background:rgba(255,92,138,.14);color:var(--pw-magenta);}
/* бесцифровая подпись 12m «дешевле всего за месяц» — своя строка под именем */
.pw-chip-note{flex-basis:100%;font-size:11px;font-weight:600;color:rgba(255,255,255,.45);
  line-height:1.2;}
/* бейдж героя «ОПТИМУМ» — печать: золотая заливка --pw-seal, тёмные чернила, top:-9px */
.plan-card .pw-badge{position:absolute;top:-9px;left:14px;transform:none;white-space:nowrap;
  font-size:10px;font-weight:800;text-transform:uppercase;letter-spacing:.4px;
  padding:3px 9px;border-radius:9px;color:var(--pw-ink-on-gold);background:var(--pw-seal);
  box-shadow:0 2px 8px rgba(0,0,0,.35);overflow:visible;text-overflow:clip;}
/* DEPRECATED (paywall v2): teal-бейдж «TRY IT» умер по спеку — правило оставлено только
   под кэшированную старую разметку, новая неделя рендерится без бейджа */
.plan-card .pk-tag-featured{color:#04241f;background:linear-gradient(135deg,#7ef0d4,#37c7a6);}
/* неделя-«вход» (кофе-якорь в .pw2-sub): пунктирная violet-рамка, без юнит-цены и бейджа;
   .featured — легаси-алиас той же строки (старый weekly-арм ставит p.featured) */
.plan-card.pw-week, .plan-card.featured{border:1px dashed rgba(167,139,250,.4);
  background:var(--pw-card-dim);}
.plan-card.pw-week.sel, .plan-card.featured.sel{border:1.5px solid var(--pw-gold);
  background:var(--pw-card);box-shadow:0 0 22px -6px var(--pw-glow);}
/* --- шапка пейвола: H1 24/800 золотым градиентом печати, сабхед violet-телом --- */
.pw2-h1{margin:0 0 6px;font-size:calc(24px * var(--font-scale));font-weight:800;letter-spacing:-.4px;line-height:1.15;
  background:var(--pw-seal);-webkit-background-clip:text;background-clip:text;
  color:var(--pw-gold-hi);   /* фоллбэк без clip:text */
  -webkit-text-fill-color:transparent;}
/* сабхед: не серый шёпот, а живая строка (основатель 2026-07-17: «серый текст скучно») —
   яркий лавандово-кремовый + плотнее вес; конкурировать с золотым H1 не должен */
.pw2-sub{margin:0 0 12px;font-size:calc(14.5px * var(--font-scale));font-weight:550;line-height:1.42;color:#E9E2FA;}

/* Блок ценности над планами — РЕДАКЦИОННЫЙ манифест, не контрол (основатель 2026-07-17,
   итерация 2: карточка с градиентной каймой читалась «ещё одной кнопкой» — та же грамматика
   rounded box + border, что у plan-card). Контейнера НЕТ: 2×2 пункта стоят на фоне экрана
   как продолжение H1; от зоны коммерции отделяет открытая hairline-линейка (::after —
   position:absolute, из грид-потока исключён и грид-ячейкой не становится). */
/* Founder 2026-07-22: одноколоночный список тап-аккордеонов (был 2×2 грид) — по тапу
   подробная выгода раскрывается ПРЯМО ЗДЕСЬ (feat_long), без ухода в отдельное окно. */
.pw-vals{position:relative;display:flex;flex-direction:column;gap:0;
  margin:4px 0 14px;padding:2px 2px 12px;}
.pw-vals::after{content:"";position:absolute;left:6%;right:6%;bottom:0;height:1px;
  pointer-events:none;
  background:linear-gradient(90deg,transparent,rgba(197,168,255,.28) 18%,
    rgba(255,217,138,.22) 50%,rgba(197,168,255,.28) 82%,transparent);}
.pw-val{display:block;width:100%;text-align:left;background:none;border:0;cursor:pointer;
  font-family:inherit;color:#E9E2FA;padding:9px 4px;-webkit-tap-highlight-color:transparent;
  border-top:1px solid rgba(197,168,255,.08);}
.pw-val:first-child{border-top:0;}
.pw-val-head{display:flex;align-items:center;gap:9px;min-height:30px;min-width:0;
  font-size:13px;font-weight:600;line-height:1.22;}
/* двухчастные лейблы (Совместимость/Личность): перенос строки, не точка — \n через pre-line */
.pw-val-lbl{flex:1 1 auto;min-width:0;white-space:pre-line;}
.pw-val-chev{flex:none;color:var(--pw-gold);font-size:16px;opacity:.6;
  transition:transform .22s ease, opacity .2s ease;}
.pw-val[aria-expanded="true"] .pw-val-chev{transform:rotate(90deg);opacity:1;}
/* раскрываемое подробное описание — max-height/opacity переход, свёрнуто по умолчанию */
.pw-val-desc{display:block;overflow:hidden;max-height:0;opacity:0;padding-left:33px;
  font-size:12.5px;font-weight:400;line-height:1.42;color:#c8bce8;
  transition:max-height .3s ease, opacity .22s ease, margin-top .3s ease;}
.pw-val[aria-expanded="true"] .pw-val-desc{max-height:220px;opacity:.95;margin-top:5px;}
.pw-val:active .pw-val-head{opacity:.82;}
.pw-val.hot .pw-val-head{color:var(--pw-gold-hi);font-weight:700;}
.pw-val.hot .pw-val-ico{filter:drop-shadow(0 0 8px rgba(255,217,138,.55));}
@media (prefers-reduced-motion:reduce){ .pw-val-desc,.pw-val-chev{transition:none;} }
@media (max-width:359px){ .pw-val-head{font-size:11.5px;} .pw-val-desc{font-size:11.5px;} }
/* --- фон экрана + watermark-печать на корне .pw2-screen (нижние паддинги корня под
   sticky-CTA — у pw4, секция PAYWALL v2 ниже по файлу). z-index:0 создаёт stacking
   context: слои с z-index:-1 лежат НАД фоном страницы, но ПОД всем контентом экрана;
   строки планов непрозрачны (--pw-card-dim) — текст цен никогда не на водяном знаке */
.pw2, .pw2-screen{position:relative;z-index:0;}
.pw2::before, .pw2-screen::before{content:"";position:absolute;top:-16px;left:-16px;right:-16px;height:60vh;
  z-index:-1;pointer-events:none;
  background:radial-gradient(120% 60% at 50% -10%, rgba(179,136,255,.14), transparent 60%);}
/* watermark-печать — геометрия tfx-sealface (twin_fx.css): внешний контур, пунктирное кольцо
   inset 7%, риски repeating-conic; глиф — <svg class="pw2-wm-star"><use href="#pg-star"/></svg>
   ВНУТРИ <div class="pw2-wm" aria-hidden="true"> непосредственно ПЕРЕД .plan-grid. */
.pw2-wm{position:absolute;z-index:-1;top:150px;left:50%;width:300px;height:300px;
  margin-left:-150px;border-radius:50%;border:2px solid var(--pw-gold-hi);
  opacity:.06;pointer-events:none;}
.pw2-wm::before{content:"";position:absolute;inset:7%;border-radius:50%;
  border:1px dashed var(--pw-gold-hi);
  background:repeating-conic-gradient(rgba(255,217,138,.55) 0 3deg, transparent 3deg 6deg);}
/* глиф печати: ТА ЖЕ геометрия, что у всех астр — <use href="#pg-star"> (шрифтовой ✦ имел
   другую форму лучей и на старых Android рисковал эмодзи-вариантом; GLYPH_SPEC ШАГ 5 · P10).
   Заливка — градиент #pgGold из спрайта; общий opacity:.06 родителя её приглушает как раньше. */
.pw2-wm .pw2-wm-star{position:absolute;top:50%;left:50%;width:110px;height:110px;
  margin:-55px 0 0 -55px;}
/* эхо-печать (P10): астра у H1 пейвола — тот же #pg-star; inline-block, чтобы .pg-burst
   (transform) играл; вспышку вешает renderPaywall при СВЕЖЕМ открытии (_casc). Дыхания у
   печати НЕТ (pg-breathe — только на .pg-приглашениях): печать статично светится. */
.pw2-h1-star{display:inline-block;line-height:1;vertical-align:-2px;}
.pw2-h1-star svg{display:block;width:22px;height:22px;}
/* --- «Что ещё внутри» — 4 строки ПОД планами, inline-SVG stroke-глифы в мягком круге
   (единый стиль iOS/Android вместо эмодзи-зоопарка; замок- и календарь-эмодзи запрещены спеком) --- */
/* Глифы пунктов ценности: БЕЗ круглых орбов и рамок (основатель 2026-07-17: «выглядят как
   кнопки на выбор» — круг+рамка читались как тап-таргет; голый золотой глиф читается как буллет) */
.pw-val-ico{flex:none;display:grid;place-items:center;width:24px;height:24px;
  filter:drop-shadow(0 0 6px rgba(255,217,138,.35));}
.pw-val-ico svg{display:block;width:20px;height:20px;fill:none;stroke:var(--pw-gold);
  stroke-width:1.6;stroke-linecap:round;stroke-linejoin:round;}
/* узкие экраны: плотнее, но анти-обрезание НЕ здесь — оно в конструкции
   (переносы + авто-рост высоты строки), как у промо-капсулы */
@media (max-width:359px){
  .plan-card{padding:12px 11px;gap:7px;}
  .pw-unit{font-size:18px;}
  .pw2-h1{font-size:calc(22px * var(--font-scale));}
}
/* BRL anchor under the ⭐ price (packs / recovery down-sell keep the OLD block form;
   внутри .pw2-sub тот же спан перекрыт инлайн-правилом выше) */
.brl-hint{display:block;margin-top:2px;font-size:12px;font-weight:600;color:var(--hint);white-space:nowrap;letter-spacing:-.2px;}

/* ===== 10 · DAILY REFILL HINT ===== */
.refill-hint{display:inline-flex;align-items:center;gap:5px;position:absolute;top:46px;right:14px;
  font-size:11.5px;font-weight:700;color:var(--credit-low);opacity:0;animation:refillFade .4s ease .2s forwards;}
.refill-hint .rh-dot{width:5px;height:5px;border-radius:50%;background:var(--credit-low);
  animation:checksLowPulse 2.4s ease-in-out infinite;}
@keyframes refillFade{to{opacity:.95}}
@media (prefers-reduced-motion:reduce){.refill-hint .rh-dot{animation:none}}

/* ============================================================================
   «ЛИЧНОСТЬ» / PERSONALITY  ·  Spec §8 F3 (chrome + content)
   Every motif descends from a shipped class (see DESIGN §12 reuse ledger).
   Mnemonic: gold astra ✦ = "subscribe" · dashed violet = "add data".
   ========================================================================== */

/* --- 4th nav tab: localization regression fix (DESIGN §11.1 / SPEC §7) --- */
.tab-label{ max-width:100%; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
@media (max-width:374px){ .tab{ font-size:10px; } }

/* --- Element palette tokens (D7) — one warm + three cool; never gold/violet ---
   Root colour aliases let JS build the weighted conic ring for the sphere. */
:root{ --el-fire:#ff8a5c; --el-earth:#5be3a7; --el-air:#6fd0ff; --el-water:#5b8cff; }
[data-el="fire"]{  --el:#ff8a5c; --el-soft:rgba(255,138,92,.15); --el-glow:rgba(255,138,92,.40); }
[data-el="earth"]{ --el:#5be3a7; --el-soft:rgba(91,227,167,.15); --el-glow:rgba(91,227,167,.38); }
[data-el="air"]{   --el:#6fd0ff; --el-soft:rgba(111,208,255,.15); --el-glow:rgba(111,208,255,.40); }
[data-el="water"]{ --el:#5b8cff; --el-soft:rgba(91,140,255,.15); --el-glow:rgba(91,140,255,.40); }

/* ---------- Shell + scroll-shrink header (DESIGN §1.3, declarations verbatim) ---------- */
.pers-shell{ position:relative; }
.pers-sentinel{ position:absolute; top:0; left:0; width:1px; height:1px; pointer-events:none; }
.pers-hero{ position:relative; display:grid; grid-template-columns:minmax(0,1fr) auto; gap:4px;
  padding:30px 16px 8px; margin:-16px -16px 0; overflow:hidden;   /* pull up over #screen's 16px top pad so no dark strip shows between the TG header and the hero */
  background:radial-gradient(120% 90% at 88% -10%, rgba(179,136,255,.20), rgba(34,26,61,0) 60%),
             linear-gradient(180deg, #1a1530 0%, #251d49 16%, rgba(15,12,29,0) 74%);   /* very top = the TG header colour (#1a1530) → seamless */
  border-radius:0;   /* straight bottom edge (founder): rounded corners + overflow:hidden were clipping the sphere glow into a curved arc */
  /* Founder bug (2026-07-03): the scroll-shrink faded the hero via --p, but the scroll listener that recomputes --p
     is unreliable in iOS Telegram WebView (body-scroll doesn't always fire window scroll) → --p got stuck HIGH and
     the header stayed invisible even at the top after a detail-back. The hero is now a plain header (no --p fade):
     always visible when it's in view, just scrolls off normally when you scroll down. */
  transition:padding .26s var(--sheet-ease); }
.pers-switch{ grid-column:1; grid-row:1; justify-self:start; align-self:start; display:inline-flex; align-items:center; gap:6px;
  min-height:44px; padding:6px 8px; margin:-6px -8px; background:none; border:0; cursor:pointer;
  color:var(--text); font-size:22px; font-weight:800; letter-spacing:-.4px;
  transition:justify-self .26s var(--sheet-ease); }
.pers-switch .ps-name{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap; max-width:62vw; }
.pers-switch .ps-caret{ font-size:16px; color:var(--accent); transition:transform .24s var(--sheet-ease); }
.pers-switch.open .ps-caret{ transform:rotate(180deg); }
.pers-motiv{ grid-column:1; grid-row:2; margin:2px 2px 0; max-width:34ch; text-align:left;
  color:var(--hint); font-size:13.5px; line-height:1.35; overflow:hidden; }
/* (removed .shrunk name-centering — the hero no longer collapses; name stays left-aligned) */
/* reduced-motion: binary .shrunk swap, no continuous interpolation jank */
@media (prefers-reduced-motion:reduce){
  .pers-hero{ transition:none; }
  .pers-switch{ transition:none; }
  .pers-switch .ps-caret{ transition:none; }
  .pers-shell.shrunk .pers-hero{ opacity:1; }   /* header stays visible (see hero note above) */
}

/* ---------- The header sphere — one orb, three skins (DESIGN §1.4) ----------
   CONTRACT for persSkinSphere(sub): set persSphere.dataset.skin = sub
   ('character'|'elements'|'karma'); for 'elements' also
   persSphere.style.setProperty('--el-conic', '<conic-gradient(...)>')
   built from --el-fire/earth/air/water weighted by %; for 'karma' inject
   `<i class="ps-n">☊</i><i class="ps-s">☋</i>` (else empty). Pure CSS otherwise. */
/* ---- BASE ORB (Характер): violet self — gold is reserved for Karma, pink removed ---- */
.pers-sphere{ grid-column:2; grid-row:1 / span 2; justify-self:end; align-self:start; position:relative;
  width:56px; height:56px; border-radius:50%;   /* fixed size (no --p shrink) — see the hero note above */
  transform:translateZ(0);
  background:radial-gradient(circle at 35% 30%, #fff 0%, #c9b6ff 40%, var(--accent) 100%);
  box-shadow:0 0 16px 3px rgba(179,136,255,.52), 0 0 30px 7px rgba(179,136,255,.22);
  animation:al-pulse 3.4s ease-in-out infinite; }
.pers-sphere::before{ content:""; position:absolute; inset:-7px; border-radius:50%;
  border:1px dashed rgba(179,136,255,.32); animation:spin 14s linear infinite; }

/* ---- СТИХИИ: keep the conic %-ring exactly as-is (the hero) ---- */
.pers-sphere[data-skin="elements"]{ background:radial-gradient(circle at 35% 30%, #fff 0%, #2c2550 70%); }
.pers-sphere[data-skin="elements"]::after{ content:""; position:absolute; inset:3px; border-radius:50%;
  background:var(--el-conic, conic-gradient(var(--accent), var(--accent2)));
  -webkit-mask:radial-gradient(closest-side, transparent 58%, #000 60%);
          mask:radial-gradient(closest-side, transparent 58%, #000 60%); }

/* ---- КАРМА: dark moon, gold North limb / violet South body. Axis = injected SVG (.ps-axis) ---- */
.pers-sphere[data-skin="karma"]{
  background:
    radial-gradient(circle at 68% 28%, #ffe7a8 0%, rgba(255,217,138,.45) 22%, transparent 48%),
    radial-gradient(circle at 38% 64%, #4a3a86 0%, #281e4c 60%, #181030 100%);
  box-shadow:0 0 12px 2px rgba(255,217,138,.16), 0 0 22px 6px rgba(124,92,210,.28); }
.pers-sphere[data-skin="karma"]::before{ border-color:rgba(255,217,138,.18); }   /* gold-tinted orbital ring */
/* NOTE: the old [data-skin="karma"]::after vertical line is DELETED — the SVG replaces it. */

/* ---- ЧЁРНАЯ ЛУНА: the dark moon. Black eclipse core, thin garnet corona, cold waning rim. ---- */
.pers-sphere[data-skin="lilith"]{
  background:
    radial-gradient(circle at 50% 50%, transparent 53%, var(--lil) 60%, transparent 71%),
    radial-gradient(circle at 38% 34%, #1b0f22 0%, var(--lil-core) 64%, #050309 100%);
  box-shadow:0 0 12px 2px var(--lil-soft), 0 0 22px 6px rgba(111,29,64,.30),
             inset 0 0 10px 1px rgba(205,214,240,.06); }
.pers-sphere[data-skin="lilith"]::before{ border-color:rgba(216,70,110,.20); }   /* garnet-tinted orbital ring */

/* the nodal-axis SVG (one string, used in header + detail) */
.pers-sphere .ps-axis{ position:absolute; inset:0; width:100%; height:100%;
  overflow:visible; pointer-events:none; }
.pers-sphere .ps-axis .ax-glow{ filter:drop-shadow(0 0 2.5px #ffd98a); }
.pers-sphere .ps-glyph-n{ fill:var(--credit); filter:drop-shadow(0 0 4px var(--credit)); }
.pers-sphere .ps-glyph-s{ fill:rgba(155,145,196,.6); }
.pers-sphere:not(.ps-detail) .ps-glyph{ display:none; }   /* glyphs: header hides, detail shows */

/* ---- DETAIL 120px: element-tint scoped so it no longer clobbers the karma skin (the real bug) ---- */
.pers-sphere.ps-detail{ position:absolute; top:6px; right:-12px; width:120px; height:120px; opacity:.92;
  pointer-events:none; animation:none; }
.pers-sphere.ps-detail:not([data-skin="karma"]):not([data-skin="lilith"]){
  background:radial-gradient(circle at 35% 30%, #fff 0%, var(--el,var(--accent2)) 45%,
            color-mix(in srgb,var(--el,var(--accent)) 70%, #000) 100%);
  box-shadow:0 0 26px 4px var(--el-glow, rgba(179,136,255,.4)); }
.pers-sphere.ps-detail::before{ inset:-9px; border-color:var(--el-soft, rgba(179,136,255,.3)); }
/* real planet SPHERE (server-rendered icon, same as the daily-broadcast cards) — replaces the CSS orb;
   the sphere + its baked body-hued aura carry the glow, the dashed orbital ring (::before) stays. */
.pers-sphere.ps-detail.pl-sphere{ background:none !important; box-shadow:none !important; overflow:visible; }
.pers-sphere.ps-detail.pl-sphere .pl-sphere-img{
  position:absolute; left:50%; top:50%; width:162%; height:162%; transform:translate(-50%,-50%);
  pointer-events:none; }   /* NO border-radius — it would clip the soft baked aura into a hard square/circle */
.pers-sphere.ps-detail[data-skin="karma"]::before{ border-color:rgba(255,217,138,.18); }
.pers-sphere.ps-detail[data-skin="karma"]{
  background:
    radial-gradient(circle at 68% 26%, #ffedbf 0%, rgba(255,217,138,.50) 20%, transparent 46%),
    radial-gradient(circle at 38% 66%, #4a3a86 0%, #241b48 60%, #140c2c 100%);
  box-shadow:0 0 30px 6px rgba(255,217,138,.18), 0 0 40px 10px rgba(124,92,210,.32); }
.pers-sphere.ps-detail[data-skin="karma"]::after{ content:""; position:absolute; inset:0; border-radius:50%;
  box-shadow:inset 0 0 0 1px rgba(255,217,138,.30), inset 0 0 14px 2px rgba(255,217,138,.16); } /* gold corona */
.pers-sphere.ps-detail .ps-glyph{ font-size:13px; }
/* NIT-9: the Ascendant detail hero has no server-rendered sphere — center its ↑ glyph so the orb isn't a blank disc */
.pers-sphere.ps-detail .ps-orb-glyph{ position:absolute; inset:0; display:flex; align-items:center; justify-content:center;
  font-size:46px; line-height:1; color:#fff; opacity:.92; text-shadow:0 0 10px rgba(255,255,255,.35); pointer-events:none; }

/* ---- ЧЁРНАЯ ЛУНА detail orb (120px): stronger ember + cold-silver corona ---- */
.pers-sphere.ps-detail[data-skin="lilith"]{
  background:
    radial-gradient(circle at 50% 50%, transparent 54%, var(--lil) 60%, transparent 72%),
    radial-gradient(circle at 38% 34%, #20122a 0%, var(--lil-core) 66%, #040208 100%);
  box-shadow:0 0 30px 6px rgba(216,70,110,.20), 0 0 40px 10px rgba(111,29,64,.34); }
.pers-sphere.ps-detail[data-skin="lilith"]::before{ border-color:rgba(216,70,110,.22); }
.pers-sphere.ps-detail[data-skin="lilith"]::after{ content:""; position:absolute; inset:0; border-radius:50%;
  box-shadow:inset 0 0 0 1px rgba(205,214,240,.26), inset 0 0 14px 2px rgba(216,70,110,.18); }  /* cold corona */

/* ---- Лилит section body (single screen): chip · hook · shadow · 4 locks · upsell ---- */
.pers-chip[data-skin="lilith"]{ border-color:var(--lil-soft); color:var(--lil-moon); }
.lil-heroline{ display:flex; flex-direction:column; align-items:flex-start; gap:10px; margin:2px 0 14px; }
.lil-heroline .pers-chip{ margin:0; }
.lil-chip-maybe{ display:block; margin-top:3px; font-size:12px; line-height:1.35; font-weight:400; color:var(--hint); }  /* near-cusp hedge — 2nd line INSIDE the chip blob */
/* — «Поделиться тенью» share dock: full-width garnet button, centred glyph+label (founder prefers it stretched) — */
.lil-share{ display:flex; width:100%; box-sizing:border-box; align-items:center; justify-content:center; gap:8px; margin:2px 0 0;
  padding:11px 16px; border-radius:999px; cursor:pointer; font-size:14px; font-weight:800;
  letter-spacing:-.1px; color:var(--lil-moon); -webkit-tap-highlight-color:transparent;
  background:linear-gradient(135deg, rgba(216,70,110,.22), rgba(149,92,214,.18));
  border:1px solid var(--lil); box-shadow:0 8px 22px -10px var(--lil-glow), 0 0 0 1px var(--lil-soft) inset; }
.lil-share .ls-ic{ font-size:15px; color:var(--lil-2); filter:drop-shadow(0 0 6px var(--lil-glow)); }
.lil-share:active{ transform:scale(.97); box-shadow:0 4px 14px -8px var(--lil-glow); }
.lil-share:disabled{ opacity:.7; }
/* the framing + honest "White Moon" (Selena) disclosure — muted lens card under the hook */
.lil-intro{ display:flex; gap:10px; align-items:flex-start; padding:12px 14px; margin-bottom:14px;
  background:var(--card); border:1px solid var(--line); border-radius:var(--radius); }
.lil-intro .li-ico{ flex:none; color:var(--lil-2); font-size:17px; filter:drop-shadow(0 0 6px var(--lil-glow)); }
.lil-intro p{ margin:0; font-size:13.5px; line-height:1.5; color:var(--hint); }
.lil-hook{ position:relative; padding:16px 16px 16px 20px; margin-bottom:14px; overflow:hidden;
  background:linear-gradient(135deg, rgba(216,70,110,.10), transparent 70%), var(--card);
  border:1px solid var(--lil-soft); border-radius:var(--radius); }
.lil-hook::before{ content:""; position:absolute; left:0; top:10px; bottom:10px; width:3px; border-radius:3px;
  background:linear-gradient(var(--lil-2), var(--lil)); }                       /* garnet quote-rule */
.lil-hook .lh-eyebrow{ font-size:11.5px; font-weight:800; letter-spacing:.3px; text-transform:uppercase;
  color:var(--lil); margin:0 0 6px; }
.lil-hook .lh-q{ font-size:19px; line-height:1.35; font-weight:800; color:var(--text); letter-spacing:-.2px; margin:0; }

.lil-shadow{ border:1px solid var(--line); border-left:3px solid var(--lil); border-radius:var(--radius);
  padding:14px 15px; margin-bottom:14px; background:var(--card); }
.lil-shadow .ls-ttl{ font-size:var(--pers-card-title); font-weight:700; color:var(--lil-moon); margin:0 0 6px; }   /* DES-2 (R9): Lilith palette (cold-silver moon rim), not the generic pers title */
.lil-shadow .ls-body p{ font-size:15px; line-height:1.6; color:var(--text); margin:0 0 8px; }
.lil-shadow .ls-body p:last-child{ margin-bottom:0; }

.lil-locks{ display:flex; flex-direction:column; }
.lil-lock{ position:relative; display:flex; align-items:flex-start; gap:12px; width:100%; text-align:left;
  cursor:pointer; border:1px solid var(--lil-soft); border-radius:var(--radius); padding:13px 14px; margin-bottom:10px;
  background:linear-gradient(135deg, rgba(216,70,110,.05), transparent 60%), var(--card); }
.lil-lock:active{ transform:scale(.99); }
.lil-lock.open{ cursor:default; }
.lil-lock .ll-ico{ flex:none; width:38px; height:38px; border-radius:12px; display:grid; place-items:center;
  font-size:18px; background:var(--lil-soft); color:var(--lil-2); filter:grayscale(.45); }   /* veiled mould, never the lock */
.lil-lock .ll-tx{ flex:1; min-width:0; }
.lil-lock .ll-title{ font-size:var(--pers-card-title); font-weight:700; color:var(--lil-moon); margin:0 0 4px; }   /* DES-2 (R9): Lilith palette, one coherent colour with the section */
.lil-lock .ll-teaser{ margin:0; font-size:13.5px; line-height:1.45; color:var(--hint); }      /* full-contrast real teaser */
.lil-lock .ll-teaser.open{ color:var(--text); font-size:15px; line-height:1.6; }
.lil-lock .ll-teaser.open p{ margin:0 0 8px; } .lil-lock .ll-teaser.open p:last-child{ margin-bottom:0; }
.lil-lock .pg, .lil-lock .prem-tag{ flex:none; align-self:center; position:relative; z-index:1; }
  /* золотое свечение = статичный .pg::before (никаких filter/drop-shadow — перф);
     z-index держит астру над magnet-glow розового hero; на hero (attraction) подложка .pg--dark */
.lil-lock.ll-hero{ overflow:hidden; padding:16px 15px; border-color:var(--lil);
  background:linear-gradient(160deg, rgba(216,70,110,.16), rgba(111,29,64,.22)); box-shadow:0 14px 30px -16px var(--lil-glow); }
.lil-lock.ll-hero .ll-title{ font-size:17px; }
.lil-lock.ll-hero::after{ content:""; position:absolute; top:-40px; right:-30px; width:140px; height:140px;
  pointer-events:none; background:radial-gradient(circle, var(--lil-glow), transparent 70%); }   /* magnet glow */

.lil-upsell{ position:relative; overflow:hidden; border-radius:20px; padding:18px 16px 16px; margin:14px 0 6px;
  cursor:pointer; background:linear-gradient(135deg,#3a1830,#241225); border:1px solid var(--lil); }
.lil-upsell:active{ transform:scale(.99); }
.lil-upsell .ku-glow{ position:absolute; top:-60px; right:-40px; width:180px; height:180px; pointer-events:none;
  background:radial-gradient(circle, var(--lil-glow), transparent 70%); }
.lil-upsell .ku-head{ position:relative; display:flex; align-items:center; gap:10px; }
.lil-upsell .ku-ico{ font-size:24px; flex:none; color:var(--lil-2); filter:drop-shadow(0 0 10px var(--lil-glow)); }
.lil-upsell .ku-head h3{ font-size:var(--pers-section-head); font-weight:800; margin:0; }
.lil-upsell .ku-body{ position:relative; font-size:13.5px; line-height:1.4; color:rgba(242,238,251,.85); margin:9px 0 14px; }
.lil-upsell .ku-cta{ position:relative; width:100%; border:0; border-radius:14px; padding:13px; cursor:pointer;
  font-size:15px; font-weight:900; color:#1a1030;                              /* gold = subscribe (doctrine) */
  background:linear-gradient(135deg,#ffe7a8,var(--credit)); box-shadow:0 8px 22px -8px var(--credit-glow); }

@media (prefers-reduced-motion:reduce){
  .pers-sphere{ animation:none; }
  .pers-sphere::before{ animation:none; }
}

/* ---------- Sticky segmented control (DESIGN §1.5, declarations verbatim) ---------- */
.pers-seg{ position:sticky; top:0; z-index:19; display:flex; margin:10px -16px 6px; padding:6px;
  background:rgba(20,16,40,.92); backdrop-filter:blur(12px); -webkit-backdrop-filter:blur(12px);
  border-bottom:1px solid transparent; transition:border-color .2s, box-shadow .2s; }
.seg-opt{ position:relative; z-index:1; flex:1; min-height:44px; background:none; border:0; cursor:pointer;
  padding:11px 3px 9px; font-size:13px; font-weight:700; color:var(--hint);
  white-space:nowrap; transition:color .2s; }
.seg-opt.sel{ color:#1a1030; }                                   /* dark text on the violet thumb */
.seg-thumb{ position:absolute; z-index:0; top:6px; bottom:6px; left:6px; width:calc((100% - 12px)/4);
  border-radius:13px; background:linear-gradient(135deg,var(--accent),var(--accent2));
  box-shadow:0 6px 18px -6px var(--accent);
  transform:translateX(calc(var(--seg-i,0) * 100%)); transition:transform .24s var(--sheet-ease); }
.pers-shell.shrunk .pers-seg{ border-bottom-color:var(--line); box-shadow:0 6px 16px -10px rgba(0,0,0,.6); }
@media (prefers-reduced-motion:reduce){ .seg-thumb{ transition:none; } }

/* ---------- Content swap skeleton (DESIGN §1.6, declarations verbatim) ---------- */
.pers-skel{ display:flex; flex-direction:column; gap:12px; padding-top:4px; }
.pers-skel .sk-card{ height:96px; border-radius:var(--radius); border:1px solid var(--line);
  background:linear-gradient(100deg, var(--card) 30%, #2b2350 50%, var(--card) 70%);
  background-size:200% 100%; animation:skShimmer 1.3s ease-in-out infinite; }
.pers-skel .sk-ring{ height:200px; }
.pers-skel .sk-row{ height:48px; }
@keyframes skShimmer{ to{ background-position:-200% 0; } }
@media (prefers-reduced-motion:reduce){ .pers-skel .sk-card{ animation:none; background:var(--card); } }
/* per-section fetch-failure retry (header + segmented control survive) */
.pers-retry{ text-align:center; padding:28px 16px; color:var(--hint); }
.pers-retry .btn{ margin-top:12px; }

/* base data-aware CTA pill — used OUTSIDE .pers-suppressed (intro nudge, retry); was unstyled grey UA chrome */
.ps-add{ display:inline-flex; align-items:center; gap:4px;
  background:rgba(179,136,255,.12); border:1px solid var(--accent); border-radius:18px; padding:7px 13px;
  font-size:13px; font-weight:700; color:var(--accent); cursor:pointer; }   /* = .ask-chip */
.ps-add:active{ opacity:.7; }

/* ---------- SUPPRESS ≠ LOCK · the dashed-violet "add data" panel (DESIGN §7, verbatim) ---------- */
.pers-suppressed{ border:1px dashed var(--line); background:rgba(255,255,255,.02);
  border-radius:var(--radius); padding:14px 16px; color:var(--hint); }   /* NOT gold, NOT a lock */
.pers-suppressed .ps-ttl{ color:var(--text); font-weight:700; font-size:15px; margin-bottom:4px; }
.pers-suppressed .ps-add{ display:inline-flex; align-items:center; gap:4px; margin-top:8px;
  background:rgba(179,136,255,.12); border:1px solid var(--accent); border-radius:18px; padding:7px 13px;
  font-size:13px; font-weight:700; color:var(--accent); cursor:pointer; }   /* = .ask-chip */
.pers-suppressed .ps-add:active{ opacity:.7; }

/* ---------- ХАРАКТЕР · facet list (DESIGN §2.1, declarations verbatim) ---------- */
.pers-facet{ display:block; width:100%; text-align:left; }
.pers-facet-head{ display:flex; align-items:center; gap:10px; margin-bottom:8px; }
.pers-facet-ico{ flex:none; width:26px; height:26px; display:grid; place-items:center; font-size:17px;
  color:var(--accent); }                                                 /* .dim-ico mould, monochrome glyph */
.pers-facet-title{ flex:1; font-size:var(--pers-card-title); font-weight:700; margin:0; color:var(--pers-title); }
.pers-facet .describe-cue{ width:28px; height:28px; font-size:16px; }   /* chunkier than the 18px forecast ring */
.clamp-3{ display:-webkit-box; -webkit-line-clamp:3; -webkit-box-orient:vertical; overflow:hidden;
  color:var(--hint); font-size:14.5px; line-height:1.5; }               /* NEW: forecast clamp is hardcoded 2-line */
.pers-lead-eyebrow{ font-size:11.5px; font-weight:700; letter-spacing:.3px; text-transform:uppercase;
  color:var(--accent); margin-bottom:4px; }
/* the lead facet (identity/Sun) is the headline of Характер — give the card a violet halo so it reads
   as primary (the modifier was applied in JS but had no rule — a silent style-drop). */
/* the lead facet is distinguished only by being FIRST in the list — no glow/halo (it read as an
   unexplained "why is this one lit up?"). */

/* ---------- ХАРАКТЕР / shared detail chrome (DESIGN §2.2, declarations verbatim) ---------- */
.pers-detail{ position:relative; }
/* Хиро на всю ширину вьюпорта (margin -16 съедает паддинг #screen): край клипа = край экрана,
   сфера «уходит за край» естественно. Раньше клип шёл по паддинг-боксу с overflow-clip-margin:24px —
   WebKit (iPhone: и наше приложение, и Telegram-iOS) clip-margin НЕ поддерживает → жёсткий срез сферы
   + чёрный жёлоб 16px справа (основатель 2026-07-23, скрины). Chromium-вид не меняется (aura и так
   светилась в жёлобе). Внутренний паддинг возвращает контенту прежние поля. */
.pers-detail-hero{ position:relative; margin:0 -16px; padding:6px 16px 0; min-height:142px; overflow-x:clip; }
.pers-chip{ display:inline-block; margin:2px 0 12px; max-width:100%;
  white-space:normal; overflow-wrap:break-word; font-size:11.5px; line-height:1.42; color:var(--hint);
  background:var(--bg2); border:1px solid var(--line); border-radius:13px; padding:5px 11px; }
/* in the detail hero the 120px ps-detail sphere bleeds in top-right; cap the chip like the title so its
   provenance tail (e.g. "Сатурн в Водолее · в изгнании") never slides under/behind the orb */
.pers-detail-hero .pers-chip{ max-width:calc(100% - 130px); }   /* reserve the 120px sphere + its -9px ring + gap so the chip never reaches the dashed ring */
/* B15: near-cusp hedge line under the karma chip — a muted 2nd line (mirrors .lil-chip-maybe) */
.pers-chip-maybe{ display:block; margin:-6px 0 12px; font-size:12px; line-height:1.35; font-weight:400; color:var(--hint); max-width:calc(100% - 130px); }
.pers-detail-title{ font-size:calc(24px * var(--font-scale)); font-weight:800; margin:0 0 8px; max-width:72%; }
/* karma detail carries a faint gold thread (lineage / lunar nodes) so it reads distinct from the
   character detail — the .karma-detail modifier was applied in JS but had no rule. */
/* (karma-detail visual is being redesigned by the design team — no stray border/tint here) */

/* ---------- THE SHARED PAGER · the one new primitive (DESIGN §5, declarations verbatim) ---------- */
.pers-pager{ display:flex; gap:14px; overflow-x:auto; scroll-snap-type:x mandatory; scroll-padding:0 7%;
  padding:4px 7% 18px; margin:0 -16px; overscroll-behavior-x:contain;   /* don't trigger TG back/refresh */
  scrollbar-width:none; -webkit-overflow-scrolling:touch; }
.pers-pager::-webkit-scrollbar{ display:none; }
.pers-page{ flex:0 0 86%; scroll-snap-align:center; scroll-snap-stop:always;
  background:var(--card); border:1px solid var(--line); border-radius:var(--radius);
  padding:18px 16px; line-height:1.6; font-size:15px; color:var(--text);
  min-height:160px; max-height:72vh; overflow-y:auto; }                 /* flex stretch equalizes to tallest page; only the rare >72vh page scrolls */
/* per-page chapter head + body (Gift→Shadow→Invitation, §6.5) — were unstyled raw UA <h3>/<div> */
.pers-page-title{ margin:0 0 10px; font-size:13px; font-weight:800; letter-spacing:.4px; text-transform:uppercase;
  color:var(--accent); }                                              /* matches .pers-lead-eyebrow */
.pers-page-body{ font-size:calc(15px * var(--font-scale)); line-height:1.6; color:var(--text); }
.pers-pager.vstack{ display:block; overflow:visible; margin:0; padding:4px 0 8px; }   /* PERS_VERTICAL fallback */
.pers-pager.vstack .pers-page{ flex:none; width:auto; height:auto; margin-bottom:12px; }
.pers-dots{ display:flex; gap:6px; justify-content:center; margin-top:2px; }
.pers-dots .dot{ width:7px; height:7px; border-radius:50%; background:var(--line); transition:width .2s, background .2s; }
.pers-dots .dot.on{ width:18px; border-radius:4px; background:var(--accent); }   /* active = stretched pill */
.pers-dots-num{ text-align:center; color:var(--hint); font-size:13px; font-weight:600; }
@media (prefers-reduced-motion:reduce){ .pers-dots .dot{ transition:none; } .pers-pager{ scroll-behavior:auto; } }

/* ---------- СТИХИИ · the ring-gauge diagram (DESIGN §3.1/§3.2) ---------- */
.pers-gauge{ display:flex; flex-direction:column; align-items:center; gap:7px; background:none; border:0;
  cursor:pointer; padding:4px; }
.pers-gauge .ring-fg{ stroke:var(--el); }
.pers-gauge.dominant .ring-wrap,.pers-gauge.dominant .ring-wrap svg{ width:84px; height:84px; }
.pers-gauge.dominant .ring-wrap{ box-shadow:0 0 28px -6px var(--el); border-radius:50%; }   /* dominant glows brightest */
.eg-tri{ position:absolute; inset:0; display:grid; place-items:center; pointer-events:none; }
.eg-tri svg{ width:46%; height:46%; }   /* gradient element icons carry their own fill/stroke */
/* the dominant ring is larger (84px) — use a smaller % so the icon stays inside it, not overflowing */
.pers-gauge.dominant .eg-tri svg{ width:40%; height:40%; filter:drop-shadow(0 0 4px var(--el-glow)); }
.eg-pct{ font-size:13px; font-weight:800; color:var(--text); font-variant-numeric:tabular-nums; }
.pers-gauge--approx .ring-fg{ stroke-dasharray:4 4 !important; opacity:.6; box-shadow:none; }
.pers-elem-approx{ text-align:center; font-size:12px; color:var(--hint); margin-top:6px; }   /* full-contrast caption */
.pers-elem-approx::before{ content:"≈ "; }
/* the gauges container is the framed violet diagram panel (the old orphaned .pers-diagram rule). */
.pers-aura{ display:flex; justify-content:space-around; align-items:center; gap:8px; flex-wrap:wrap; margin:8px 0 14px;
  background:var(--card); border:1px solid var(--line); border-radius:var(--radius); min-height:188px; padding:18px 12px; }
.pers-aura .pers-gauge{ flex:0 1 auto; }
/* per-count layouts: 1 centred · 2–3 centred row · 4 → spec'd 2×2 grid (not a cramped single row) */
.pers-aura-1{ justify-content:center; }
.pers-aura-2,.pers-aura-3{ justify-content:center; gap:18px; }
.pers-aura-4{ flex-wrap:nowrap; justify-content:space-between; gap:4px; }   /* all four in ONE row */
/* MIN-21: on ≤370px phones the 4 rings overflow a single row — let them wrap into 2×2 */
@media (max-width:374px){ .pers-aura-4{ flex-wrap:wrap; justify-content:space-around; row-gap:8px; } }
/* element qualities: titled cards (label + its meaning), not a bare word column */
.pers-quals{ display:flex; flex-direction:column; gap:8px; margin-top:10px; }
.pe-qual{ background:var(--bg2); border-radius:12px; padding:9px 12px; }
.pe-q-label{ display:block; font-size:13px; font-weight:700; color:var(--text); margin-bottom:2px; }
.pe-q-text{ display:block; font-size:13px; line-height:1.42; color:var(--hint); }
.pers-elem-balanced{ text-align:center; font-size:13px; font-weight:700; color:var(--accent); margin:2px 0 12px; }

/* ---------- СТИХИИ · element list (DESIGN §3.3) ---------- */
.pers-elem-card{ position:relative; border-left:3px solid var(--el); }   /* extends .card; left --el accent rule */
.pers-elem-head{ display:flex; align-items:center; gap:10px; margin-bottom:8px; }
.pers-elem-head .eg-tri{ position:relative; inset:auto; width:22px; height:22px; }
.pers-elem-head .eg-tri svg{ width:100%; height:100%; }
.pers-elem-name{ flex:1; font-size:var(--pers-card-title); font-weight:700; margin:0; color:var(--text); }   /* neutral white — element colour lives in the icon/left-rule, a blue title would clash */
.pers-elem-pct{ font-size:18px; font-weight:800; color:var(--text); font-variant-numeric:tabular-nums; }
.pers-elem-state{ font-size:12.5px; font-weight:700; margin:0 0 6px; color:var(--hint); }
.pers-elem-card.dominant .pers-elem-state{ color:var(--el); }
.pers-elem-desc{ font-size:14.5px; line-height:1.5; color:var(--text); }   /* renders FULL — no clamp */
.pers-elem-card.absent{ filter:saturate(.35); border-left-color:var(--line); }   /* "Lo que falta" 5th muted card */
.pers-elem-card.absent .pers-elem-pct{ display:none; }
.pers-qualities{ display:flex; flex-wrap:wrap; gap:7px; margin-top:10px; }   /* static labels in v1 */
.pers-quality{ display:inline-flex; align-items:center; min-height:30px; padding:5px 11px; border-radius:16px;
  background:var(--el-soft); border:1px solid var(--el); color:var(--text); font-size:13px; font-weight:600; }
/* tap-to-scroll flash on a gauge target */
.pers-elem-card.flash{ animation:persFlash 1s ease; }
@keyframes persFlash{ 0%{ box-shadow:0 0 0 0 var(--el-glow); } 30%{ box-shadow:0 0 0 3px var(--el-glow); } 100%{ box-shadow:0 0 0 0 rgba(0,0,0,0); } }
@media (prefers-reduced-motion:reduce){ .pers-elem-card.flash{ animation:none; } }

/* ---------- СТИХИИ · recommendations plank — PREMIUM (DESIGN §3.4) ---------- */
.pers-reco{ display:flex; align-items:center; gap:13px; width:100%; text-align:left; cursor:pointer;
  margin:14px 0 4px; padding:15px 16px; border:0; border-radius:var(--radius);
  background:linear-gradient(135deg,#3a2d63,#2a2150); color:var(--text); }
.pers-reco:active{ transform:scale(.99); }
.pers-reco.locked{ box-shadow:0 0 0 1px var(--credit-soft); }   /* D9: gold = "subscribe" */
.pers-reco-ico{ flex:none; font-size:22px; }
.pers-reco-tx{ flex:1; min-width:0; display:flex; flex-direction:column; gap:1px; }
.pers-reco-eyebrow{ font-size:10.5px; font-weight:800; letter-spacing:.4px; color:var(--accent); }
.pers-reco.locked .pers-reco-eyebrow{ color:var(--credit); }
.pers-reco-title{ font-size:var(--pers-card-title); font-weight:700; }
.pers-reco-sub{ font-size:12.5px; color:var(--hint); }
.pers-reco .pg{ flex:none; }   /* астра: свечение = статичный .pg::before; подложка .pg--dark обязательна — голое золото сливается с золотой рамкой планки */
.pers-reco-go{ flex:none; font-size:20px; font-weight:800; color:var(--accent); }   /* violet › = "open here" */
/* N8: the reco pill carries data-el (fire/earth/air/water → --el/--el-soft); nothing consumed it, so
   the element tint never applied. Tint the pill to its element — but NOT the neutral "balanced" pill
   (data-el="", no --el vars) so it keeps the default .pill styling. */
.pers-reco-pill[data-el]:not([data-el=""]){ background:var(--el-soft); color:var(--el); }

/* ---------- КАРМА · intro + list + upsell (DESIGN §4) ---------- */
.karma-intro{ margin-bottom:14px; }
.karma-intro .ki-head{ display:flex; align-items:center; gap:10px; margin-bottom:8px; }
.karma-intro .ki-ico{ font-size:22px; color:var(--accent); text-shadow:0 0 10px var(--accent); }
.karma-intro h3{ font-size:var(--pers-section-head); font-weight:800; margin:0; }
.karma-intro .ki-body{ font-size:14px; line-height:1.5; }
.karma-list{ display:flex; flex-direction:column; gap:10px; }
.karma-row{ display:flex; align-items:flex-start; gap:12px; width:100%; text-align:left; cursor:pointer;
  background:var(--card); border:1px solid var(--line); border-radius:var(--radius); padding:14px 15px; }
.karma-row:active{ transform:scale(.99); }
.karma-row .kr-ico{ flex:none; width:38px; height:38px; border-radius:12px; display:grid; place-items:center;
  font-size:18px; background:rgba(179,136,255,.14); color:var(--accent); }   /* .dim-ico violet mould */
.karma-row .kr-tx{ flex:1; min-width:0; }
.karma-row .kr-title{ font-size:var(--pers-card-title); font-weight:700; margin:0 0 5px; display:flex; align-items:center; gap:8px; color:var(--pers-title); }
.karma-row .kr-free{ font-size:10.5px; font-weight:800; letter-spacing:.3px; text-transform:uppercase;
  color:var(--good); background:rgba(91,227,167,.14); border:1px solid var(--good); border-radius:10px; padding:1px 7px; }
.karma-row .kr-sum{ margin:0; }
.karma-row .kr-go{ flex:none; align-self:center; font-size:20px; font-weight:800; color:var(--accent); }
/* locked teaser: signal lock via gold-tinted SOLID border + the gold astra .pg--badge (dashed is
   reserved for suppressed, D12/§7). grayscale lives only on the icon mould — never on the astra:
   its glow is the static .pg::before (no filter/drop-shadow — perf), breathing in sync (delay:0,
   stagger запрещён). Free rows keep the violet › (.kr-go base rule above). */
.karma-row.lock{ border-color:var(--credit-soft); }
.karma-row.lock .kr-ico{ filter:grayscale(.4); } /* мягче: астра+PREMIUM уже сигналят замок */
.karma-row.lock .kr-sum{ color:var(--hint); }   /* full-contrast teaser */
.karma-row.lock .pg, .karma-row.lock .prem-tag{ flex:none; align-self:center; }
/* violet upsell card — the Account gold .acc-prem grammar, recoloured (D9) */
.karma-upsell{ position:relative; overflow:hidden; border-radius:20px; padding:18px 16px 16px;
  margin:14px 0 6px; cursor:pointer;
  background:linear-gradient(135deg,#3a2d63,#2a2150); border:1px solid rgba(179,136,255,.45); }
.karma-upsell:active{ transform:scale(.99); }
.karma-upsell .ku-glow{ position:absolute; top:-60px; right:-40px; width:180px; height:180px; pointer-events:none;
  background:radial-gradient(circle, rgba(179,136,255,.42), rgba(179,136,255,0) 70%); }   /* static corner glow — was a distracting pulse */
.karma-upsell .ku-head{ position:relative; display:flex; align-items:center; gap:10px; }
.karma-upsell .ku-ico{ font-size:24px; flex:none; color:var(--accent); filter:drop-shadow(0 0 10px var(--accent)); }
.karma-upsell .ku-head h3{ font-size:var(--pers-section-head); font-weight:800; margin:0; }   /* 900 reserved for the gold CTA */
.karma-upsell .ku-body{ position:relative; font-size:13.5px; line-height:1.4; color:rgba(242,238,251,.85); margin:9px 0 14px; }
.karma-upsell .ku-cta{ position:relative; width:100%; border:0; border-radius:14px; padding:13px; cursor:pointer;
  font-size:15px; font-weight:900; color:#1a1030;                       /* the sole 900-weight: the gold upsell CTA */
  background:linear-gradient(135deg,var(--accent),var(--accent2)); box-shadow:0 8px 22px -8px var(--accent); }

/* ---------- Profile switcher list (.pers-prof = .mc-way reskin, DESIGN §1.7) ---------- */
.pers-prof-list{ display:flex; flex-direction:column; gap:9px; margin-top:14px; }
.pers-prof{ display:flex; align-items:center; gap:12px; width:100%; text-align:left; min-height:44px;
  padding:9px 12px; border-radius:14px; background:var(--bg2); border:1px solid var(--line); cursor:pointer;
  color:var(--text); }   /* explicit light name colour — else the client theme leaks a near-black default (low contrast on dark) */
.pers-prof.sel{ border-color:var(--accent); background:rgba(179,136,255,.12); }
.pers-prof .pp-nm{ flex:1; min-width:0; font-size:15px; font-weight:700; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.pers-prof .pp-ck{ flex:none; color:var(--accent); font-weight:800; font-size:16px; }
.pers-prof.add{ border-style:dashed; color:var(--accent); }
.pers-prof.add .person-ava{ background:rgba(179,136,255,.12); color:var(--accent); }

/* ---------- first-run teach card (pers.intro) ---------- */
.pers-intro{ margin-bottom:14px; }
.pers-intro .pers-intro-l1{ font-size:var(--pers-section-head); font-weight:800; margin:0 0 6px; }
.pers-intro .hint{ font-size:calc(14px * var(--font-scale)); line-height:1.5; margin:2px 0; }
.pers-intro .pers-intro-cta{ display:flex; flex-wrap:wrap; align-items:center; gap:10px; margin-top:12px; }

/* ---------- a11y focus ring (DESIGN §11.4) ---------- */
.pers-shell :focus-visible, .pers-detail :focus-visible, .pers-pager :focus-visible, .pers-prof:focus-visible{
  outline:2px solid var(--accent); outline-offset:2px; border-radius:8px; }

/* ✦ ВАШИ ГЛАВЫ — personal transit chapters (Section B) */
.fc-sec{ display:flex; align-items:center; gap:8px; margin:22px 4px 12px; }
.fc-sec-mark{ color:var(--gold,#ffd98a); font-size:13px; }
.fc-sec-lbl{ font-size:12px; font-weight:800; letter-spacing:.14em; color:var(--hint,#9b91c4); text-transform:uppercase; white-space:nowrap; }
.fc-sec::after{ content:""; flex:1; height:1px; background:linear-gradient(90deg,rgba(155,145,196,.3),transparent); }
/* R5-M3-1: на 320px подпись «показано на сегодня» ломала строку шапки и съедала
   линию-разделитель (ellipsis не вариант — усечение честной подписи до «показано на
   с…» убивает её смысл). На широких — одна строка с ужатием как страховка (min-width
   у линии держит «конец линии» для «i»); на самых узких подпись СОЗНАТЕЛЬНО переезжает
   второй строкой под заголовок, а первая строка остаётся «✦ ЗАГОЛОВОК ─── i» — целиком.
   ВСЁ скоплено под .fc-sec--i (шапка С кнопкой «i», т.е. при включённом ритуале):
   без кнопки — RELEASE_SPLIT — шапка на проде обязана вести себя как на master.
   pointer-events:none на подписи — SPLIT2-1: строка подписи ложилась поверх нижней
   половины 44px-хит-зоны кнопки и съедала тапы по нижним углам. */
.fc-sec--i::after{ min-width:14px; }
.fc-sec--i .fc-sec-sub{ white-space:nowrap; overflow:hidden; text-overflow:ellipsis; min-width:0; pointer-events:none; }
@media (max-width:345px){
  .fc-sec--i{ flex-wrap:wrap; row-gap:2px; }
  .fc-sec--i .fc-sec-sub{ order:2; flex:0 0 100%; margin-left:21px; }  /* под текст заголовка: ✦(13px)+gap(8px) */
}
/* «i» секции транзитов (FIX_RITUAL_5 п.6): стоит В КОНЦЕ линии-разделителя — order:1
   отправляет кнопку ЗА ::after-линию (у той order:0). Кружок 22px, хит-зона 44px —
   ::before (приём .mx-info: расширяем зону, не кнопку); отрицательные вертикальные
   маргины не дают 22px-кружку раздуть строку шапки. Без анимаций — в reduced-motion
   глушить нечего. */
.fc-sec-i{ order:1; flex:none; position:relative; width:22px; height:22px; margin:-4px 0;
  border-radius:50%; border:1px solid rgba(255,255,255,.20); background:rgba(255,255,255,.05);
  color:var(--hint,#9b91c4); font-family:inherit; font-style:italic; font-weight:700; font-size:12px;
  line-height:1; display:grid; place-items:center; cursor:pointer;
  -webkit-tap-highlight-color:transparent; }
.fc-sec-i::before{ content:""; position:absolute; inset:-11px; }   /* 22 + 2×11 = 44px */
.fc-sec-i:active{ background:rgba(255,255,255,.11); color:var(--text,#f2eefb); }
/* шторка «что такое транзиты» — та же типографика, что у легенды 14 дней */
.tfi-sheet h2{ margin:0 0 12px; font-size:17px; }
.tfi-sheet p{ margin:0 0 10px; font-size:13.5px; line-height:1.5; color:var(--text); opacity:.9; }
.tfi-sheet .tfi-read{ margin-top:14px; color:var(--hint,#9b91c4); opacity:1; }
.tfi-row{ display:flex; align-items:baseline; gap:10px; padding:6px 0; font-size:13.5px; line-height:1.45; color:var(--text); }
.tfi-row .tf-lg{ flex:none; }
.tfi-row b{ font-weight:700; }
.tf-list{ display:flex; flex-direction:column; gap:12px; }
.tf-cell{ background:var(--card,#221a3d); border-radius:16px; padding:14px 16px; border-left:3px solid var(--accent,#b388ff); }
.tf-cell.tint-saturn{ border-left-color:#8a93b5 } .tf-cell.tint-pluto{ border-left-color:#c0507e }
.tf-cell.tint-jupiter{ border-left-color:#e9b873 } .tf-cell.tint-uranus{ border-left-color:#5fd6e3 }
.tf-cell.tint-neptune{ border-left-color:#7e8ce0 } .tf-cell.tint-mars{ border-left-color:#ff7e6b }
.tf-cell.tint-node{ border-left-color:#9b8cff }
.tf-top{ display:flex; justify-content:space-between; align-items:center; margin-bottom:6px; }
.tf-pill{ font-size:11px; font-weight:700; color:var(--accent,#b388ff); text-transform:uppercase; letter-spacing:.04em; }
.tf-period{ font-size:12px; color:var(--hint,#9b91c4); }
.tf-title{ margin:2px 0 10px; font-size:calc(17px * var(--font-scale)); font-weight:700; color:var(--text); line-height:1.25; }
.tf-bar{ position:relative; height:6px; border-radius:3px; background:rgba(255,255,255,.08); }
.tf-fill{ position:absolute; left:0; top:0; height:100%; border-radius:3px; background:linear-gradient(90deg,var(--accent,#b388ff),var(--accent2,#ff7eb6)); }
.tf-peak{ position:absolute; top:-3px; width:0; height:0; border-left:4px solid transparent; border-right:4px solid transparent; border-bottom:7px solid var(--gold,#ffd98a); transform:translateX(-4px); }
.tf-count{ margin-top:7px; font-size:12px; color:var(--hint,#9b91c4); }
.tf-body{ margin-top:11px; }
.tf-spine{ font-size:calc(13.5px * var(--font-scale)); line-height:1.5; color:var(--text); opacity:.92; margin:0 0 8px; }
.tf-read{ font-size:calc(13.5px * var(--font-scale)); line-height:1.55; color:var(--text); opacity:.78; margin:0 0 10px; }
.tf-recs{ list-style:none; padding:0; margin:0; display:flex; flex-direction:column; gap:5px; }
.tf-rec{ font-size:13px; line-height:1.4; padding-left:18px; position:relative; color:var(--text); opacity:.86; }
.tf-rec.good::before{ content:"＋"; position:absolute; left:0; color:var(--good,#5be3a7); font-weight:700; }
.tf-rec.bad::before{ content:"−"; position:absolute; left:3px; color:var(--warn,#ffd166); font-weight:700; }
.tf-addtime{ margin:12px 4px 4px; padding:11px 14px; border:1px dashed rgba(179,136,255,.5); border-radius:12px; color:var(--accent,#b388ff); font-size:13px; text-align:center; }
/* 1c-3: locked-chapter PREVIEW sheet — a real taste (2 sentences / spine) that fades out into a subscribe CTA */
.tf-teaser{ position:relative; margin:2px 0 0; }
.tf-teaser-body{ margin:0; opacity:.9; -webkit-mask-image:linear-gradient(180deg,#000 42%,transparent 100%); mask-image:linear-gradient(180deg,#000 42%,transparent 100%); }
.tf-teaser-fade{ position:absolute; left:0; right:0; bottom:0; height:56px; pointer-events:none;
  background:linear-gradient(180deg, rgba(34,26,61,0) 0%, var(--card,#221a3d) 92%); }
.tf-teaser-cta{ margin-top:10px; width:100%; display:flex; justify-content:center; align-items:center; gap:6px;
  padding:12px; border-radius:12px; border:1px solid var(--gold,#ffd98a); background:rgba(255,217,138,.10);
  color:var(--gold,#ffd98a); font:inherit; font-weight:700; font-size:14.5px; cursor:pointer;
  -webkit-tap-highlight-color:transparent; }
.tf-teaser-cta:active{ background:rgba(255,217,138,.18); }
/* «Астра»: micro-line between the teaser fade and the CTA — the chapters' premium anchor (glyph + the word
   Premium via common.premium_more). Glyph markup comes from premGlyph("inline") in JS; hint-sized gold text. */
.tf-prem-more{ display:flex; align-items:center; justify-content:center; gap:6px; margin:2px 0 0;
  font-size:12px; font-weight:600; letter-spacing:.02em; color:var(--gold,#ffd98a); }

/* transit chapter cell = tappable button → detail sheet */
.tf-cell{ display:block; width:100%; text-align:left; font:inherit; color:var(--text);
  -webkit-appearance:none; appearance:none; border:0; border-left:3px solid var(--accent,#b388ff);
  cursor:pointer; -webkit-tap-highlight-color:transparent; }
.tf-title{ display:flex; align-items:center; justify-content:space-between; gap:8px; }
.tf-go{ color:var(--hint,#9b91c4); font-size:19px; font-weight:400; flex:0 0 auto; opacity:.7; }
.tf-lk{ font-size:14px; flex:0 0 auto; }
.tf-sub{ font-size:12.5px; color:var(--hint,#9b91c4); margin:-4px 0 10px; letter-spacing:.01em; }
/* detail sheet */
.tf-sheet{ border-left:3px solid var(--accent,#b388ff); padding-left:13px; }
.tf-sheet.tint-saturn{ border-left-color:#8a93b5 } .tf-sheet.tint-pluto{ border-left-color:#c0507e }
.tf-sheet.tint-jupiter{ border-left-color:#e9b873 } .tf-sheet.tint-uranus{ border-left-color:#5fd6e3 }
.tf-sheet.tint-neptune{ border-left-color:#7e8ce0 } .tf-sheet.tint-mars{ border-left-color:#ff7e6b }
.tf-sheet .tf-sub{ margin:0 0 6px; }
.tf-sh-title{ margin:2px 0 5px; font-size:21px; font-weight:700; color:var(--text); line-height:1.2; }
.tf-sh-meta{ font-size:13px; color:var(--hint,#9b91c4); margin-bottom:15px; }

/* why-now causal line + body-tint→gold progress fill (peak = the gold endpoint) */
.tf-why{ margin-top:8px; font-size:12px; color:var(--credit,#ffd98a); opacity:.82; line-height:1.35; }
.tf-why-sheet{ font-size:13.5px; color:var(--gold,#ffd98a); line-height:1.5; margin:0 0 13px; }
.tf-cell.tint-saturn .tf-fill,.tf-sheet.tint-saturn .tf-fill{ background:linear-gradient(90deg,#8a93b5,var(--gold,#ffd98a)) }
.tf-cell.tint-pluto .tf-fill,.tf-sheet.tint-pluto .tf-fill{ background:linear-gradient(90deg,#c0507e,var(--gold,#ffd98a)) }
.tf-cell.tint-jupiter .tf-fill,.tf-sheet.tint-jupiter .tf-fill{ background:linear-gradient(90deg,#e9b873,var(--gold,#ffd98a)) }
.tf-cell.tint-uranus .tf-fill,.tf-sheet.tint-uranus .tf-fill{ background:linear-gradient(90deg,#5fd6e3,var(--gold,#ffd98a)) }
.tf-cell.tint-neptune .tf-fill,.tf-sheet.tint-neptune .tf-fill{ background:linear-gradient(90deg,#7e8ce0,var(--gold,#ffd98a)) }
.tf-cell.tint-mars .tf-fill,.tf-sheet.tint-mars .tf-fill{ background:linear-gradient(90deg,#ff7e6b,var(--gold,#ffd98a)) }
.tf-cell:active{ transform:scale(.99); transition:transform .1s; }

/* peak marker → a downward gold pin sitting ON the bar (was a triangle floating too high) */
.tf-peak{ position:absolute; top:-2px; width:0; height:0; border-left:4px solid transparent;
  border-right:4px solid transparent; border-top:6px solid var(--gold,#ffd98a); border-bottom:0;
  transform:translateX(-4px); }

/* long-period UX: peak-anchored metric + phase chip + graded peaks + you-are-here head + sheet timeline */
.tf-mbig{ color:var(--gold,#ffd98a); font-weight:700; font-size:13.5px; }
.tf-msub{ color:var(--hint,#9b91c4); font-size:12px; }
.tf-pill.tf-ph-peak{ color:var(--gold,#ffd98a); }
.tf-pill.tf-ph-applying{ color:var(--accent,#b388ff); }
.tf-pill.tf-ph-between,.tf-pill.tf-ph-separating,.tf-pill.tf-ph-upcoming{ color:var(--hint,#9b91c4); }
.tf-peak.past{ opacity:.4; border-top-color:var(--hint,#9b91c4); }
.tf-peak.future{ opacity:.6; }
.tf-peak.next{ filter:drop-shadow(0 0 4px var(--gold,#ffd98a)); }
.tf-head{ position:absolute; top:-3px; width:2px; height:12px; background:#fff; transform:translateX(-1px); border-radius:1px; box-shadow:0 0 3px rgba(255,255,255,.6); z-index:2; }
.tf-sh-phase{ display:flex; align-items:baseline; gap:8px; flex-wrap:wrap; margin-bottom:10px; }
.tf-enc{ display:flex; gap:8px; flex-wrap:wrap; margin-bottom:9px; align-items:flex-start; }
.tf-enc-i{ display:inline-flex; flex-direction:column; align-items:center; gap:3px; }   /* station beat: pill + role label */
.tf-enc-lbl{ font-size:10px; font-style:normal; color:var(--hint,#9b91c4); opacity:.8; letter-spacing:.02em; }
.tf-enc-n{ font-size:12px; padding:3px 9px; border-radius:999px; border:1px solid rgba(255,217,138,.35); color:var(--gold,#ffd98a); opacity:.55; }
.tf-enc-n.next{ opacity:1; background:rgba(255,217,138,.12); }
.tf-enc-n.past{ opacity:.4; border-color:rgba(155,145,196,.3); color:var(--hint,#9b91c4); }
.tf-sh-win{ font-size:11.5px; color:var(--hint,#9b91c4); opacity:.7; margin-bottom:13px; }


/* ════ Transit timeline RAIL v2 — bounded · dated · peak-centric (design-team redesign) ════ */
.tf-cell.tint-saturn{ --tf-tint:#8a93b5 } .tf-cell.tint-pluto{ --tf-tint:#c0507e }
.tf-cell.tint-jupiter{ --tf-tint:#e9b873 } .tf-cell.tint-uranus{ --tf-tint:#5fd6e3 }
.tf-cell.tint-neptune{ --tf-tint:#7e8ce0 } .tf-cell.tint-mars{ --tf-tint:#ff7e6b }
.tf-cell.tint-node{ --tf-tint:#9b8cff }
.tf-bar{ position:relative; height:6px; margin:20px 4px 0; border-radius:3px; background:rgba(255,255,255,.07); overflow:visible; }
/* lived TRAIL — thin, tint-only (gold leaves the fill), demoted behind the now-dot */
.tf-fill{ position:absolute; left:0; top:50%; transform:translateY(-50%); height:3px; border-radius:2px; opacity:.5; background:var(--tf-tint,#b388ff) !important; }
/* window boundary CAPS */
.tf-cap{ position:absolute; top:50%; transform:translateY(-50%); width:2px; height:11px; border-radius:1px; background:var(--hint,#9b91c4); }
.tf-cap.s{ left:0; opacity:.55 } .tf-cap.e{ right:0; opacity:.78 }
/* start/end DATE row under the bar (the dates now label the geometry) */
.tf-ends{ display:flex; justify-content:space-between; margin:7px 1px 0; font-size:10.5px; color:var(--hint,#9b91c4); font-variant-numeric:tabular-nums; }
/* PEAK pins — diamond nodes riding ABOVE the track, graded by SHAPE (a11y) not just hue */
.tf-peak{ position:absolute; bottom:9px; left:0; width:8px; height:8px; border:0; border-radius:1px;
  transform:translateX(-50%) rotate(45deg); background:var(--gold,#ffd98a); }
.tf-peak.past{ background:var(--hint,#9b91c4); opacity:.45; }
.tf-peak.future{ opacity:.7; }
.tf-peak.next{ width:10px; height:10px; box-shadow:0 0 6px var(--gold,#ffd98a); }
.tf-peak.retro{ background:transparent; border:1.5px solid var(--gold,#ffd98a); }
.tf-rx{ position:absolute; left:50%; bottom:11px; transform:translateX(-50%) rotate(-45deg); font-size:9px; color:var(--gold,#ffd98a); }
/* the universal NOW dot — a DISC on the track (distinct shape from the peak diamonds), on EVERY card */
.tf-now{ position:absolute; top:50%; width:11px; height:11px; transform:translate(-50%,-50%); border-radius:50%;
  background:var(--tf-tint,#b388ff); border:1.5px solid #fff; box-shadow:0 0 6px -1px var(--tf-tint,#b388ff); z-index:2; }
.tf-now::after{ content:""; position:absolute; inset:0; margin:auto; width:3px; height:3px; border-radius:50%; background:#fff; }
.tf-now.ghost{ background:transparent; border-color:var(--hint,#9b91c4); box-shadow:none; }
.tf-now.ghost::after{ display:none; }
.tf-now.done{ opacity:.5; box-shadow:none; }
.tf-now.live{ animation:tfBreathe 2.4s ease-in-out infinite; }
.tf-now.peak{ background:#fff; border-color:var(--gold,#ffd98a); box-shadow:0 0 9px var(--gold,#ffd98a); }
@keyframes tfBreathe{ 0%,100%{ box-shadow:0 0 4px -1px var(--tf-tint,#b388ff) } 50%{ box-shadow:0 0 10px 1px var(--tf-tint,#b388ff) } }
@media (prefers-reduced-motion:reduce){ .tf-now.live{ animation:none } }

/* ════ simplified rail (founder: проще, но красиво) — tint fill + ONE soft-gold peak dot ════ */
.tf-bar{ margin:9px 4px 0; height:5px; }
.tf-fill{ height:5px !important; opacity:.85 !important; border-radius:3px; }
.tf-pk{ position:absolute; top:50%; width:9px; height:9px; transform:translate(-50%,-50%); border-radius:50%;
  background:var(--gold,#ffd98a); box-shadow:0 0 8px var(--gold,#ffd98a); z-index:2; }
.tf-pk.hot{ background:#fff; box-shadow:0 0 11px 1px var(--gold,#ffd98a); }

/* ════════ Transit chapters v3 — minimalist planet-badge cards (founder ref IMG_0111). Overrides the rail layout above. ════════ */
.tf-list{ display:flex; flex-direction:column; gap:10px; }
.tf-cell{ display:flex; align-items:flex-start; gap:13px; width:100%; text-align:left; font:inherit;
  background:var(--card,#221a3d); border:1px solid rgba(255,255,255,.05); border-left:1px solid rgba(255,255,255,.05);
  border-radius:16px; padding:13px 15px; color:var(--text); cursor:pointer; transition:transform .1s, background .15s; }
.tf-cell:active{ transform:scale(.99); }
/* upcoming / eased transits: дим вешаем ТОЛЬКО на текст, не на контейнер (основатель 2026-07-18:
   opacity ячейки гасил и сферу, и премиум-астру в углу → «тёмные звёзды»). Сфера-глиф и .pg
   остаются в полной яркости — звезда всегда горит, «предстоящесть» несёт приглушённый текст + чип «через N дней». */
.tf-cell.is-soon  .tf-hd1, .tf-cell.is-soon  .tf-chip, .tf-cell.is-soon  .tf-asp, .tf-cell.is-soon  .tf-desc{ opacity:.62; }
.tf-cell.is-eased .tf-hd1, .tf-cell.is-eased .tf-chip, .tf-cell.is-eased .tf-asp, .tf-cell.is-eased .tf-desc{ opacity:.66; }
/* the lit planet sphere + its glyph */
.tf-badge{ position:relative; flex:0 0 auto; width:46px; height:46px; border-radius:50%;
  display:flex; align-items:center; justify-content:center;
  background:radial-gradient(circle at 33% 27%, rgba(255,255,255,.55), var(--tf-tint,#b388ff) 62%, rgba(8,5,20,.35) 140%);
  box-shadow:0 3px 9px -3px rgba(0,0,0,.55), inset 0 1px 0 rgba(255,255,255,.22), inset 0 0 0 1px rgba(255,255,255,.08); }
.tf-bg-gl{ font-size:22px; line-height:1; color:#fff; text-shadow:0 1px 3px rgba(0,0,0,.45); transform:translateY(-1.5px); } /* астро-глиф шрифт сажает низко → поднимаем к центру сферы (основатель 2026-07-18) */
/* ШОРТКАТЫ font: НИЖЕ РАЗЛОЖЕНЫ В LONGHAND (основатель 2026-08-02). Запись вида
   `font:800 14px/1 inherit` НЕВАЛИДНА — inherit разрешён только как значение всего
   свойства, а не как семейство внутри шортката, — и движок выбрасывал декларацию
   ЦЕЛИКОМ. Замер до правки: вес 400 и размер 16px у бейджей (вместо 800/14, 700/10,
   700/13) и системный Arial 13.33px у кнопок .f14-unlock/.f14-handoff.
   Семейство у <i>-бейджей и так наследовалось верно — теряли только вес и размер. */
.tf-bg-dir{ position:absolute; top:-4px; right:-4px; width:21px; height:21px; border-radius:50%;
  display:flex; align-items:center; justify-content:center; font-weight:800; font-size:14px; line-height:1; font-family:inherit; font-style:normal;
  background:var(--bg,#15102b); box-shadow:inset 0 0 0 1.5px currentColor; }
.tf-bg-dir.dir-up{ color:var(--good,#5be3a7); } .tf-bg-dir.dir-down{ color:var(--gold,#ffd98a); }
.tf-bg-dir.dir-neutral{ color:var(--teal,#56c9c0); }
/* crisp SVG direction arrow — sizes per context, centers exactly, colored via currentColor */
.tf-arw{ display:inline-block; width:1em; height:1em; vertical-align:-0.14em; fill:none; stroke:currentColor; stroke-width:2.6; stroke-linecap:round; stroke-linejoin:round; }
.tf-bg-dir .tf-arw{ display:block; width:15px; height:15px; vertical-align:0; }
.tf-chip .tf-arw{ width:13px; height:13px; }
.tf-bg-rx{ position:absolute; bottom:-4px; left:-4px; min-width:16px; height:16px; padding:0 3px; border-radius:8px;
  display:flex; align-items:center; justify-content:center; font-weight:700; font-size:10px; line-height:1; font-family:inherit; font-style:normal;
  background:var(--bg,#15102b); color:var(--hint,#9b91c4); box-shadow:inset 0 0 0 1px rgba(255,255,255,.18); }
/* the right text column */
.tf-col{ position:relative; flex:1 1 auto; min-width:0; }
.tf-col .tf-go{ position:absolute; top:0; right:0; color:var(--hint,#9b91c4); font-size:18px; opacity:.55; }
/* locked card corner: the premium astra (.pg--corner, 16px) replaces the › chevron inside the same .tf-go slot.
   Full brightness — the .55 dim above is chevron-affordance only; a dimmed astra would mute the invitation.
   display:block kills the inline baseline gap so the 16px box sits flush; .tf-hd1 padding-right:18px still clears it.
   (No :has() — old LatAm Android webviews; the existing .locked class on the cell is the hook.) */
.tf-cell.locked .tf-col .tf-go{ opacity:1; }
.tf-go .pg{ display:block; }
.tf-hd1{ font-size:15.5px; font-weight:700; color:var(--text); line-height:1.2; padding-right:18px; }
.tf-sgn{ font-size:12.5px; font-weight:500; color:var(--hint,#9b91c4); white-space:nowrap; }
.tf-chip{ display:inline-flex; align-items:center; gap:5px; margin:6px 0 6px; font-size:11.5px; font-weight:600;
  padding:2px 9px; border-radius:999px; background:rgba(255,255,255,.06); color:var(--hint,#9b91c4); }
.tf-chip .tf-ar{ font-weight:800; }
.tf-chip.dir-up{ color:var(--good,#5be3a7); background:rgba(91,227,167,.12); }
.tf-chip.dir-down{ color:var(--gold,#ffd98a); background:rgba(255,217,138,.12); }
.tf-chip.dir-neutral{ color:var(--teal,#56c9c0); background:rgba(86,201,192,.12); }
.tf-asp{ font-size:12.5px; font-weight:600; color:var(--text); opacity:.8; margin-bottom:3px; }
.tf-desc{ margin:0; font-size:12.5px; line-height:1.4; color:var(--hint,#9b91c4);
  display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden; }
.tf-cell.is-soon .tf-badge{ filter:saturate(.85); } /* было .55 — сфера читалась тускло (основатель 2026-07-18) */
/* legend — decodes the badge symbols (↑/↓/− direction + ℞ retro) */
/* РАСТЯНУТА НА ВСЮ СТРОКУ (основатель 2026-08-02). Была прижата влево и обрывалась на
   середине карточки, оставляя справа пустоту. space-between разносит четыре ключа по всей
   ширине: крайние садятся ровно на края контейнера, зазор 11px становится МИНИМУМОМ, а не
   фиксированной величиной. Для длинных локалей (ru: сумма 333px против 320px доступных)
   перенос сохраняется — MIN-22 требует, чтобы ключ ℞ никогда не обрезался, — и осиротевший
   элемент второй строки прижимается влево, что читается нормально. Вариант «четыре равные
   колонки» отвергнут: он центрирует такого сироту посреди пустой строки. */
.tf-legend{ display:flex; flex-wrap:wrap; align-items:center; justify-content:space-between; gap:4px 11px; margin:-2px 2px 12px; font-size:10.5px; color:var(--hint,#9b91c4); white-space:normal; overflow:visible; }   /* MIN-22: wrap on small screens / long RU so the ℞ key never truncates */
.tf-legend span{ display:inline-flex; align-items:center; gap:3px; }
.tf-lg{ display:inline-flex; align-items:center; }
.tf-lg .tf-arw{ width:13px; height:13px; vertical-align:0; }
.tf-lg.dir-up{ color:var(--good,#5be3a7); } .tf-lg.dir-down{ color:var(--gold,#ffd98a); } .tf-lg.dir-neutral{ color:var(--teal,#56c9c0); }
.tf-lg-rx{ font-style:normal; font-weight:700; color:var(--hint,#cdc4e8); }
.tf-cell.is-peak .tf-badge{ animation:tfBreathe 2.7s ease-in-out infinite; }
@keyframes tfBreathe{ 0%,100%{ box-shadow:0 3px 9px -3px rgba(0,0,0,.55), inset 0 1px 0 rgba(255,255,255,.22), inset 0 0 0 1px rgba(255,255,255,.08); }
  50%{ box-shadow:0 0 15px 2px var(--tf-tint,#b388ff), inset 0 1px 0 rgba(255,255,255,.3), inset 0 0 0 1px rgba(255,255,255,.14); } }
@media (prefers-reduced-motion:reduce){ .tf-cell.is-peak .tf-badge{ animation:none } }

/* ════ retrograde-STATION cards (Mercury/Venus/Mars) — same badge language, gold ℞ in the notch ════ */
.tf-cell.tint-mercury{ --tf-tint:#9ad0c4; border-left-color:#9ad0c4 }   /* quicksilver teal */
.tf-cell.tint-venus  { --tf-tint:#e6a3c8; border-left-color:#e6a3c8 }   /* rose */
.tf-sheet.tint-mercury{ border-left-color:#9ad0c4 } .tf-sheet.tint-venus{ border-left-color:#e6a3c8 }
.tf-cell.tint-mercury .tf-fill,.tf-sheet.tint-mercury .tf-fill{ background:linear-gradient(90deg,#9ad0c4,var(--gold,#ffd98a)) }
.tf-cell.tint-venus .tf-fill,.tf-sheet.tint-venus .tf-fill{ background:linear-gradient(90deg,#e6a3c8,var(--gold,#ffd98a)) }
.tf-bg-rx-main{ position:absolute; top:-4px; right:-4px; width:21px; height:21px; border-radius:50%;
  display:flex; align-items:center; justify-content:center; background:var(--bg,#15102b);
  font-weight:700; font-size:13px; line-height:1; font-family:inherit; font-style:normal; color:var(--gold,#ffd98a); box-shadow:inset 0 0 0 1.5px currentColor; }
.tf-cell.is-soon .tf-bg-rx-main{ color:var(--hint,#9b91c4) }              /* muted while pre-shadow/upcoming */
.tf-cell.is-retro .tf-bg-rx-main{ box-shadow:inset 0 0 0 2px currentColor }   /* active retrograde: bolder ring */
.tf-chip.is-retro{ color:var(--gold,#ffd98a); background:rgba(255,217,138,.12) }
.tf-chip.is-retro .tf-arw{ width:13px; height:13px }

/* ════ compat picker — computed scores on the mode tabs + the centre focal score-ring (design team) ════ */
.compat-screen .line-opt{ position:relative; }
.compat-screen .lo-lbl{ display:block; max-width:100%; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.compat-screen .lo-pip{ position:absolute; top:6px; right:8px; font-weight:800; font-size:12px; line-height:1; font-family:inherit;
  color:var(--lt); background:var(--lt-soft); border:1px solid var(--line); border-radius:999px; padding:1px 7px; }
/* DES-1 (R9): the owned ✓ line-pip reads as unlocked/good, not a neutral score chip */
.compat-screen .lo-pip.owned{ color:var(--good); background:rgba(91,227,167,.16); border-color:rgba(91,227,167,.4); }
.compat-screen .lo-spark{ position:absolute; top:6px; right:8px; font-size:11px; opacity:.5; transition:opacity .14s linear; }
/* ПОД ПОДСВЕТКОЙ ТАКТА «СОВМЕСТИМОСТЬ» ✨ ГАСНЕТ — решение, а не инерция. Формально
   запрет концепта касается замка и ✦ (.lo-spark ими не является: тап по такой линии
   зовёт setCompatLine, а не paywall), но у свежего пользователя с двумя профилями в
   окне света ровно два жёлтых спарка, и это единственное жёлтое пятно внутри фиолетовой
   подсветки во всём туре — при том, что в продукте золото = премиум. Плюс ✨ говорит
   «по этой линии ещё нет результата», то есть спорит с репликой такта («это три разных
   ответа») за одни и те же две секунды. Гашение обратимо и живёт ровно один такт: класс
   на <body> ставит tourStepClass, снимает tourEnd. Опасити, а не display — метка не
   двигает вёрстку опции. */
body.tour-at-compat .compat-screen .lo-spark{ opacity:0; }
.compat-screen .pick-row{ gap:6px; }
/* the ONE focal figure between the two person cards */
.compat-screen .pick-score{ position:relative; flex:0 0 84px; width:84px; height:84px; display:flex; align-items:center; justify-content:center; }
.compat-screen .pick-score::before{ content:""; position:absolute; inset:-8px; border-radius:50%; z-index:-1;
  background:radial-gradient(circle, var(--lt-glow) 0%, transparent 70%); }
.compat-screen .pick-score.ghost::before{ background:none; }
.compat-screen .pick-score svg{ position:absolute; inset:0; transform:rotate(-90deg); }
.compat-screen .ps-fg{ stroke-dashoffset:226; animation:ring-fill .7s cubic-bezier(.22,.9,.3,1) forwards; }
.compat-screen .ps-mid{ position:relative; display:flex; flex-direction:column; align-items:center; justify-content:center; gap:1px; }
.compat-screen .ps-num{ font-size:26px; font-weight:900; line-height:1;
  background:linear-gradient(135deg,#ffd166,#ffd98a); -webkit-background-clip:text; background-clip:text;
  -webkit-text-fill-color:transparent; color:#ffd166; }
.compat-screen .ps-num.ps-check{ background:none; -webkit-text-fill-color:var(--good,#5be3a7); color:var(--good,#5be3a7); font-size:24px; }
.compat-screen .ps-bkt{ font-size:8px; font-weight:800; text-transform:uppercase; letter-spacing:.05em;
  opacity:0; animation:ps-bkt-in .18s ease .55s forwards; }
@keyframes ps-bkt-in{ from{ opacity:0; transform:translateY(4px); } to{ opacity:1; transform:translateY(0); } }
.compat-screen .pick-score.ghost .ps-mid{ animation:ps-pulse 2s ease-in-out infinite; }
.compat-screen .pick-score.ghost .ps-motif{ font-size:20px; opacity:.5; }
.compat-screen .pick-score.ghost .ps-q{ font-size:13px; font-weight:800; color:var(--hint,#9b91c4); }
@keyframes ps-pulse{ 0%,100%{ opacity:.6; } 50%{ opacity:1; } }
@media (prefers-reduced-motion:reduce){
  .compat-screen .ps-fg{ animation:none; stroke-dashoffset:var(--off); }
  .compat-screen .ps-bkt{ animation:none; opacity:1; }
  .compat-screen .pick-score.ghost .ps-mid{ animation:none; }
}

/* ════════════ 14-DAY «ЛУННАЯ ДУГА» forecast (concept/design/ТЗ: FORECAST14_*.md) ════════════ */
/* element tokens SCOPED to the block (never a document-wide :root override) — air is blue, not gold,
   so it can't collide with the reserved lunation/illum gold */
.f14-block{ margin:14px 0 6px; --el-fire:#ff8a6b; --el-earth:#9ad0c4; --el-air:#8fb8ff; --el-water:#b0a0ff; }
.sr-only{ position:absolute; width:1px; height:1px; padding:0; margin:-1px; overflow:hidden; clip:rect(0,0,0,0); white-space:nowrap; border:0; }
.f14-narr{ display:flex; align-items:center; gap:7px; font-size:13.5px; font-weight:700; color:var(--text); margin:0 2px 10px; }
.f14-narr .f14-nmoon{ color:var(--gold,#ffd166); font-size:15px; }
/* the scroll object: arc stacked over rail, both 660px, scroll in lockstep */
.f14-scroll{ overflow-x:auto; overflow-y:hidden; -webkit-overflow-scrolling:touch; touch-action:pan-x pan-y;
  overscroll-behavior-x:contain; scroll-snap-type:x proximity; scrollbar-width:none; border-radius:16px;
  background:linear-gradient(180deg, rgba(179,136,255,.06), transparent); padding:6px 0 2px; }
.f14-scroll::-webkit-scrollbar{ display:none; }
/* ═══════════════ КОНЦЕПТ «НЕБО ЗА КРИВОЙ» ═══════════════
   Поле графика — кусок ночного неба, а не пустая плоскость.
   ДЕФЕКТ ПОЧИНЕН: было height:120px при viewBox "0 0 660 132" + preserveAspectRatio="none" —
   весь график сжимался по вертикали на 9%, узлы рисовались эллипсами, толщины обводок врали.
   Теперь 132px и viewBox 1:1; preserveAspectRatio снят в разметке.
   ЗАПРЕТ: в этом блоке нет ни одного filter/drop-shadow/blur — свечение даёт вторая широкая
   полупрозрачная обводка и градиенты <defs>. Анимируются только opacity и transform. */
.f14-arc{ display:block; position:relative; z-index:1; width:660px; height:132px; }
/* НЕБО — отдельный слой ПОД дугой. Он не входит в .f14-arc намеренно: dockDay переклеивает дугу
   на каждый тап, и бесконечный дрейф звёзд стартовал бы заново, дёргая поле под пальцем.
   И это HTML-БОКС, а не один <svg>: ложе лежит статичной подложкой, а две копии звёздного поля
   едут внутри .f14-drift. Виньетки по краям (26px в цвет ложа) переехали сюда же из <rect> с
   градиентами — всё, что не звёзды, не должно копироваться вместе с полем. */
.f14-sky{ display:block; position:absolute; left:0; top:0; z-index:0; width:660px; height:132px;
  overflow:hidden; pointer-events:none; }
.f14-sky-bed{ display:block; position:absolute; left:0; top:0; width:660px; height:132px; }
.f14-sky::after{ content:""; position:absolute; inset:0; pointer-events:none;
  background:linear-gradient(90deg,#1a1434 0,rgba(26,20,52,0) 26px),
             linear-gradient(270deg,#1a1434 0,rgba(26,20,52,0) 26px); }
.f14-sky-st{ fill:#dfe6ff; }
/* ДРЕЙФ ВПРАВО — «всё движется в правую сторону, в будущее» (основатель). Очень медленно: 120с на
   полный оборот поля. Бесшовность: две одинаковые копии поля лежат встык (обёртка сдвинута на −660),
   и на последнем кадре копия A встаёт ровно туда, где копия B стояла на первом.
   ДРЕЙФ ЕДЕТ НА HTML-БОКСЕ, А НЕ НА SVG-ГРУППЕ. Замер: transform на <g> Blink композитору не отдаёт
   — получался ПОЛНЫЙ layout поддерева неба каждый кадр (300 Layout за 5 с против 2 без дрейфа,
   и он не прекращался, даже когда блок уезжал за экран). На блочном боксе тот же transform уходит
   в слой композитора: 0 layout. Идиома в проекте уже есть (.onb-spin, .fcw-rotor). */
@keyframes f14drift{ from{ transform:translateX(0); } to{ transform:translateX(660px); } }
.f14-drift{ position:absolute; left:-660px; top:0; width:1320px; height:132px; display:flex;
  animation:f14drift 120s linear infinite; }
.f14-sky-f{ display:block; flex:none; width:660px; height:132px; }
/* тихое мерцание — ДВЕ ГРУППЫ звёзд в противофазе вместо 24 персональных анимаций (те давали
   24 микрослоя композитора 2×2 px и пересчёт стиля каждый кадр). Яркость звезды остаётся её
   собственной: opacity узла перемножается с opacity группы, поэтому в кейфреймах чистые литералы
   и никакого calc(var(--o)*…) на каждый кадр. */
.f14-tw{ animation:f14tw 9s ease-in-out infinite; }
.f14-tw.b{ animation-delay:-4.5s; }
@keyframes f14tw{ 0%,100%{ opacity:1; } 50%{ opacity:.4; } }
/* ПАУЗА ВНЕ ВЬЮПОРТА (класс ставит IntersectionObserver, f14SkyWatch). Браузер небо не троттлит:
   за экраном оно стоило ровно столько же. paused замораживает кадр, а не сбрасывает дрейф. */
.f14-sky.f14-off .f14-drift, .f14-sky.f14-off .f14-tw{ animation-play-state:paused; }

/* КРИВАЯ: три прохода одним путём — «стеклянная трубка с раскалённой нитью».
   Дальний пояс = рост ШИРИНЫ при удержании яркости ядра (ширина означает неуверенность),
   а не затухание, которое читалось бы как выдуманное падение достоверности. */
.f14-halo,.f14-body,.f14-thread{ fill:none; stroke-linecap:round; stroke-linejoin:round; }
.f14-halo{ stroke-width:7; opacity:.13; }
.f14-halo.far{ stroke-width:13; opacity:.07; }
.f14-body{ stroke-width:3.2; opacity:.55; }
.f14-thread{ stroke-width:1.3; opacity:.9; }
.f14-thread.far{ stroke-width:.9; }
/* ШТРИХ-ПОДПИСЬ метрики поверх нити: у любви длинный пунктир, у карьеры точки, у энергии ничего
   (сплошная — её знак). Второй, НЕЦВЕТОВОЙ признак кривой: при дейтеранопии энергия и карьера
   различаются на 31 по RGB, то есть не различаются никак (WCAG 1.4.1). Рисунок штриха повторён
   в полосе-свидетеле гнезда. Отдельный проход, потому что сама нить занята dasharray проявления. */
.f14-tex{ fill:none; stroke-linecap:round; stroke-linejoin:round; stroke-width:2; opacity:.85; }
.f14-tex.far{ stroke-width:1.7; opacity:.7; }
.f14-fill{ stroke:none; }
/* ВХОД — буквально .fcr-arc колец: .9s cubic-bezier(.22,.9,.3,1), база анимации = финальный кадр.
   Переключение метрики — не перерисовка, а проявление (.22s opacity). */
@keyframes f14draw{ from{ stroke-dashoffset:1; } }
@keyframes f14fade{ from{ opacity:0; } }
.f14-arc .f14-halo,.f14-arc .f14-body,.f14-arc .f14-thread{
  stroke-dasharray:1; stroke-dashoffset:0; animation:f14draw .9s cubic-bezier(.22,.9,.3,1) both; }
.f14-arc .f14-fill,.f14-arc .f14-tex{ animation:f14fade .9s ease both; }
.f14-mgroup{ animation:f14fade .22s ease both; }
/* СМЕНА ДНЯ — НЕ ПОВТОРНЫЙ ВХОД. Класс вешает dockDay на переклеенную дугу: проявление
   кривых играется один раз, при появлении блока на экране, иначе каждый тап по дню
   перечерчивал все три линии заново и это читалось как моргание. */
.f14-arc.f14-noanim .f14-halo, .f14-arc.f14-noanim .f14-body, .f14-arc.f14-noanim .f14-thread,
.f14-arc.f14-noanim .f14-fill, .f14-arc.f14-noanim .f14-tex, .f14-arc.f14-noanim .f14-mgroup{
  animation:none; }
/* Разбор дня на время запроса не стирается, а гаснет — видно, что он устарел и обновляется. */
#fc-below.fc-below-stale{ opacity:.45; transition:opacity .16s ease; }
/* УЗЛЫ — голова дуги кольца «Орбиты дня», переведённая со stroke на fill.
   Обводка ядра — цвет ЛОЖА НЕБА (#1a1434), а не карточки: узлы теперь стоят на небе. */
.f14-node-o{ stroke:none; opacity:.16; }
.f14-node-i{ stroke:#1a1434; stroke-width:1.6; }
.f14-node-c{ stroke:none; }
/* ПЛЕЙХЕД = ось этого прибора: идиома оси Asc/MC натального колеса (.fcw-axis, dasharray 5 6) */
.f14-ph-bed{ stroke:var(--accent,#b388ff); stroke-width:7; opacity:.10; stroke-linecap:round; }
.f14-ph{ stroke:rgba(255,255,255,.45); stroke-width:1.2; }   /* сплошной: основатель 2026-08-04 */
.f14-tick{ stroke-width:2; stroke-linecap:round; opacity:.45; }
.f14-tick.el-fire{ stroke:var(--el-fire); } .f14-tick.el-earth{ stroke:var(--el-earth); }
.f14-tick.el-air{ stroke:var(--el-air); } .f14-tick.el-water{ stroke:var(--el-water); }
/* ═══════════════════════════════════════════════════════════════════════════════
   ВЧЕРА / СЕГОДНЯ / ЗАВТРА — тот же прибор, что шкалы сфер: три гнезда, свет стоит
   в одном. Композиция обязана читаться как ОДНА СЕМЬЯ с «Орбитой дня» (.fcr-*) и
   натальным колесом (.fcw-*), между которыми она физически зажата.

   ТОКЕН ИСПРАВЛЕН: MAGENTA УБРАНА ЦЕЛИКОМ. --accent2 #ff7eb6 в этом продукте
   означает ВРЕМЯ И ДЕФИЦИТ (#promo-timer, .pw-chip-save, .fcw-aspect.tense).
   «Сегодня» — не дефицит, это позиция указателя; активная плашка кричала «сгорит».
   Свет несёт ФИОЛЕТ — тело интерфейса.
   ЗОЛОТА НА ПЛАШКАХ НЕТ НИ ПИКСЕЛЯ: это бесплатная поверхность, а золото в продукте
   означает ценность/премиум. Золото осталось только на градуировке шкалы и на замке.
   ТЁМНЫЕ ЧЕРНИЛА #1a1030 НА ФИОЛЕТЕ — это КАНОН сегмент-контрола продукта
   (.seg-opt.sel, styles.css ~2130), а не грамматика золотой печати: два сегмент-
   контрола приложения обязаны говорить на одном языке.

   transition для background/box-shadow УДАЛЁН НЕ ТОЛЬКО ПОТОМУ, ЧТО ЭТО PAINT:
   он не срабатывал НИКОГДА — fcBelowUpdate переклеивает host.innerHTML, и узел
   рождается заново уже с классом .on. Значит подтверждение тапа сегодня отсутствует
   вовсе, и дать его можно ТОЛЬКО одноразовой анимацией на свежерождённом узле.
   ═══════════════════════════════════════════════════════════════════════════════ */
.f14-quick{ position:relative; display:flex; gap:3px; margin:0 0 7px; padding:0;
  background:none; border:0; border-radius:0; }

/* ГНЕЗДО. Было rgba(255,255,255,.035) — «еле заметно» у одного из ТОП-элементов
   по тапам. Стало — тот же канал, что жёлоб шкалы двумястами пикселями ниже:
   тёмное дно, свет сверху, губа снизу.
   ГЕОМЕТРИЯ КОМПЕНСИРОВАНА ДО ПИКСЕЛЯ: было min-height 26 + margin 9 = 35;
   стало min-height 28 + margin 7 = 35. Окно света такта колец в туре «Проводник»
   НЕ ДВИГАЕТСЯ.
   flex-центрирование + 12px/1.15 + overflow-wrap чинят ЖИВОЙ дефект: при line-height:1
   перенос («Aujourd'hui», деванагари, «Keberuntungan») схлопывает строки друг на
   друга и режет верхние матры.
   transition ТОЛЬКО transform — единственное, что здесь физически может сработать
   (узел живёт от перерисовки до перерисовки). */
.f14-qseg{
  position:relative; z-index:0; overflow:hidden; flex:1; min-height:28px; padding:6px 4px;
  display:flex; align-items:center; justify-content:center; text-align:center;
  overflow-wrap:anywhere; hyphens:auto;
  border:0; border-radius:8px; cursor:pointer;
  /* ШОРТКАТ font: ЗДЕСЬ НЕВАЛИДЕН И ВЫБРАСЫВАЛСЯ ЦЕЛИКОМ. `inherit` разрешён только как
     значение ВСЕГО свойства, а не как семейство внутри шортката, — движок отбрасывал всю
     декларацию, и плашки годами рисовались системным Arial 400/13.33px вместо задуманного
     700/12px (замер getComputedStyle: fontWeight 400, fontFamily Arial). Баг предсуществующий,
     не регрессия этого редизайна, но чинится здесь: типографика — половина вида этих кнопок.
     Тот же дефект живёт ещё в 7 местах файла (grep 'font:.*inherit') — вынесено отдельно. */
  font-weight:700; font-size:12px; line-height:1.15; font-family:inherit;
  letter-spacing:.01em; color:var(--hint,#9b91c4);
  background:
    radial-gradient(130% 170% at 50% -30%, rgba(255,255,255,.06) 0%, rgba(255,255,255,0) 60%),
    linear-gradient(180deg,#1b1536 0%,#151030 100%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.035), inset 0 -1px 0 rgba(0,0,0,.30);
  transition:transform .1s ease;
}

/* СВЕТ СТОИТ В ЭТОМ ГНЕЗДЕ. Скин на ::before, а не на самом фоне кнопки: так база
   не трогается, а появление скина — чистый opacity (композитор), а не перекраска.
   ТРИ СЛОЯ:
     1 кремовая кромка 1px — ТОТ ЖЕ сигнал «здесь стоит свет», что кромка отлива
       и кремовое гало мениска на шкалах ниже. Один язык на весь экран;
     2 фирменная формула света 30%/24% — та же, что атмосфера кольца и .pers-gauge;
     3 фиолетовый цилиндр. Нижний стоп #9a6fe4 выбран ПО КОНТРАСТУ: чернила #1a1030
       на нём дают 4.98:1 (AA для 12px/700 = 4.5), на середине #a97ff0 — 6.0:1.
       Темнее не делать: на #8b60d8 получается 4.1:1 и AA рушится. */
.f14-qseg::before{
  content:""; position:absolute; z-index:-1; inset:0; border-radius:8px; opacity:0;
  pointer-events:none;
  background:
    linear-gradient(180deg, rgba(255,243,214,.55) 0 1px, rgba(255,243,214,0) 1px),
    radial-gradient(130% 170% at 30% 24%, rgba(255,255,255,.22) 0%, rgba(255,255,255,0) 62%),
    linear-gradient(180deg,#bfa0ff 0%,#a97ff0 54%,#9a6fe4 100%);
}
.f14-qseg.on{ color:#1a1030; }
.f14-qseg.on::before{ opacity:1; animation:fq-seat .22s cubic-bezier(.33,1,.68,1) both; }

/* ПЕРЕЛИВ — ровно ОДИН проход при каждой смене дня, 900 мс, один узел на весь экран.
   transform-слой под overflow:hidden (канон .promo-clip::after, уже узаконенный НА
   ЭТОМ ЖЕ экране), а НЕ background-position: анимация paint дорога на дешёвом Android.
   JS не нужен: dockDay пересобирает карточку, узел рождается заново → проход играет
   ровно один раз и читается как «свет перешёл сюда».
   БАЗА = ФИНАЛ: покой = полоса уже за правым краем. */
.f14-qseg.on::after{
  content:""; position:absolute; top:-30%; bottom:-30%; left:-45%; width:34%;
  pointer-events:none;
  background:linear-gradient(100deg, rgba(255,255,255,0) 0%, rgba(255,255,255,.26) 50%, rgba(255,255,255,0) 100%);
  transform:translateX(430%) skewX(-16deg);
  animation:fq-sheen .9s cubic-bezier(.33,1,.68,1) .06s 1 both;
}

/* ТАП. Было filter:brightness(1.06) — ПРЯМОЙ ЗАПРЕТ ПЕРФ-ДОКТРИНЫ (filter на дешёвом
   WebView снимает поддерево с композитора). Канон продукта:
   .rings .ring-item:active .ring-wrap{scale(.95)}, .pw-cta:active{scale(.98)}. */
.f14-qseg:active{ transform:scale(.965); }

/* ЧЕТВЁРТОЕ СОСТОЯНИЕ — ДАЛЬНИЙ ДЕНЬ: указатель ушёл с ближней шкалы, ни одна плашка
   не активна (dockDay пейволит только off>=2, у самих плашек премиум-состояния нет
   и быть не должно). Раньше это были три одинаково мёртвые пилюли, не сообщавшие
   ничего. Класс идёт на КОНТЕЙНЕР: первый class-токен кнопки остаётся "f14-qseg",
   аналитика el.f14-qseg (ТОП-элемент по тапам) не задета; "q-far" не пересекается
   ни с одним именем из most-specific-списка analytics.js.
   Гнёзда становятся ЯРЧЕ, а не тусклее: это единственный путь назад.
   Фиолетовая (НЕ золотая — поверхность бесплатная) линия-намёк живёт в отрицательном
   bottom, высоту ряда не меняет. Ноль новых i18n-строк. */
.f14-quick.q-far .f14-qseg{
  background:
    radial-gradient(130% 170% at 50% -30%, rgba(255,255,255,.09) 0%, rgba(255,255,255,0) 60%),
    linear-gradient(180deg,#241d47 0%,#1c1638 100%);
  color:#bcb2e0;
}
.f14-quick.q-far::after{
  content:""; position:absolute; left:6px; right:6px; bottom:-3px; height:1px; pointer-events:none;
  background:linear-gradient(90deg, rgba(179,136,255,0), rgba(179,136,255,.28), rgba(179,136,255,0));
}

/* 320px: карточка внутри 256px − gap 6 = 83.3px на сегмент − padding 8 = поле 75.3px.
   «Aujourd'hui» ≈73px — на грани. Страховка кеглем на самых узких: поле 79.3px при
   11px → ≈67px, влезает в одну строку. Ряд физически не может сломаться (flex +
   align-items:stretch держит три сегмента одной высоты), может только вырасти. */
@media (max-width:359px){
  .f14-qseg{ font-size:11px; padding:6px 2px; letter-spacing:0; }
}

@keyframes fq-seat { from{ opacity:0; } }                              /* to = база = 1 */
@keyframes fq-sheen{ from{ transform:translateX(0) skewX(-16deg); } }  /* to = база = за краем */

/* ═══ REDUCED-MOTION ДЛЯ ОБОИХ ЭЛЕМЕНТОВ (шкалы сфер + плашки дней) — ОДИН
   медиазапрос, и он стоит ЗДЕСЬ намеренно: он обязан идти ПОЗЖЕ обоих блоков,
   иначе `.f14-qseg{transition:none}` перебивается собственным поздним объявлением
   (одинаковая специфичность, побеждает последнее).
   Это не «выключено», а СПРОЕКТИРОВАННЫЙ СТОП-КАДР С КОМПЕНСАЦИЕЙ СТАТИКОЙ (приём
   .fcr-halo{opacity:calc(var(--halo)+.06)}): картинка добирает статикой ровно то,
   что потеряла в динамике. Работает потому, что БАЗА = ФИНАЛ у всех трёх анимаций —
   снятие анимации оставляет ПРАВИЛЬНЫЙ кадр. ═══ */
@media (prefers-reduced-motion:reduce){
  #focus-more .aspect .bar::after, #fc-far-more .aspect .bar::after,
  .f14-qseg.on::before, .f14-qseg.on::after{ animation:none !important; }
  .aspect-row::before{ transition:none; }
  .f14-qseg{ transition:none; }
  /* компенсация */
  .aspect .bar > i{ --core-w:13px; --core-a:.42; }    /* мениск ярче: граница показания читается сильнее */
  .f14-quick.q-far::after{ background:linear-gradient(90deg, rgba(179,136,255,0), rgba(179,136,255,.36), rgba(179,136,255,0)); }
}

/* the rail — a LUNAR TIMELINE: a faint track threads the moon-phase glyphs (sky above) over each day's date;
   near days (yesterday/today/tomorrow) read prominent, key sky days (new/full/ingress) carry a gold ★. */
/* ГОРИЗОНТ. .f14-baseline снесена: нижняя линия графика — это верхняя кромка ленты, и обе линии
   компонента наконец нарисованы одной рукой (дословно рецепт соседней ::before). */
.f14-rail{ display:flex; width:660px; margin-top:0; position:relative; }
.f14-rail::after{ content:""; position:absolute; left:0; right:0; top:0; height:1px; z-index:0;
  background:linear-gradient(90deg, transparent, rgba(179,136,255,.22) 8%, rgba(179,136,255,.22) 92%, transparent); }
/* the whisper baseline that ties the days into one journey (sits at the moon-glyph row) */
.f14-rail::before{ content:""; position:absolute; left:26px; right:26px; top:20px; height:1px; z-index:0;
  background:linear-gradient(90deg, transparent, rgba(179,136,255,.28) 10%, rgba(179,136,255,.28) 90%, transparent); }
/* ОСНОВАТЕЛЬ: «слова и числа прилипли к линии» — колонка получила воздух сверху (10px вместо 6),
   так что лунный ряд отходит от кромки горизонта, а день с подписью — от лунной нити. */
.f14-col{ flex:0 0 44px; width:44px; scroll-snap-align:center; display:flex; flex-direction:column; align-items:center; gap:1px;
  padding:10px 0 8px; background:none; border:0; color:var(--hint,#9b91c4); cursor:pointer; position:relative; z-index:1; }
.f14-col .f14-wd{ font-size:9.5px; text-transform:uppercase; letter-spacing:.03em; opacity:.7; }
.f14-col .f14-dn{ font-size:15px; font-weight:700; color:var(--text); line-height:1.1; }
/* ФАЗЫ ЛУНЫ РИСУЕМ МЫ (см. f14MoonSvg) — вместо эмодзи из чужого шрифта, который на Android
   приходит из системного набора с другими метриками и чужой палитрой. Подложка-диск, «разрывающая»
   лунную нить за глифом, остаётся ровно как была. */
.f14-col .f14-mg{ position:relative; height:20px; min-width:20px; display:inline-flex; align-items:center; justify-content:center;
  font-size:13px; line-height:1; margin-bottom:3px; opacity:.55; border-radius:50%;
  background:radial-gradient(circle, var(--bg,#15102b) 60%, transparent 72%); }
.f14-moonsvg{ display:block; width:20px; height:20px; overflow:visible; }
.f14-col.near .f14-mg{ opacity:1; font-size:16px; }
.f14-col.key .f14-mg{ opacity:1; box-shadow:0 0 0 1px rgba(255,217,138,.35), 0 0 8px -1px rgba(255,217,138,.45); }
.f14-legg .f14-moonsvg{ width:24px; height:24px; display:block; }
.f14-legg .f14-legstar{ font-style:normal; color:#ffd98a; font-size:15px; text-shadow:0 0 8px rgba(255,217,138,.45); }
.f14-col .f14-mg .f14-star{ position:absolute; top:-3px; right:-4px; font-size:7px; font-style:normal; line-height:1;
  color:var(--gold,#ffd98a); text-shadow:0 0 5px rgba(255,217,138,.8); }
.f14-col.near .f14-wd{ opacity:1; }
.f14-col .f14-wdrow{ display:inline-flex; align-items:center; gap:2px; }
.f14-col .f14-cb{ font-size:9px; line-height:1; }   /* the notable-day marker, right of the weekday */
.f14-col.today .f14-dn{ color:var(--accent,#b388ff); }
.f14-col.today::after{ content:""; position:absolute; bottom:2px; width:16px; height:2px; border-radius:2px; background:var(--accent,#b388ff); }
/* ВЫБРАННЫЙ ДЕНЬ — ФИОЛЕТОВЫЙ, НЕ ЗОЛОТОЙ. Золото в продукте значит «премиум/замок»
   (те же ✦ и .f14-unlock лежат в двух пикселях под этой лентой), и золотая подложка на
   выбранной колонке читалась как «этот день платный» — ровно наоборот смыслу: докнутый
   день это единственный день, который человеку уже открыт. Отдельная цена ошибки: такт
   тура «14 дней» подсвечивает именно эти колонки, а в туре золота нет ни разу. Акцент
   тот же, что у маркера «сегодня» строкой выше, подложка отличает выбор от «сегодня». */
.f14-col.dock{ background:rgba(179,136,255,.14); border-radius:12px; }
.f14-col.dock .f14-dn{ color:var(--accent,#b388ff); }
/* Phase 1a: free far days = CALM DIM (no blur/frost, no lock chrome) — "the days ahead", still tappable
   to the unlock invite. Replaces the old frosted buy-lock columns that read as "hidden content". */
/* Приглушение больше НЕ прозрачностью текста: даты платной дали давали 2.42:1 при требуемых 4.5:1,
   а исключение WCAG для «неактивных» на них не распространяется — колонки кликабельны и ведут в
   пейвол. «Дальше и тише» теперь несут цвет текста (--hint, 5.6:1 против белых 14.3:1 у ближних)
   и приглушённые ГЛИФЫ, а не общая полупрозрачность. */
.f14-col.ahead{ opacity:1; }
.f14-col.ahead .f14-dn{ color:var(--hint,#9b91c4); }
.f14-col.ahead .f14-moonsvg,.f14-col.ahead .f14-ed,.f14-col.ahead .f14-cb{ opacity:.55; }
/* MIN-9: a non-self chart's far days are always free (self-only content, nothing to buy) — a
   plain dim, NOT the frosted buy-lock chrome above (no blur, no seam, no aria-disabled). */
.f14-col.selfonly{ opacity:1; }   /* тот же разбор контраста, что у .ahead выше */
.f14-col.selfonly .f14-dn{ color:var(--hint,#9b91c4); }
.f14-col.selfonly .f14-moonsvg,.f14-col.selfonly .f14-ed,.f14-col.selfonly .f14-cb{ opacity:.55; }
/* seam marker at the free→locked rail boundary (legacy frost-era chrome — Phase 1a calm dim renders no seam) */
.f14-col .f14-seam{ position:absolute; left:-9px; top:50%; transform:translateY(-50%); font-size:12px; z-index:2; filter:none; opacity:1; }
/* docked card */
.f14-card{ margin-top:12px; padding:13px 15px; border-radius:16px; background:var(--card,#221a3d); border:1px solid rgba(255,255,255,.05); }
.f14-dh{ font-size:15px; font-weight:800; color:var(--text); }
.f14-moon{ font-size:12.5px; color:var(--hint,#9b91c4); margin:3px 0 9px; }
.f14-energy{ font-size:13px; color:var(--hint,#9b91c4); margin-bottom:8px; }
.f14-energy b{ font-size:20px; font-weight:900; }
.f14-rings{ display:flex; flex-wrap:wrap; gap:6px; }
.f14-mini{ font-size:11.5px; font-weight:700; padding:2px 8px; border-radius:999px; background:rgba(255,255,255,.05); }
.f14-mini.b-high{ color:var(--good,#5be3a7); } .f14-mini.b-mid{ color:var(--warn,#ffd166); } .f14-mini.b-low{ color:var(--hint,#9b91c4); }
.b-high{ color:var(--good,#5be3a7); } .b-mid{ color:var(--warn,#ffd166); } .b-low{ color:var(--bad,#ff6b8a); }
.f14-be{ font-size:12px; color:var(--hint,#9b91c4); margin-top:8px; }
.f14-be.muted{ opacity:.7; }
.f14-cband{ font-size:14px; font-weight:700; color:var(--text); }
.f14-cev{ font-size:12.5px; color:var(--gold,#ffd98a); margin-top:6px; }
.f14-orient{ font-size:11.5px; color:var(--hint,#9b91c4); opacity:.75; margin-top:8px; font-style:italic; }
.f14-locked{ font-size:13px; color:var(--hint,#9b91c4); text-align:center; padding:8px 0; }
/* free teaser */
/* compact unlock strip INSIDE the graph card footer (no separate card / no wasted gap) */
.f14-teaser{ padding:10px 14px 12px; margin-top:2px; border-top:1px solid rgba(255,255,255,.05); }
.f14-cta{ margin:0; }
/* Variant B2 unlock ribbon — full-width, flush to the bottom of the spine card (the card clips it round) */
.f14-unlock{ display:flex; align-items:center; justify-content:center; gap:6px; width:100%; box-sizing:border-box;
  min-height:44px; margin-top:2px; padding:12px 14px; border:0; border-top:1px solid rgba(179,136,255,.22);
  background:linear-gradient(90deg, rgba(179,136,255,.20), rgba(255,180,90,.14)); color:var(--text,#e6d5ff);
  font-weight:700; font-size:12.5px; line-height:1.2; font-family:inherit; letter-spacing:.02em; cursor:pointer; }
/* filter:brightness(1.08) снесён — тот же запрет доктрины, что и на .f14-qseg:active,
   и та же карточка. Подтверждение тапа даёт transform (композитор). */
.f14-unlock:active{ transform:scale(.985); transition:transform .1s ease; }
/* REDUCED-MOTION: не «выключено», а спроектированный СТОП-КАДР. Дрейф и мерцание снимаются,
   финальный кадр остаётся полным (звезда стоит на своей штатной яркости), а потерю жизни
   компенсирует статика — ореол кривой ярче ровно на .04 (приём .fcr-halo колец). */
@media (prefers-reduced-motion:reduce){
  .f14-drift, .f14-tw{ animation:none !important; transform:none !important; }
  .f14-tw{ opacity:1; }
  .f14-arc .f14-halo,.f14-arc .f14-body,.f14-arc .f14-thread,.f14-arc .f14-fill,.f14-arc .f14-tex,
  .f14-mgroup,.f14-mchip b.flip{ animation:none !important; }
  .f14-mchip,.f14-mchip::before,.f14-mchip::after{ transition:none; }
  .f14-halo{ opacity:.17; } .f14-halo.far{ opacity:.11; }
}
/* QA fixups: 44px tap targets, WCAG-AA contrast (drop opacity dimmers), gender-free bucket bar */
.f14-cta{ min-height:44px; display:flex; align-items:center; justify-content:center; }
.f14-col{ min-height:44px; }
.f14-col .f14-wd{ opacity:1; color:var(--hint,#9b91c4); }
.f14-orient{ opacity:1; color:var(--hint,#9b91c4); }
.f14-lvl{ font-size:12px; letter-spacing:1px; }
.f14-lvl, .f14-mini.b-high .f14-lvl{ color:inherit; }
.f14-col .f14-ed{ width:5px; height:5px; border-radius:50%; margin-top:2px; background:var(--hint,#9b91c4); }
.f14-col .f14-ed.b-high{ background:var(--good,#5be3a7); } .f14-col .f14-ed.b-mid{ background:var(--warn,#ffd166); } .f14-col .f14-ed.b-low{ background:var(--hint,#9b91c4); }

/* ═══════ 14-DAY UX2 «Spine v2» — labeled energy line, per-day below, legible markers (founder feedback) ═══════ */
.f14-arc{ pointer-events:none; }   /* the SVG never traps the drag — the catcher above it takes the tap */
/* the tap catcher: a transparent layer over the curve that docks the tapped day (arcTap), while the
   curve itself stays pointer-events:none so a horizontal drag of the fortnight keeps working. The
   catcher does NOT set touch-action, so .f14-scroll's pan-x/pan-y still owns every drag. */
.f14-arcwrap{ position:relative; width:660px; }
.f14-arctap{ position:absolute; left:0; right:0; top:0; bottom:0; background:transparent; cursor:pointer; }
/* sticky axis label (never scrolls): word in the spark's violet, value gold — "this line is ЭНЕРГИЯ" */
.f14-axis{ display:flex; align-items:baseline; gap:5px; margin:2px 2px 4px; font-size:12px; font-weight:700; }
.f14-axis-k{ color:var(--accent,#b388ff); letter-spacing:.04em; }
.f14-axis-dot{ color:var(--accent,#b388ff); font-size:10px; }
.f14-axis b{ color:var(--gold,#ffd166); font-size:16px; font-weight:900; }
.f14-yhint{ display:flex; justify-content:space-between; margin:-2px 4px 2px; font-size:9px; color:var(--hint,#9b91c4); opacity:.7; text-transform:uppercase; letter-spacing:.05em; }
/* the energy node at the docked day — a concrete point at your finger */
/* phase-emoji moons (obviously a moon) + shaped glyph pins */
.f14-moon-g{ font-size:9px; }
.f14-moon-g.ecl{ fill:#e58bad; }   /* drop-shadow снят — перф-доктрина; затмение отличает цвет, не свечение */
.f14-gpin{ font-size:11px; font-weight:700; }
.f14-gpin.peak{ fill:var(--warn,#ffd166); }
.f14-gpin.rest{ fill:var(--hint,#9b91c4); }
.f14-gpin.k-best_love{ fill:var(--accent2,#ff7eb6); } .f14-gpin.k-best_work{ fill:#7ec8ff; }
/* docked echo + handoff + precision chip */
.f14-echo{ margin-top:8px; font-size:12.5px; font-weight:600; color:var(--gold,#ffd98a); }
.f14-echo.k-rest{ color:var(--hint,#9b91c4); } .f14-echo.k-eclipse{ color:#e58bad; }
.f14-handoff{ display:block; width:100%; margin-top:11px; padding:8px 10px; border-radius:11px; border:1px solid rgba(255,255,255,.07);
  background:rgba(179,136,255,.07); color:var(--accent,#b388ff); font-weight:600; font-size:12px; line-height:1.2; font-family:inherit; cursor:pointer; text-align:center; }
.fc-below-h{ display:flex; align-items:center; justify-content:space-between; }
.f14-prec{ font-size:10.5px; font-weight:700; padding:2px 8px; border-radius:999px; background:rgba(255,255,255,.05); color:var(--hint,#9b91c4); }
.f14-prec.p-A{ color:var(--good,#5be3a7); } .f14-prec.p-B{ color:var(--warn,#ffd166); } .f14-prec.p-C{ color:var(--hint,#9b91c4); }
.fc-sec-sub{ font-size:10.5px; font-weight:600; color:var(--hint,#9b91c4); opacity:.8; margin-left:6px; }
/* mini-legend (only marks present) + ⓘ */
.f14-legend{ display:flex; align-items:center; gap:6px; margin:4px 2px 0; font-size:11px; color:var(--hint,#cdc4e8); }
.f14-leg-items{ flex:1; min-width:0; }
.f14-leg-i{ flex:none; width:22px; height:22px; border:0; background:none; color:var(--accent,#b388ff); font-size:14px; cursor:pointer; }
.f14-legsheet h2{ margin:0 0 12px; font-size:17px; }
.f14-legrow{ display:flex; align-items:center; gap:11px; padding:7px 0; font-size:13.5px; color:var(--text); }
.f14-legg{ width:24px; text-align:center; font-size:15px; }
/* one-time coach-mark */
.f14-teach{ margin:0 0 12px; padding:13px 15px; border-radius:14px; border:1px solid rgba(179,136,255,.25); background:linear-gradient(180deg, rgba(179,136,255,.09), rgba(255,217,138,.04)); }
.f14-teach-b{ font-size:12.5px; color:var(--text); margin-bottom:6px; }
.f14-teach-row{ display:flex; align-items:center; justify-content:space-between; margin-top:6px; }

/* ═══════ 14-DAY «MINIMAL SPINE CARD» — clean upper block + folded day header (founder visual polish) ═══════ */
.f14-spine{ margin:14px 0 12px; padding:0; border:1px solid rgba(255,255,255,.06); border-radius:18px; overflow:hidden;
  background:linear-gradient(180deg, rgba(179,136,255,.05), rgba(21,16,43,0)), var(--card,#221a3d); }
.f14-spine-top{ display:flex; justify-content:space-between; align-items:center; gap:8px; padding:10px 12px 8px; }
.f14-spine-k{ font-size:10.5px; font-weight:700; text-transform:uppercase; letter-spacing:.12em; color:var(--accent,#b388ff); opacity:.85; }
/* ⓘ мерялась 37×41 — единственный интерактив блока ниже порога 44. padding:11px/margin:-11px
   до 44 не добирали; знак остался на месте, выросла только площадь попадания. */
.f14-info{ flex:none; min-width:44px; min-height:44px; padding:0; margin:0 -11px; display:flex;
  align-items:center; justify-content:center; color:var(--accent,#b388ff); font-size:15px; background:none; border:0; cursor:pointer; }
.f14-spine .f14-scroll{ background:none; border-radius:0; padding:2px 0 0; }
/* Число у точки остаётся ТОЛЬКО там, где коллизий нет — на трёх ближних free-днях. Золото снято
   (это бесплатная поверхность, а золото в продукте означает премиум): цвет задаётся инлайном как
   --mc-hi своей кривой. transition:x/y снят — это анимация ГЕОМЕТРИИ, запрещённая доктриной. */
/* Обводка — цвет ЛОЖА НЕБА (#1a1434), а не поверхности карточки (#241c46): числа уехали НА НЕБО,
   и «поверхность карточки» под ними давала светлую плашку на два тона светлее фона — три самых
   ярких пятна левой трети поля. Тем же цветом обведены ядра узлов. */
.f14-nodeval{ font-size:12.5px; font-weight:800; text-anchor:middle; paint-order:stroke; stroke:#1a1434; stroke-width:3;
  font-variant-numeric:tabular-nums; }
.f14-rail{ border-top:0; margin-top:0; padding-top:0; }
/* folded day header in the lower block — the "your tap re-titled the read" cue */
.f14-dayhead{ padding:2px 2px 10px; }
.f14-dayhead .dh-row{ display:flex; align-items:baseline; justify-content:space-between; gap:8px; }
.f14-dayhead .dh-title{ font-size:15.5px; font-weight:800; color:var(--text,#fff); }
.f14-dayhead .dh-row{ flex-wrap:wrap; }
.f14-dayhead .f14-moon{ margin:0; flex:1 1 auto; text-align:right; font-size:12px; color:var(--hint,#9b91c4); min-width:150px; cursor:pointer; }
/* Компакт дальних дней (.rings.sm) переехал в блок «ОРБИТА ДНЯ» (выше, п.17): старая
   версия жила ЗДЕСЬ и никогда не подключалась — разметка не ставила класс `sm`. */
.f14-dayhead .f14-echo{ margin:3px 0 0; }
.f14-dayhead .dh-hr{ height:1px; background:rgba(255,255,255,.06); margin:10px 0 0; }

/* ═══════ ГНЁЗДА-ПОКАЗАНИЯ. Три числа докнутого дня стали самими переключателями метрик:
   единственное место, где три значения на одном x показываются без расталкивания подписей
   (старый LBL_GAP=13 при шкале ≈1 балл на 1 unit врал до 26 единиц). Точка при этом стоит
   ровно на своём y. Скин — тот же, что у сегмент-контрола .f14-qseg: тёмное дно, свет
   сверху, губа снизу; «+/✓» ушли, ON читается светом и полосой-свидетелем. ═══════ */
.f14-metrics{ flex:1 1 auto; min-width:0; display:flex; gap:8px; }
.f14-mchip{
  position:relative; overflow:hidden; flex:1 1 0; min-width:0; min-height:54px;
  display:flex; flex-direction:column; align-items:center; justify-content:center; gap:0;
  /* ОСНОВАТЕЛЬ: «любовь, энергия и карьера прилипли к полосочке» и «слова и числа приподнять
     повыше». Нижняя отбивка 16px против прежних 6: между подписью и полосой-свидетелем теперь
     живой воздух, а не касание. Полоса при этом осталась на своём месте у самого низа гнезда. */
  padding:8px 10px 16px; border:0; border-radius:10px; cursor:pointer;
  font-family:inherit; -webkit-tap-highlight-color:transparent;
  /* СИСТЕМНОЕ УВЕЛИЧЕНИЕ ШРИФТА: без этого подпись раздувалась и резалась НАСУХО, симметрично с
     двух сторон (de KARRIERE на 320px при 2× читалось «ARRIER»), причём пользователь не видел,
     что слово ампутировано. Тот же приём уже стоит на .plan-card и .promo-cap — там OS font-scale
     уже ломал вёрстку в бою. Гнездо — переключатель метрики, теряется не украшение, а его имя. */
  -webkit-text-size-adjust:100%; text-size-adjust:100%;
  background:linear-gradient(180deg,#1b1536 0%,#151030 100%);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.035), inset 0 -1px 0 rgba(0,0,0,.30);
  transition:transform .1s ease; }
/* СВЕТ СТОИТ В ГНЕЗДЕ: скин отдельным слоем на ::before, появление — чистый opacity (композитор),
   а не перекраска фона. Формула источника 30%/24% — та же, что атмосфера кольца «Орбиты дня». */
.f14-mchip::before{ content:""; position:absolute; inset:0; border-radius:10px; opacity:0; pointer-events:none;
  transition:opacity .18s ease;
  background:
    linear-gradient(180deg, var(--mc-edge,rgba(179,136,255,.45)) 0 1px, rgba(255,255,255,0) 1px),
    radial-gradient(130% 170% at 30% 24%, var(--mc-soft,rgba(179,136,255,.22)) 0%, rgba(0,0,0,0) 62%); }
.f14-mchip.on::before{ opacity:1; }
/* ПОЛОСА-СВИДЕТЕЛЬ — буквальный образец штриха своей кривой вместо галочки. --mc-bar приходит
   инлайном и повторяет РИСУНОК штриха метрики (пунктир/точки), а не только её цвет: при
   дейтеранопии цвет энергии и карьеры совпадает, и связь «гнездо ↔ кривая» держит рисунок. */
.f14-mchip::after{ content:""; position:absolute; left:10px; right:10px; bottom:5px; height:2px; border-radius:2px;
  background:var(--mc-bar, var(--mc,#b388ff)); opacity:0; transition:opacity .18s ease; pointer-events:none; }
.f14-mchip.on::after{ opacity:1; }
.f14-mchip b{ display:block; font-size:17px; font-weight:800; line-height:1; letter-spacing:-.3px;
  font-variant-numeric:tabular-nums; color:var(--mc-hi,#efe6ff); }
/* Подпись живёт В СВОИХ ГРАНИЦАХ, а не в min-content: как flex-item при align-items:center она
   сначала вылезала за padding-box, потом за гнездо, и только потом обрезалась — насухо, без
   многоточия. Растянута на ширину гнезда, лишнее честно уходит в «…». */
/* АКЦЕНТЫ ЗАГЛАВНЫХ (витрина fr-FR/02, сборка 40): overflow:hidden (ради «…») резал верх
   строки 1.1 — «ÉNERGIE»/«CARRIÈRE» читались «ENERGIE»/«CARRIERE». 2px сверху ушли из margin в
   padding: акценту есть где жить внутри обрезки, а общая высота гнезда не изменилась. */
.f14-mchip span{ display:block; align-self:stretch; width:100%; min-width:0; margin-top:3px; padding-top:2px;
  font-size:9px; font-weight:700; line-height:1.1; text-align:center;
  text-transform:uppercase; letter-spacing:.09em; white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
  color:var(--mc,#b388ff); }
/* ВЫКЛ: место числа резервируется всегда — ряд не прыгает по высоте, когда метрику гасят.
   ПРОЧЕРК ВМЕСТО СРЕДНЕЙ ТОЧКИ: «·» в 17px рисовалась крапиной 2×2 px цветом метрики при .28
   (≈1.4:1) — на тёмном дне это читалось битым пикселем, а не погашенным показанием. */
.f14-mchip.off b{ color:var(--hint,#9b91c4); opacity:.7; }
.f14-mchip.off span{ color:var(--hint,#9b91c4); }
.f14-mchip:active{ transform:scale(.965); }
/* смена докнутого дня: цифры «перещёлкиваются» как показания прибора */
@keyframes f14num{ from{ opacity:0; transform:translateY(2px); } }
.f14-mchip b.flip{ animation:f14num .16s ease both; }
/* 320px: разрядка .06em съедала весь запас у самой длинной подписи из 18 локалей — вьетнамская
   «NĂNG LƯỢNG» (10 знаков С ПРОБЕЛОМ) мерялась 64.7px при внутренних 60.3 и вылезала за гнездо
   уже при штатном шрифте. 8px + .02em дают запас ~3px, новых строк локалей это не требует. */
@media (max-width:359px){ .f14-mchip{ padding:8px 7px 16px; } .f14-mchip span{ font-size:8px; letter-spacing:0; } }
/* one-time attention pulse so the user notices they're tappable — box-shadow больше не анимируется
   (paint на каждый кадр), подсказку несёт opacity */
.f14-metrics.hint .f14-mchip{ animation:f14chip 1s ease 2; }
@keyframes f14chip{ 0%,100%{ opacity:1; } 50%{ opacity:.5; } }
@media (prefers-reduced-motion:reduce){ .f14-metrics.hint .f14-mchip{ animation:none; } }

/* collapse/expand the natal placements card (founder: hide to save space — the toggle itself must be tiny) */
.hero-split.collapsed{ display:none; }
/* СВЁРНУТОЕ КОЛЕСО — display:none, а не opacity/height: так браузер снимает и вёрстку, и
   ВСЕ бесконечные анимации внутри (34 звезды, дыхание гало, поочерёдные вспышки связей).
   Ради этого свёрнутое состояние вообще имеет смысл на дешёвом Android. */
.fc-wheel.collapsed{ display:none; }
.fc-hero-toggle{ display:flex; align-items:center; justify-content:center; gap:5px; width:100%; margin:-10px 0 4px; padding:2px;
  background:none; border:0; color:var(--hint,#9b91c4); cursor:pointer; -webkit-tap-highlight-color:transparent; opacity:.6;
  /* ШОРТКАТ font: РАЗЛОЖЕН. `font:600 11px/1 inherit` невалиден (inherit не может быть
     семейством внутри шортката) и выбрасывался целиком — кнопка рисовалась системным
     шрифтом. Тот же дефект, что чинили на .f14-qseg. */
  font-weight:600; font-size:11px; line-height:1; font-family:inherit; }
.fc-hero-toggle .fc-ht-chev{ font-size:12px; }
.fc-hero-toggle:active{ opacity:.35; }
/* collapsed → the "show" bar is a touch clearer than the bare ⌃ handle, and needs its own top spacing */
.hero-split.collapsed + .fc-hero-toggle{ margin:2px 0 8px; opacity:.85; }
/* ОТСТУП ПОЛОЖИТЕЛЬНЫЙ, а не как у .fc-hero-toggle (-10px). Карточка героя тянет тумблер
   ВВЕРХ, потому что у неё есть собственный нижний паддинг, который надо съесть. У колеса
   его нет: последний элемент внутри — подсказка .fcw-hint с margin:2px 0 0, а у самого
   .fc-wheel снизу 2px. Отрицательный отступ клал стрелку ПРЯМО НА текст подсказки
   («Коснись планеты…») — найдено основателем 2026-08-02. 8px сверху дают чистый зазор. */
.fc-wheel-toggle{ margin:8px 0 6px; }
/* СТРОКА-ТУМБЛЕР ОСТАЁТСЯ ТОЛЬКО ДЛЯ СВЁРНУТОГО СОСТОЯНИЯ. У раскрытого колеса она стоила
   30px по вертикали (16 высота + 8/6 отступы) и была безымянной стрелкой; основатель
   2026-08-03 попросил перенести её в строку подсказки и подписать. Свернуть теперь можно
   кнопкой .fcw-fold рядом с «Коснись планеты…», развернуть — по-прежнему этой строкой,
   иначе пути назад не будет (.fc-wheel.collapsed сам display:none). */
.fc-wheel:not(.collapsed) + .fc-wheel-toggle{ display:none; }
/* Подсказка + «Свернуть» в один ряд по центру. flex-wrap: в самых длинных локалях
   («Tampilkan lebih sedikit», id) кнопка уходит на вторую строку, а не наезжает на текст. */
.fc-wheel .fcw-hintrow{ display:flex; align-items:center; justify-content:center;
  gap:10px; flex-wrap:wrap; margin:2px 0 0; }
.fc-wheel .fcw-hintrow .fcw-hint{ margin:0; }
/* ПИЛЮЛЯ, а не текст (основатель 2026-08-03: «сделаем как маленькую кнопочку, чтобы было
   понятно, что по ней можно нажать»). Контур + подложка читаются как кнопка на любом фоне,
   в отличие от прежней подписи цвета подсказки.
   Цвет НЕ золотой: золото в системе значит «премиум/личное» (см. «Астру»), а это обычное
   управление — берём фиолетовый акцент приглушённо.
   Высота пилюли 23px против 17px у голого текста: +6px к строке, что несопоставимо с
   прежними 47px «подсказка + отдельная строка со стрелкой».
   Прожатие — ТОЛЬКО transform+opacity (перф-доктрина: никаких анимаций box-shadow). */
.fc-wheel .fcw-fold{ position:relative; cursor:pointer; font-family:inherit;
  font-size:11px; font-weight:700; line-height:1; letter-spacing:.01em;
  color:var(--hint,#9b91c4); display:inline-flex; align-items:center; gap:5px;
  padding:5px 10px; border-radius:999px;
  border:1px solid rgba(167,139,250,.30); background:rgba(167,139,250,.10);
  transition:transform .12s ease, opacity .12s ease;
  -webkit-tap-highlight-color:transparent; }
/* Символ ⌃ (U+2303) сидит ВЫСОКО в своём em-боксе, и насколько именно — зависит от шрифта
   устройства (замер 2026-08-03: бокс глифа отцентрован идеально, а «чернильница» уезжала
   вверх). Поэтому рисуем чеврон сами: квадрат 7×7 с левой и верхней границей, повёрнутый
   на 45°. Тогда положение считается, а не подбирается, и одинаково на iOS и Android.
   Геометрия: у повёрнутого квадрата чернила занимают ВЕРХНЮЮ половину бокса (вершина в
   точке −4.95px от центра, концы лучей — на уровне центра), поэтому опускаем всю фигуру
   на половину этой высоты: translateY(2.5px). Порядок трансформов важен — translate
   применяется ПОСЛЕ поворота, то есть двигает уже готовый значок по вертикали экрана. */
.fc-wheel .fcw-fold .fc-ht-chev{
  font-size:0; line-height:0; width:7px; height:7px; opacity:.85;
  border-left:1.6px solid currentColor; border-top:1.6px solid currentColor;
  transform:translateY(2.5px) rotate(45deg); }
.fc-wheel .fcw-fold:active{ transform:scale(.94); opacity:.6; }
/* Палец бьёт по 45×нужному, глаз видит пилюлю 23px: невидимый расширитель тап-цели не
   участвует в раскладке, поэтому строка не растёт. */
.fc-wheel .fcw-fold::after{ content:""; position:absolute; inset:-11px -8px; }
.fc-wheel.collapsed + .fc-wheel-toggle{ margin:2px 0 8px; opacity:.85; }


/* daily forecast broadcast settings */
/* 2026-08-03: «когда приходит письмо» — ОДНА строка: час + пояс. Левый рельс (border-left
   + padding) убран вместе с текстами, которые он группировал: рельс собирал в блок три
   абзаца, а над двумя полями в ряд он только съедал ширину, которой поясу и не хватало. */
/* Выравниваем по ВЕРХУ, а поля колонками: так обе подписи стоят на одной линии независимо
   от того, что нативные input[type=time] и select имеют разную собственную высоту. */
.fc-bc-time{ margin-top:10px; display:flex; flex-wrap:wrap; gap:10px; align-items:flex-start; }
.fc-bc-time.hidden{ display:none; }
.fc-bc-time .field{ margin:0; display:flex; flex-direction:column; min-width:0; }
/* Нативные input[type=time] и select имеют РАЗНУЮ собственную высоту при одинаковых
   padding/font (замер: 52.8 против 49) — у поля времени выше внутренняя строка с системной
   иконкой. Рядом это читается как ошибка вёрстки, поэтому высоту задаём явно обоим.
   Вертикальные padding при этом обнуляются, иначе они прибавятся к height. 48px — не
   произвольное число: это минимальный комфортный размер цели для пальца. */
.fc-bc-time input[type=time], .fc-bc-tz select{ height:48px; padding-top:0; padding-bottom:0; }
.fc-bc-hh{ flex:0 0 auto; }
/* Нативный input[type=time] по своей воле занимает ~150px — половину строки ради «10:00».
   124px = 96px содержимого при padding:14px: «10:00» шестнадцатым кеглем плюс системная
   иконка часов. Меньше (пробовал 104px) — и минуты уезжают под иконку. */
.fc-bc-time input[type=time]{ width:120px; min-width:0; }
/* Пояс забирает весь остаток. min-width:0 обязателен: без него flex-элемент не даёт себя
   сжать ниже ширины содержимого, и длинная подпись зоны выдавливала бы строку за карточку
   вместо того, чтобы обрезаться. padding-right — под нативную стрелку: без него текст
   заезжает под неё (смещение при этом остаётся читаемым, но выглядит поломкой). */
/* flex-basis:150px — это ПОРОГ, а не ширина: пока в строке остаётся хотя бы 150px, пояс
   стоит рядом со временем — так на всех ходовых экранах, включая 360px (самая частая
   ширина Android). Уже — строка переносится и пояс занимает всю ширину. Альтернативой
   было ужать шрифт или обрезать подпись, но на 320px обрезалось РОВНО смещение, ради
   которого поле и существует. */
.fc-bc-tz{ flex:1 1 150px; }
.fc-bc-tz select{ width:100%; max-width:100%; padding-left:12px; padding-right:26px; text-overflow:ellipsis; }
.compat-hedge{ margin:6px 0 0; font-size:12.5px; line-height:1.4; color:var(--muted,#b8b0d4); text-align:center; opacity:.9; }
/* MAJ-13: honour reduced-motion for the spinner + astro-loader (natal-loader already gated) */
@media (prefers-reduced-motion: reduce){
  .spinner{ animation:none !important; }
  .astro-loader .al-orbit, .astro-loader .al-ring, .astro-loader .al-star, .astro-loader .al-core, .astro-loader .al-planet{ animation:none !important; }
}

/* MAJ-11/12 a11y: a visible KEYBOARD focus ring on the app's clickable controls
   (native buttons/links + the role="button" divs/spans made operable in app.js).
   Scoped to :focus-visible so mouse/touch users see NO change — the look stays
   identical for them. The dialog container (.sheet[tabindex="-1"]) is focused
   programmatically on open and must never show a ring. */
[role="button"]:focus-visible,
[role="option"]:focus-visible,
[role="tab"]:focus-visible,
[tabindex="0"]:focus-visible,
button:focus-visible,
a:focus-visible,
select:focus-visible,
input:focus-visible,
textarea:focus-visible {
  outline: 2px solid var(--accent, #b388ff);
  outline-offset: 2px;
}
/* Never show the ring for pointer interaction, nor on the programmatically-focused sheet. */
[role="button"]:focus:not(:focus-visible) { outline: none; }
.sheet:focus, .sheet:focus-visible { outline: none; }

/* ===== Onboarding redesign «Cosmic Immersion» — R2 (persistent-cosmos + 6 founder fixes) ===== */
/* #4 — the cosmos is a PERSISTENT sibling of #screen (#onb-cosmos-host), never rebuilt on a
   form re-render. State classes f-* , cta-armed, onb-fire live on the inner #onb-cosmos; the
   .armed/.flat-orbits/.rm budget classes live on the host. Content stays scoped to .onb-redesign. */

/* raise #screen above the fixed z-index:0 cosmos only while onboarding is mounted */
body.onb-cosmos-on #screen{ position:relative; z-index:1;
  /* founder 2026-07-11: #screen reserves 90px for the fixed tabbar — hidden during
     onboarding, so it was dead space under the CTA. */
  padding-bottom:20px; }

#onb-cosmos-host{
  position:fixed; top:0; bottom:0; left:50%; transform:translateX(-50%);
  width:100%; max-width:520px; z-index:0; pointer-events:none; overflow:hidden;
}
#onb-cosmos-host .onb-cosmos{
  position:absolute; inset:0; overflow:hidden; transform-origin:50% 30%;
  background:radial-gradient(130% 90% at 50% 12%, #241a48 0%, #17112f 45%, #0f0c1d 78%, #0b0819 100%);
}
#onb-cosmos-host .onb-cosmos::after{
  content:""; position:absolute; inset:0; pointer-events:none;
  background:radial-gradient(60% 42% at 50% 30%, rgba(255,217,138,.10) 0%, rgba(255,217,138,0) 70%);
  opacity:0; transition:opacity 1.3s ease;
}
#onb-cosmos-host .onb-cosmos.f-name::after { opacity:.42; }
#onb-cosmos-host .onb-cosmos.f-date::after { opacity:.62; }
#onb-cosmos-host .onb-cosmos.f-place::after{ opacity:.82; }
#onb-cosmos-host .onb-cosmos.cta-armed::after{ opacity:1; }
#onb-cosmos-host .onb-cosmos.onb-fire{ animation:onbk-bloom .6s ease-out 1; }
@keyframes onbk-bloom{ 0%{transform:scale(1);filter:brightness(1);} 45%{transform:scale(1.02);filter:brightness(1.26);} 100%{transform:scale(1);filter:brightness(1);} }

/* 1. starfield */
#onb-cosmos-host .sf{ position:absolute; inset:0; will-change:transform; }
#onb-cosmos-host .sf i{ position:absolute; display:block; border-radius:50%; background:#fff; }
#onb-cosmos-host .sf-far  i{ width:1px; height:1px; opacity:.35; }
#onb-cosmos-host .sf-mid  i{ width:2px; height:2px; opacity:.55; }
#onb-cosmos-host .sf-near i{ width:3px; height:3px; opacity:.8; box-shadow:0 0 4px 1px rgba(255,255,255,.5); }
#onb-cosmos-host .sf-far { animation:onbk-drift 120s linear infinite alternate; }
#onb-cosmos-host .sf-mid { animation:onbk-drift  78s linear infinite alternate; }
#onb-cosmos-host .sf-near{ animation:onbk-drift  46s linear infinite alternate; }
@keyframes onbk-drift{ 0%{transform:translate3d(0,0,0);} 100%{transform:translate3d(-6px,-14px,0);} }
#onb-cosmos-host .sf-near i,#onb-cosmos-host .sf-mid i:nth-child(3n){ animation:onbk-twinkle 3.4s ease-in-out infinite; }
@keyframes onbk-twinkle{ 0%,100%{opacity:.25; transform:scale(.7);} 50%{opacity:1; transform:scale(1.15);} }

/* 2. breathing gold core — anchored 42% into the clean pill gap (#6 polish) */
#onb-cosmos-host .onb-core{
  position:absolute; top:42%; left:50%; width:64px; height:64px; margin:-32px 0 0 -32px;
  border-radius:50%; z-index:3; opacity:.18; transform:scale(.82);
  transition:opacity 1.1s ease, transform 1.1s cubic-bezier(.22,1,.36,1);
}
#onb-cosmos-host .onb-core-glow{
  position:absolute; inset:0; border-radius:50%;
  background:radial-gradient(circle at 38% 32%, #fff6df 0%, #ffd98a 42%, #e8a94b 74%, rgba(179,136,255,0) 100%);
  box-shadow:0 0 26px 6px rgba(255,217,138,.35), 0 0 60px 18px rgba(255,217,138,.12);
  animation:onbk-breathe 5.5s ease-in-out infinite; will-change:transform;
}
@keyframes onbk-breathe{ 0%,100%{transform:scale(1);} 50%{transform:scale(1.06);} }
#onb-cosmos-host .onb-cosmos.f-name  .onb-core{ opacity:1; transform:scale(1); }
#onb-cosmos-host .onb-cosmos.f-date  .onb-core{ opacity:1; transform:scale(1.05); }
#onb-cosmos-host .onb-cosmos.f-place .onb-core{ opacity:1; transform:scale(1.09); }
#onb-cosmos-host .onb-cosmos.cta-armed .onb-core{ opacity:1; transform:scale(1.15); }
#onb-cosmos-host .onb-cosmos.onb-fire .onb-core-glow{ animation:onbk-breathe 5.5s ease-in-out infinite, onbk-settle 1s ease-out; }
@keyframes onbk-settle{ 0%{filter:brightness(1);} 40%{filter:brightness(1.75);} 100%{filter:brightness(1);} }

/* 3. orbits + planets */
#onb-cosmos-host .onb-orbit{
  position:absolute; top:42%; left:50%; border-radius:50%; z-index:1;
  transform:translate(-50%,-50%) rotateX(62deg); opacity:0; transition:opacity .9s ease;
}
#onb-cosmos-host .onb-orbit.o1{ width:150px; height:150px; border:1px solid rgba(255,217,138,.14); }
#onb-cosmos-host .onb-orbit.o2{ width:236px; height:236px; border:1px solid rgba(179,136,255,.13); }
#onb-cosmos-host .onb-orbit.o3{ width:312px; height:312px; border:1px dashed rgba(255,217,138,.08); }
#onb-cosmos-host .onb-spin{ position:absolute; inset:0; animation:onbk-spin var(--dur,30s) linear infinite; will-change:transform; }
#onb-cosmos-host .o1 .onb-spin{ --dur:18s; }
#onb-cosmos-host .o2 .onb-spin{ --dur:31s; }
#onb-cosmos-host .o3 .onb-spin{ --dur:52s; animation-direction:reverse; }
@keyframes onbk-spin{ to{ transform:rotate(360deg); } }
#onb-cosmos-host .onb-planet{
  position:absolute; top:-6px; left:50%; width:12px; height:12px; margin-left:-6px;
  border-radius:50%; transform:rotateX(-62deg);
}
#onb-cosmos-host .o1 .onb-planet{ width:13px; height:13px;
  background:radial-gradient(circle at 35% 30%,#fff,#ffd98a 55%,#d99a3f);
  box-shadow:0 0 10px 2px rgba(255,217,138,.6); }
#onb-cosmos-host .o2 .onb-planet{
  background:radial-gradient(circle at 35% 30%,#e6d6ff,var(--accent) 60%,#6a4bbf);
  box-shadow:0 0 9px 2px rgba(179,136,255,.6); }
#onb-cosmos-host .o3 .onb-planet{ width:8px; height:8px; background:var(--accent2); opacity:.85;
  box-shadow:0 0 8px 2px rgba(255,126,182,.5); }
#onb-cosmos-host .onb-cosmos.f-date .onb-orbit{ opacity:1; }
#onb-cosmos-host .onb-cosmos.f-date .onb-orbit.o2{ transition-delay:.3s; }
#onb-cosmos-host .onb-cosmos.f-date .onb-orbit.o3{ transition-delay:.6s; }
#onb-cosmos-host.flat-orbits .onb-orbit{ transform:translate(-50%,-50%) scaleY(.46) !important; }
#onb-cosmos-host.flat-orbits .onb-planet{ transform:none !important; }

/* 4. signature constellation */
#onb-cosmos-host .onb-constel{
  position:absolute; top:42%; left:50%; width:300px; height:300px;
  margin:-150px 0 0 -150px; z-index:2; overflow:visible;
}
#onb-cosmos-host .onb-constel line{
  stroke:#ffe6a6; stroke-width:1.7; fill:none; opacity:.85;
  stroke-dasharray:var(--len,60); stroke-dashoffset:var(--len,60);
  transition:stroke-dashoffset 1.15s ease, opacity .6s ease;
  filter:drop-shadow(0 0 4px rgba(255,217,138,.55));
}
#onb-cosmos-host .onb-constel circle{
  fill:#fff3d0; opacity:0; transform-box:fill-box; transform-origin:center; transform:scale(1);
  filter:drop-shadow(0 0 7px rgba(255,217,138,.95)) drop-shadow(0 0 2px rgba(255,255,255,.9));
  transition:opacity .5s ease, filter .5s ease, transform .55s cubic-bezier(.22,1,.36,1);
}
/* a freshly-lit star pops big + bright so the "chart forming" is clearly visible (founder 2026-07-06) */
/* 2026-07-11: the gender question left onboarding (feeds no calculation) — f-gender is never
   set anymore. The s2 star + its l1/l2 links are rebound to the name+date pair so the
   constellation keeps all six stars and every link stays reachable. */
#onb-cosmos-host .onb-cosmos.f-name  .onb-constel .s1,
#onb-cosmos-host .onb-cosmos.f-name.f-date .onb-constel .s2,
#onb-cosmos-host .onb-cosmos.f-date  .onb-constel .s3,
#onb-cosmos-host .onb-cosmos.f-time  .onb-constel .s4,
#onb-cosmos-host .onb-cosmos.f-place .onb-constel .s5,
#onb-cosmos-host .onb-cosmos.f-time.f-place .onb-constel .s6{ opacity:1; transform:scale(1.9); }   /* 2026-07-11: f-res retired with the rplace field */
#onb-cosmos-host .onb-cosmos.f-name.f-date    .onb-constel .l1,
#onb-cosmos-host .onb-cosmos.f-name.f-date    .onb-constel .l2,
#onb-cosmos-host .onb-cosmos.f-date.f-time    .onb-constel .l3,
#onb-cosmos-host .onb-cosmos.f-time.f-place   .onb-constel .l4,
#onb-cosmos-host .onb-cosmos.f-time.f-place   .onb-constel .l5{ stroke-dashoffset:0; }
#onb-cosmos-host .onb-cosmos.cta-armed .onb-constel line{ opacity:.92; stroke-width:1.3; }
#onb-cosmos-host .onb-cosmos.cta-armed .onb-constel circle{ opacity:1; filter:drop-shadow(0 0 6px rgba(255,217,138,.95)); }

/* 4b. claim beam — armed lives on the HOST */
#onb-cosmos-host .onb-beam{
  position:absolute; top:42%; left:50%; width:12px; height:12px; margin:-6px 0 0 -6px;
  border-radius:50%; z-index:6; opacity:0; pointer-events:none;
  background:radial-gradient(circle,#fff6df 0%,#ffd98a 45%,rgba(255,217,138,0) 72%);
  box-shadow:0 0 18px 7px rgba(255,217,138,.7);
}
#onb-cosmos-host.armed .onb-beam{ animation:onbk-beam 1.05s cubic-bezier(.5,0,.25,1) forwards; }
@keyframes onbk-beam{ 0%{opacity:0; transform:translateY(0) scale(.5);} 14%{opacity:1;} 100%{opacity:0; transform:translateY(74vh) scale(1.15);} }

/* ---- content scaffold ---- */
.onb-redesign{ position:relative;
  /* цвет скрима липкого дока. Здесь, на КОРНЕ, а не на самой .onb-cta-wrap: объявление
     на элементе перебило бы унаследованное значение, и .onb-editor не смог бы его
     переопределить (?v=433). Онбординг = цвет космоса, редактор = фон приложения. */
  --onb-cta-scrim:9,7,20; }
.onb-redesign .onb-content{ position:relative; z-index:1; }

/* ---- HERO copy ---- */
/* #1 — position:relative so the readability scrim anchors to the TEXT box */
.onb-redesign .onb-hero{ position:relative; padding:22px 6px 6px; text-align:center; }   /* founder 2026-07-11: compact hero */
.onb-redesign .onb-hero-scrim{
  position:absolute; left:50%; top:20px; transform:translateX(-50%);
  width:min(600px,100%); height:300px; z-index:0; pointer-events:none;  /* was 124% → overflowed narrow screens */
  /* Основатель 2026-08-18 (скрин iPhone): база rgba(9,7,20) ТЕМНЕЕ и фона, и
     glow-подсветки страницы — кромка эллипса читалась «переходом от тёмного к
     светлому». Цвет переведён на базовый фон (15,12,29), плотность снижена, стопы
     растянуты: звёзды под текстом всё так же гаснут, а границы у пятна больше нет. */
  background:radial-gradient(88% 68% at 50% 44%,
      rgba(15,12,29,.62) 0%, rgba(15,12,29,.50) 38%, rgba(15,12,29,.32) 60%,
      rgba(15,12,29,.16) 78%, rgba(15,12,29,.06) 90%, rgba(15,12,29,0) 100%);
  /* filter:blur(4px) снят: запретный filter на слое 600×300 поверх онбординга — самый
     дорогой пиксель первого экрана. Мягкость вернули стопами самого градиента. */
}
.onb-redesign .onb-kicker,
.onb-redesign .onb-title,
.onb-redesign .onb-hook,
.onb-redesign .onb-values{ position:relative; z-index:1; }   /* values были ПОД скримом → тёмные подписи */
.onb-redesign .onb-kicker{
  display:inline-block; font-size:11.5px; font-weight:800; letter-spacing:2.4px;
  text-transform:uppercase; color:var(--warn); opacity:.82; margin-bottom:10px;
}
.onb-redesign .onb-title{
  font-size:25px; line-height:1.14; font-weight:800; letter-spacing:-.5px;
  margin:0 0 10px; color:var(--text);
  text-shadow:0 2px 30px rgba(255,217,138,.16), 0 1px 16px rgba(9,7,20,.55); /* #1 dark guard */
}
.onb-redesign .onb-title .who{
  background:linear-gradient(100deg,#fff6df 0%,#ffd98a 55%,#e8b45c 100%);
  -webkit-background-clip:text; background-clip:text;
  -webkit-text-fill-color:transparent; color:transparent;
}
@supports not ((-webkit-background-clip:text) or (background-clip:text)){
  .onb-redesign .onb-title .who{ background:none; color:#ffd98a; -webkit-text-fill-color:#ffd98a; }
}
.onb-redesign .onb-hook{
  color:#c8bce8; font-size:14px; line-height:1.4; margin:0 auto 14px; max-width:34ch; text-align:center;
  text-shadow:0 1px 14px rgba(9,7,20,.75); /* #1 dark guard */
}

/* ---- #2 — VALUE LEGEND (not buttons): borderless inline caption row ---- */
.onb-redesign .onb-values{
  /* founder 2026-07-11: ONE line in every locale — es «Predicciones» wrapped «Amor» onto a
     2nd row. nowrap + fluid pill padding/caption size shrink to fit instead of wrapping. */
  display:flex; flex-wrap:nowrap; justify-content:center; align-items:center;
  gap:0; margin:0 0 12px; white-space:nowrap;
}
.onb-redesign .onb-val{
  display:inline-flex; align-items:center; gap:7px;
  padding:1px clamp(6px,2.4vw,15px); background:none; border:0; border-radius:0; min-width:0;
}
.onb-redesign .onb-val + .onb-val{ border-left:1px solid rgba(179,136,255,.22); }
.onb-redesign .onb-val .glyph{
  flex:none; display:inline-flex; align-items:center; justify-content:center; height:16px;
  font-size:16px; line-height:1; color:#ffd98a; opacity:.92;
  text-shadow:0 0 10px rgba(255,217,138,.35);
}
/* ♀ (Venus, «Любовь») is an inline SVG (text ♀ metrics differ per device/font → it slipped). The SVG renders
   identically everywhere; its ink is centred in the viewBox so it sits level with ☉/☾ (founder 2026-07-06). */
.onb-redesign .onb-val .gv svg{ width:15px; height:15px; display:block; overflow:visible; }
.onb-redesign .onb-val .cap{
  font-size:clamp(10.5px,3.2vw,12.5px); font-weight:700; letter-spacing:.2px; text-transform:none;
  color:#c8bce8; white-space:nowrap;
}
@media (max-width:330px){
  .onb-redesign .onb-val{ padding:1px 11px; }
  .onb-redesign .onb-val + .onb-val{ border-left:0; }
}

/* scroll cue (first paint only) */
.onb-redesign .onb-scroll-cue{
  display:block; margin:6px auto 0; width:22px; height:22px; opacity:0;
  animation:onbk-cuebob 1.9s ease-in-out 1.4s 3, onbk-cuefade .6s ease 7s forwards;
}
.onb-redesign .onb-scroll-cue svg{ display:block; width:100%; height:100%; fill:none;
  stroke:#ffd98a; stroke-width:2.2; stroke-linecap:round; stroke-linejoin:round; opacity:.65; }
@keyframes onbk-cuebob{ 0%,100%{opacity:.55; transform:translateY(0);} 50%{opacity:.9; transform:translateY(6px);} }
@keyframes onbk-cuefade{ to{opacity:0; visibility:hidden;} }
.onb-redesign .onb-scroll-cue.hide{ animation:none; opacity:0; visibility:hidden; }

/* while a field is focused, add scroll room so ANY field (incl. the last) can rise above the on-screen keyboard —
   and its city dropdown fits in the space above the keyboard instead of hiding behind it (founder 2026-07-06). */
.onb-redesign .onb-form.kb-open{ padding-bottom:48vh; }

/* first-paint stagger */
.onb-redesign.onb-first-paint .onb-form .field{ animation:onbk-fadeup .5s both; }
.onb-redesign.onb-first-paint .onb-form .field:nth-child(1){ animation-delay:.05s; }
.onb-redesign.onb-first-paint .onb-form .field:nth-child(2){ animation-delay:.12s; }
.onb-redesign.onb-first-paint .onb-form .field:nth-child(3){ animation-delay:.19s; }
.onb-redesign.onb-first-paint .onb-form .field:nth-child(4){ animation-delay:.26s; }
.onb-redesign.onb-first-paint .onb-form .field:nth-child(5){ animation-delay:.33s; }
.onb-redesign.onb-first-paint .onb-val{ animation:onbk-fadeup .5s both; }
.onb-redesign.onb-first-paint .onb-val:nth-child(1){ animation-delay:.30s; }
.onb-redesign.onb-first-paint .onb-val:nth-child(2){ animation-delay:.40s; }
.onb-redesign.onb-first-paint .onb-val:nth-child(3){ animation-delay:.50s; }
@keyframes onbk-fadeup{ from{opacity:0; transform:translateY(8px);} to{opacity:1; transform:none;} }

/* ---- glass field cards ---- */
.onb-redesign .field{
  margin:12px 0; padding:16px 15px 15px; border-radius:18px;
  background:color-mix(in srgb, var(--card) 78%, transparent);
  border:1px solid var(--line);
  backdrop-filter:blur(9px); -webkit-backdrop-filter:blur(9px);
  box-shadow:0 6px 22px -12px rgba(0,0,0,.6);
  transition:border-color .18s ease, box-shadow .18s ease, background .18s ease; /* #3 */
}
@supports not ((backdrop-filter:blur(2px)) or (-webkit-backdrop-filter:blur(2px))){
  .onb-redesign .field{ background:color-mix(in srgb, var(--card) 94%, #0b0819); backdrop-filter:none; -webkit-backdrop-filter:none; }
}
.onb-redesign .field > label{ font-size:13px; font-weight:600; color:var(--hint); margin-bottom:9px; letter-spacing:.2px; }

/* ---- #5 — inputs / selects: box-sizing + min-width:0 kills native intrinsic overflow ---- */
.onb-redesign input[type=text],
.onb-redesign input[type=time],
.onb-redesign select{
  display:block; box-sizing:border-box; width:100%; max-width:100%; min-width:0;
  padding:13px 14px; font-size:16px; color:var(--text);
  background:var(--bg2); border:1px solid var(--line); border-radius:13px;
  outline:none; font-family:inherit; transition:border-color .18s, box-shadow .18s;
}
.onb-redesign input[type=time]{ -webkit-appearance:none; appearance:none; }
.onb-redesign input[type=time]::-webkit-date-and-time-value{ margin:0; padding:0; text-align:left; min-width:0; }
.onb-redesign input[type=time]::-webkit-calendar-picker-indicator{
  margin:0 0 0 auto; padding:0; flex:0 0 auto;
  filter:invert(72%) sepia(24%) saturate(900%) hue-rotate(214deg);
}
/* время рождения: обёртка с плейсхолдером «--:--» и значком часов (см. timeInputHtml) */
.tm-wrap{ position:relative; display:block; }
.tm-ph, .tm-ico{ display:none; }
@supports (-webkit-touch-callout:none){   /* только iOS-WebKit: там пустое поле времени — немая плашка */
  .tm-wrap .tm-ph{ position:absolute; left:15px; top:50%; transform:translateY(-50%);
    font-size:16px; letter-spacing:.06em; color:var(--hint); opacity:.75; pointer-events:none; }
  .tm-wrap.empty .tm-ph{ display:block; }
  .tm-wrap .tm-ico{ display:block; position:absolute; right:14px; top:50%; transform:translateY(-50%);
    width:20px; height:20px; fill:none; stroke:var(--accent); stroke-width:1.6; stroke-linecap:round;
    opacity:.85; pointer-events:none; }
}
.onb-redesign input[type=time]::-webkit-inner-spin-button,
.onb-redesign input[type=time]::-webkit-clear-button{ -webkit-appearance:none; display:none; }
.onb-redesign input[type=text]:focus,
.onb-redesign input[type=time]:focus,
.onb-redesign select:focus{ border-color:var(--accent); box-shadow:0 0 0 3px rgba(179,136,255,.18); }
.onb-redesign input::placeholder{ color:var(--hint); opacity:.7; }

/* ---- #3 — PREMIUM FOCUS STATE: the whole glass card lights on focus ---- */
.onb-redesign .field:focus-within{
  border-color:color-mix(in srgb, var(--accent) 72%, var(--line));
  background:color-mix(in srgb, var(--card) 88%, transparent);
  box-shadow:0 0 0 1px rgba(179,136,255,.55),
             0 0 22px -2px rgba(179,136,255,.38),
             0 10px 30px -14px rgba(0,0,0,.7);
}
.onb-redesign .field:focus-within input[type=text],
.onb-redesign .field:focus-within input[type=time],
.onb-redesign .field:focus-within select:focus{
  border-color:var(--accent); box-shadow:0 0 0 3px rgba(179,136,255,.22);
}
/* POLISH 5 — plain :focus too (iOS drops :focus-visible on tap for role=button divs) */
.onb-redesign .choice:focus,
.onb-redesign .choice:focus-visible{
  outline:none; border-color:color-mix(in srgb, var(--accent) 78%, var(--line));
  box-shadow:0 0 0 2px rgba(179,136,255,.55), 0 0 16px -2px rgba(179,136,255,.4);
}
.onb-redesign .switch input:focus-visible + .track{ box-shadow:0 0 0 2px rgba(179,136,255,.55); }
.onb-redesign #onb-submit:focus-visible,
.onb-redesign .onb-cta:focus-visible{
  outline:none;
  box-shadow:0 0 0 3px rgba(255,246,223,.7), 0 0 0 1px rgba(255,217,138,.5),
             0 14px 34px -10px rgba(255,217,138,.5), 0 2px 0 rgba(255,255,255,.3) inset;
}

/* gender chips */
/* minmax(0,1fr) (not 1fr = minmax(auto,1fr)) so the 3 chips ALWAYS fit the width even with a large system font —
   otherwise a wide label ("Женский") forces its column past the min-content width and "Другое" is clipped off-screen. */
.onb-redesign .choice-grid{ grid-template-columns:repeat(3, minmax(0,1fr)); gap:9px; }
.onb-redesign .choice{ padding:12px 6px; border-radius:13px; min-width:0; overflow-wrap:anywhere; hyphens:auto; transition:border-color .15s, background .15s, transform .08s; }
.onb-redesign .choice:active{ transform:scale(.97); }
.onb-redesign .choice.sel{ box-shadow:0 0 0 3px rgba(179,136,255,.14); }

/* date grid */
.onb-redesign .date-grid{ grid-template-columns:minmax(0,1fr) minmax(0,1.3fr) minmax(0,1fr); gap:9px; }
.onb-redesign .date-grid.dp-mdy{ grid-template-columns:minmax(0,1.3fr) minmax(0,1fr) minmax(0,1fr); }   /* en: Month / Day / Year */
.onb-redesign .date-grid select{ text-align:center; }

/* toggle rows */
.onb-redesign .toggle-row{
  padding:11px 2px 3px; margin-top:4px;
  display:flex; align-items:center; justify-content:flex-end; gap:14px;   /* founder 2026-07-13: пара «подпись+свитч» прижата к правому краю блока */
}
.onb-redesign .toggle-row .tr-label{ font-size:14px; color:#cbc0e6; flex:none; }   /* глушим базовый flex:1 — он утаскивал свитч к правому краю */
/* founder 2026-07-11: «необязательно» tag on the optional fields (self + add-person) — muted, non-shouty */
/* R1-MIN-21: nowrap keeps «· необязательно» together — without it ru/pt at 320dp broke INSIDE the
   span and left the separator dangling at the end of the first line («…места рождения ·»). The tag
   wraps to the next line as a whole instead. */
.field label .opt{ font-weight:400; font-size:12px; color:var(--hint); opacity:.85; text-transform:none; letter-spacing:0; white-space:nowrap; }
/* add-person в redesign-шелле: компактный заголовок вместо hero;
   #screen резервирует 90px под таб-бар — в add-person его нет, компенсируем (90→20). */
.onb-addperson{ margin-bottom:-70px; }
.onb-addperson .onb-add-title{ font-size:24px; font-weight:800; letter-spacing:-.4px; margin:6px 2px 14px; }
/* ФОРМА ПЕРВОГО ВХОДА В СОВМЕСТИМОСТЬ (основатель 2026-08-30, комбо V1+V2). Вместо
   «Давай познакомимся» — строка пары «Я ⊕ …и кто?» из пакета неба (.sky-names живёт
   в compat_sky.css, он заведомо загружен: сюда ведёт только SKY.render) + объяснение
   .sky-sub. Цвет линии — через data-line на корне формы (токены --lt глобальные).
   Лунка второго: пусто → пунктир дышит (правило пакета), имя → первая буква, дата →
   глиф знака. Золото ×1: лунка уже маяк, ореол пикера даты здесь гасим. */
.onb-redesign.onb-first .sky-names{ margin:6px 2px 0; }
.onb-redesign.onb-first .sky-sub{ margin:8px 2px 16px; text-wrap:balance; }
.onb-redesign.onb-first .sky-face.empty.lettered{ display:inline-flex; align-items:center; justify-content:center;
  font-size:13px; font-weight:800; color:var(--lt); animation:none; opacity:1; }
.onb-redesign.onb-first .date-grid .dp-cell.dp-glow::after{ display:none; }
.onb-redesign.onb-first .date-grid .dp-cell.dp-glow > select{ border-color:var(--line); }

/* ---- #6 — city list over the cosmos ---- */
.onb-redesign .city-list{ border-radius:12px; border:1px solid var(--line); background:rgba(20,16,40,.72); }
/* founder 2026-07-11: the EMPTY suggestions box drew its 1px border as a stray "divider"
   line between the city input and the toggle — don't render it until it has options. */
.city-list:empty{ display:none; }
.onb-redesign .city-list .city-item{ min-height:46px; display:flex; align-items:baseline; gap:6px; }
.city-head{ padding:9px 12px 6px; font-size:11.5px; font-weight:700; letter-spacing:.5px;
  text-transform:uppercase; color:var(--hint); }
.onb-redesign .city-head{ color:#ffd98a; opacity:.82; border-bottom:1px solid var(--line); }
/* POLISH 3 — the empty-results fallback is a dead row, never a tap target */
.city-item.no-hit{ cursor:default; pointer-events:none; opacity:.7; }
.city-item.no-hit:active,.city-item.no-hit:hover{ background:transparent; }

/* ---- CTA (unchanged: the single brightest gold object; wrapper .armed drives the receive flare) ---- */
/* Founder 2026-07-09: sticky create button — 306/361 set a date but never reached the CTA. Pin it to the bottom so
   it is always visible while the form scrolls; a gradient lets content fade under it. */
.onb-redesign .onb-cta-wrap{
  position:sticky; bottom:0; z-index:6;
  margin:18px -14px 0; padding:14px 14px calc(12px + var(--sab, env(safe-area-inset-bottom)));
  background:linear-gradient(to top, rgba(var(--onb-cta-scrim),0) 0%, rgba(var(--onb-cta-scrim),.88) 22%, rgba(var(--onb-cta-scrim),.97) 58%, rgba(var(--onb-cta-scrim),.62) 82%, rgba(var(--onb-cta-scrim),0));
}
/* .onb-cta = класс-алиас золотой кнопки (?v=433): редактор профиля берёт ТОТ ЖЕ объект,
   но со своим id (pe-save) — второй #onb-submit создал бы второй гейт, который дёргают
   setBdate()/onbHeroSync(). Драматургия онбординга (.cta-in/.cta-wait/.cta-gild/.armed)
   алиаса НЕ получает. */
.onb-redesign #onb-submit,
.onb-redesign .onb-cta{
  position:relative; overflow:hidden; width:100%;
  min-height:58px; border-radius:18px; padding:14px 16px; border:0; margin:0;
  font-family:inherit; font-size:17px; font-weight:800; letter-spacing:-.2px;
  cursor:pointer; color:#1a1030; opacity:1;
  background:linear-gradient(135deg,#ffe9b8 0%,#ffd98a 45%,#e8b45c 100%);
  box-shadow:0 0 0 1px rgba(255,217,138,.4), 0 14px 34px -10px rgba(255,217,138,.5), 0 2px 0 rgba(255,255,255,.3) inset;
  animation:onbk-halo 5.5s ease-in-out infinite;
}
.onb-redesign #onb-submit[disabled]{
  /* founder 2026-07-14: серую кнопку ПРЯЧЕМ — на неё тыкали (dead_tap), а толку ноль;
     до готовности в CTA-плашке живёт только золотая подсказка «осталась дата» */
  display:none;
}
/* появление кнопки в момент готовности — один раз (класс cta-in ставит onbRender) */
.onb-redesign #onb-submit.cta-in{
  animation:ctaIn 450ms cubic-bezier(.2,1,.3,1), onbk-halo 5.5s ease-in-out 450ms infinite;
}
@keyframes ctaIn{ from{ opacity:0; transform:translateY(14px) scale(.97); } to{ opacity:1; transform:none; } }
/* этап «до взрыва» (д+м есть, года нет): кнопка РАБОЧАЯ, но серая — золото надо заслужить */
.onb-redesign #onb-submit.cta-wait{
  background:var(--bg2); border:1px solid var(--line); box-shadow:none; animation:none;
  color:#cbc0e6; cursor:pointer;
}
.onb-redesign #onb-submit.cta-wait::after{ display:none; }   /* блик тоже ждёт золота */
.onb-redesign #onb-submit.cta-wait.cta-in{ animation:ctaIn 450ms cubic-bezier(.2,1,.3,1); }
/* озолочение после взрыва: короткий прогрев + штатный ореол */
.onb-redesign #onb-submit.cta-gild{
  animation:ctaGild 700ms ease-out, onbk-halo 5.5s ease-in-out 700ms infinite;
}
@keyframes ctaGild{ 0%{ filter:brightness(.7); } 55%{ filter:brightness(1.4); } 100%{ filter:brightness(1); } }
.onb-redesign #onb-submit:not([disabled])::after,
.onb-redesign .onb-cta:not([disabled])::after{
  content:""; position:absolute; top:0; bottom:0; left:-45%; width:40%;
  background:linear-gradient(100deg,rgba(255,255,255,0) 0%,rgba(255,255,255,.5) 50%,rgba(255,255,255,0) 100%);
  transform:skewX(-18deg); animation:onbk-shine 4.2s ease-in-out infinite; pointer-events:none;
}
.onb-redesign #onb-submit:active:not([disabled]),
.onb-redesign .onb-cta:active:not([disabled]){ transform:scale(.99); }
.onb-redesign.armed #onb-submit:not([disabled]){ animation:onbk-halo 5.5s ease-in-out infinite, onbk-receive 1s ease .82s 1; }
@keyframes onbk-receive{
  0%{box-shadow:0 0 0 1px rgba(255,217,138,.4),0 14px 34px -10px rgba(255,217,138,.5),0 2px 0 rgba(255,255,255,.3) inset;}
  40%{box-shadow:0 0 0 2px #fff6df,0 0 40px 12px rgba(255,217,138,.85),0 14px 34px -8px rgba(255,217,138,.7),0 2px 0 rgba(255,255,255,.4) inset;}
  100%{box-shadow:0 0 0 1px rgba(255,217,138,.4),0 14px 34px -10px rgba(255,217,138,.5),0 2px 0 rgba(255,255,255,.3) inset;}
}
@keyframes onbk-halo{
  0%,100%{box-shadow:0 0 0 1px rgba(255,217,138,.4), 0 0 16px 2px rgba(255,217,138,.28), 0 14px 34px -10px rgba(255,217,138,.4), 0 2px 0 rgba(255,255,255,.3) inset;}
  50%{box-shadow:0 0 0 1px rgba(255,217,138,.5), 0 0 26px 6px rgba(255,217,138,.45), 0 14px 34px -8px rgba(255,217,138,.55), 0 2px 0 rgba(255,255,255,.3) inset;}
}
@keyframes onbk-shine{ 0%,62%{left:-45%;} 86%,100%{left:130%;} }
.onb-redesign .onb-disabled-hint{ text-align:center; margin:11px 0 0; font-size:12.5px; font-weight:600; color:#ffd98a; opacity:.85; }

/* ============================================================
   MOTION FALLBACKS — cosmos on #onb-cosmos-host, content on .onb-redesign
   ============================================================ */
@media (prefers-reduced-motion:reduce){
  #onb-cosmos-host .sf, #onb-cosmos-host .onb-spin, #onb-cosmos-host .onb-core-glow,
  #onb-cosmos-host .onb-beam, #onb-cosmos-host .onb-cosmos.onb-fire,
  .onb-redesign #onb-submit, .onb-redesign .onb-cta, .onb-redesign.onb-first-paint .field,
  .onb-redesign.onb-first-paint .onb-val, .onb-redesign .onb-scroll-cue{ animation:none !important; }
  #onb-cosmos-host .onb-cosmos.onb-fire{ transform:none !important; filter:none !important; }
  #onb-cosmos-host .onb-cosmos::after{ opacity:1 !important; transition:none; }
  #onb-cosmos-host .onb-core{ opacity:1 !important; transform:scale(1.1) !important; transition:none; }
  #onb-cosmos-host .onb-orbit{ opacity:.6 !important; transition:none; }
  #onb-cosmos-host .onb-constel line{ stroke-dashoffset:0 !important; transition:none; opacity:.6; }
  #onb-cosmos-host .onb-constel circle{ opacity:.95 !important; transition:none; }
  #onb-cosmos-host .o1 .onb-spin{ transform:rotate(30deg); }
  #onb-cosmos-host .o2 .onb-spin{ transform:rotate(200deg); }
  #onb-cosmos-host .o3 .onb-spin{ transform:rotate(300deg); }
  .onb-redesign .onb-scroll-cue{ opacity:0 !important; }
}
/* JS-forced budget: cosmos on host.rm, content on .onb-redesign.rm */
#onb-cosmos-host.rm .sf, #onb-cosmos-host.rm .onb-spin, #onb-cosmos-host.rm .onb-core-glow,
#onb-cosmos-host.rm .onb-beam, #onb-cosmos-host.rm .onb-cosmos.onb-fire{ animation:none !important; }
#onb-cosmos-host.rm .onb-cosmos.onb-fire{ transform:none !important; filter:none !important; }
#onb-cosmos-host.rm .onb-cosmos::after{ opacity:1 !important; transition:none; }
#onb-cosmos-host.rm .onb-core{ opacity:1 !important; transform:scale(1.1) !important; transition:none; }
#onb-cosmos-host.rm .onb-orbit{ opacity:.6 !important; transition:none; }
#onb-cosmos-host.rm .onb-constel line{ stroke-dashoffset:0 !important; transition:none; opacity:.6; }
#onb-cosmos-host.rm .onb-constel circle{ opacity:.95 !important; transition:none; }
#onb-cosmos-host.rm .o1 .onb-spin{ transform:rotate(30deg); }
#onb-cosmos-host.rm .o2 .onb-spin{ transform:rotate(200deg); }
#onb-cosmos-host.rm .o3 .onb-spin{ transform:rotate(300deg); }
.onb-redesign.rm #onb-submit, .onb-redesign.rm .field, .onb-redesign.rm .onb-val,
.onb-redesign.rm .onb-scroll-cue{ animation:none !important; }
.onb-redesign.rm .onb-scroll-cue{ opacity:0 !important; }

/* ---------------------------------------------------------------------------
   DES-13: onboarding draft resume — shortened re-entry for returning users.
   The hero compresses (they've seen the pitch), the value bullets/hook hide,
   and a resume note at the top of the form says exactly what's left. */
.onb-redesign.onb-resume .onb-hero{ padding-top:22px; padding-bottom:2px; }
/* founder 2026-07-11: in resume mode the hero is ~150px tall but the 300px scrim kept its
   full height and washed a dark blur over the resume note below — clamp it to the hero. */
.onb-redesign.onb-resume .onb-hero-scrim{ height:140px; top:10px; }
.onb-redesign.onb-resume .onb-hook,
.onb-redesign.onb-resume .onb-values,
.onb-redesign.onb-resume .onb-scroll-cue{ display:none; }
.onb-resume-note{
  margin:0 0 14px; padding:10px 12px; border-radius:12px; font-size:13.5px; line-height:1.4;
  background:rgba(179,136,255,.12); border:1px solid rgba(179,136,255,.35); color:#e8e4f5;
}

/* ============================================================
   «Звёздный близнец» (celebrity twin, onboarding Concept A).
   Container #onb-twin sits between the date and time fields; JS flips
   data-state="teaser" | "card" and animates height inline (240ms), CSS
   only supplies the states. No external resources, no photos.
   ============================================================ */

/* first-paint: the twin container takes its own stagger slot between the
   date field (.12s) and the fields below (which shift +1 nth slot — fine,
   same precedent as the resume note). */
.onb-redesign.onb-first-paint .onb-form .onb-twin{ animation:onbk-fadeup .5s both .12s; }

/* ---- shell (shared by teaser + card) — glass like .onb-redesign .field,
   deliberately NOT the .field class (would inherit focus-within highlight) ---- */
.onb-twin{
  /* founder 2026-07-13: живёт ВНУТРИ блока даты — вложенная карточка, не дубль стекла */
  margin:12px 0 2px; border-radius:14px; overflow:hidden;
  background:rgba(179,136,255,.055);
  border:1px solid rgba(179,136,255,.14);
  transition:height 240ms cubic-bezier(0.33,1,0.68,1), border-color .18s ease;
}
@supports not ((backdrop-filter:blur(2px)) or (-webkit-backdrop-filter:blur(2px))){
  .onb-twin{ background:color-mix(in srgb, var(--card) 94%, #0b0819); backdrop-filter:none; -webkit-backdrop-filter:none; }
}
.onb-twin[data-state="card"]{ border-color:color-mix(in srgb, var(--accent) 40%, var(--line)); }
/* founder 2026-07-14: у миников было ТРИ уровня стекла (блок даты → контейнер → карточки) —
   средний убираем: плашки близнецов лежат прямо в блоке даты */
.onb-twin[data-state="minis"]{ background:none; border-color:transparent; }

/* ---- teaser (default state, fixed 40px) ---- */
.onb-twin[data-state="teaser"]{ min-height:40px; }   /* founder 2026-07-13: 2-строчный тизер прижимало вниз фиксом 40px */
.onb-twin-teaser{ display:flex; align-items:center; gap:9px; min-height:40px; padding:8px 14px; }
.onb-twin-teaser .tw-spark{
  flex:none; font-size:15px; line-height:1; color:var(--gold);
  text-shadow:0 0 10px rgba(255,217,138,.35);            /* same trick as .onb-val .glyph */
}
.onb-twin-teaser .tw-teaser-txt{
  font-size:13px; line-height:1.25; color:#c8bce8;
  display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden;   /* founder 2026-07-13: 2 строки, «…» на первой резал смысл */
}

/* ---- card (reveal state; content fades up 60ms after the height starts) ---- */
.onb-twin-card{
  padding:12px 14px; cursor:pointer; -webkit-tap-highlight-color:transparent;
  opacity:0; transform:translateY(8px);
  transition:opacity 240ms cubic-bezier(0.33,1,0.68,1) 60ms,
             transform 240ms cubic-bezier(0.33,1,0.68,1) 60ms;
}
.onb-twin-card.in{ opacity:1; transform:none; }
/* draft-resume: card known at mount → no entrance animation at all */
.onb-twin.instant{ transition:none; }
.onb-twin.instant .onb-twin-card{ transition:none; opacity:1; transform:none; }
.onb-twin .onb-twin-card:active{ transform:scale(.99); }

.onb-twin .tw-row{ display:flex; align-items:center; gap:12px; transition:opacity 150ms ease; }
.onb-twin .tw-body{ flex:1; min-width:0; }

/* wrap разрешён на ЛЮБОЙ ширине: RU «ТВОЙ ЗВЁЗДНЫЙ БЛИЗНЕЦ» + чип «ТОТ ЖЕ ДЕНЬ И ГОД»
   не влезают в одну строку и на 375–393px (не только ≤360) — чип уходит на свою строку,
   а не режется правым краем карточки (ночной QA 2026-07: overflow 53–61px) */
.onb-twin .tw-top{ display:flex; align-items:center; justify-content:space-between; gap:8px; flex-wrap:wrap; row-gap:2px; }
.onb-twin .tw-label{
  font-size:10px; font-weight:800; letter-spacing:1.6px; text-transform:uppercase;
  color:var(--hint); opacity:.9; white-space:nowrap;
}
.onb-twin .tw-name{
  font-size:16px; font-weight:600; color:var(--text); line-height:1.2; margin-top:1px;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.onb-twin .tw-meta{
  font-size:clamp(11px, 3.2vw, 12.5px); color:var(--hint); line-height:1.35; margin-top:2px;
  /* founder 2026-07-14: тексты карточки адаптируются, а не режутся — кламп строк убран */
}
.onb-twin .tw-meta .tw-sun{ color:#c8bce8; }

/* фото поверх монограммы (фолбэк остаётся под ним на случай битой загрузки) */
.twin-portrait{ position:relative; }
.twin-portrait .tw-photo{
  position:absolute; inset:0; width:100%; height:100%; object-fit:cover;
  border-radius:inherit; display:none;
}
.twin-portrait.has-photo .tw-photo{ display:block; }
.twin-portrait.has-photo .tw-mono{ visibility:hidden; }
/* «©» атрибуции фото: 14px в левом верхнем углу портрета (глиф знака — в правом нижнем);
   хит-зона шире за счёт ::after, чтобы попадать пальцем, не раздувая значок */
.twin-portrait .ph-cr{
  position:absolute; left:-3px; top:-3px; z-index:2; width:15px; height:15px; padding:0;
  border-radius:50%; border:1px solid var(--line); background:rgba(15,12,29,.78);
  color:rgba(255,255,255,.72); font-size:9px; line-height:1; font-family:inherit;
  display:flex; align-items:center; justify-content:center; cursor:pointer;
  -webkit-tap-highlight-color:transparent;
}
.twin-portrait .ph-cr::after{ content:""; position:absolute; inset:-9px; }
.twin-portrait:not(.has-photo) .ph-cr{ display:none; }   /* фото не загрузилось → монограмма, атрибуция не нужна */
.tw-mini-p .ph-cr{ width:13px; height:13px; font-size:8px; left:-2px; top:-2px; }
.ph-cr-pop{
  position:fixed; z-index:9999; max-width:min(280px, calc(100vw - 16px));
  padding:7px 10px; border-radius:10px; font-size:11px; line-height:1.35; color:#e6e0f7;
  background:rgba(20,16,38,.96); border:1px solid rgba(179,136,255,.28);
  box-shadow:0 6px 20px rgba(0,0,0,.45); overflow-wrap:anywhere;
  display:-webkit-box; -webkit-line-clamp:4; -webkit-box-orient:vertical; overflow:hidden;
  opacity:0; transform:translateY(-3px); transition:opacity .16s ease, transform .16s ease;
  pointer-events:auto;
}
.ph-cr-pop.in{ opacity:1; transform:none; }
@media (prefers-reduced-motion: reduce){ .ph-cr-pop{ transition:none; transform:none; } }
.tw-arr{
  width:22px; height:22px; border-radius:50%; border:1px solid var(--line);
  background:rgba(179,136,255,.08); color:var(--accent); font-size:13px; line-height:1;
  display:inline-flex; align-items:center; justify-content:center; cursor:pointer; padding:0;
}
.tw-arr:active{ transform:scale(.92); }

/* ---- B-1 dev-picker: пилюли [A][B][C][↻] выбора вариации вспышки (twin_fx="picker") ---- */
.tw-fx-pills{ display:inline-flex; align-items:center; gap:4px; margin-left:auto; }
.tw-fx-pill{
  min-width:22px; height:22px; border-radius:11px; border:1px solid var(--line);
  background:rgba(179,136,255,.08); color:var(--accent); font-size:11px; font-weight:700;
  line-height:1; display:inline-flex; align-items:center; justify-content:center;
  cursor:pointer; padding:0 6px;
}
.tw-fx-pill.on{
  background:rgba(179,136,255,.28); border-color:var(--accent); color:var(--text);
}
.tw-fx-pill:active{ transform:scale(.92); }
.tw-fx-pill.tw-fx-replay{ color:var(--gold); }

/* ---- мини-плашки (частичная дата: день → 3 в разных месяцах, день+месяц → 1) ---- */
.tw-minis-cap{
  padding:10px 14px 0; font-size:10px; font-weight:800; letter-spacing:1.4px;
  text-transform:uppercase; color:var(--hint); opacity:.9;
}
.onb-twin-minis{ display:grid; grid-template-columns:repeat(3,1fr); gap:8px; padding:8px 12px 10px; }
.tw-mini-p .tw-glyph{ width:15px; height:15px; font-size:9px; }   /* значок знака как на карточке, чуть мельче под 34px портрет */
.onb-twin-minis.one{ grid-template-columns:1fr; }
.onb-twin-minis.one .tw-mini{ flex-direction:row; justify-content:flex-start; gap:10px; padding:8px 12px; }
.onb-twin-minis.one .tw-mini-name{ font-size:14px; }
.tw-mini{
  display:flex; flex-direction:column; align-items:center; gap:5px;
  padding:9px 6px; border-radius:12px; min-width:0;
  background:rgba(179,136,255,.06); border:1px solid rgba(179,136,255,.16);
}
.tw-mini .tw-mini-p{ width:34px; height:34px; }
.tw-mini .tw-mini-p .tw-mono{ font-size:15px; }
.tw-mini-name{
  max-width:100%; font-size:11.5px; font-weight:600; color:var(--text); line-height:1.2;
  text-align:center; white-space:normal; overflow-wrap:break-word;   /* founder 2026-07-13: имена НЕ обрезать — перенос до 2 строк */
  min-height:2.4em; display:flex; align-items:center; justify-content:center;
}
.tw-mini-occ{ font-size:10px; color:#c8bce8; line-height:1.15; text-align:center; }
.tw-mini-md{ font-size:10px; color:var(--hint); }

/* tier chip — words only, no similarity percentages (doctrine) */
.onb-twin .tw-tier{
  flex:none; padding:2px 8px; border-radius:10px; max-width:100%;   /* был 52% — ellipsis прятал хвост чипа; теперь wrap в .tw-top, кап только на ширину карточки */
  font-size:10px; font-weight:800; letter-spacing:.4px; text-transform:uppercase; white-space:nowrap;
  overflow:hidden; text-overflow:ellipsis;
}
.onb-twin-card[data-tier="date"]   .tw-tier{ background:rgba(179,136,255,.14); color:var(--accent);  border:1px solid rgba(179,136,255,.35); }
.onb-twin-card[data-tier="solar"]  .tw-tier{ background:rgba(255,217,138,.12); color:var(--gold);    border:1px solid rgba(255,217,138,.32); }   /* gold dosed: CTA stays the brightest gold */
.onb-twin-card[data-tier="cosmic"] .tw-tier{ background:rgba(255,126,182,.14); color:var(--accent2); border:1px solid rgba(255,126,182,.38); }

.onb-twin .tw-bridge{
  margin-top:8px; font-size:clamp(11.5px, 3.3vw, 12.5px); font-weight:600; line-height:1.3;
  color:var(--accent);
}
.onb-twin .tw-bridge .tw-arrow{ display:inline-block; margin-left:3px; }

.onb-twin .tw-foot{ display:flex; align-items:center; justify-content:space-between; gap:10px; margin-top:6px; }
/* honesty badge — mandatory on every card («расчёт по дате · без времени рождения») */
.onb-twin .tw-badge{ font-size:10px; color:var(--hint); opacity:.75; line-height:1.3; min-width:0;
  display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden;
  white-space:normal; }

/* ---- .twin-portrait — «звёздный портрет»: monogram + sign glyph, NO photo.
   Element gradients: mid stop of each = the exact --el of [data-el] tokens
   (styles.css [data-el] block), so the palette matches the Личность spheres;
   --el-glow arrives by itself from the global [data-el] attribute. ---- */
.twin-portrait{
  position:relative; flex:none; width:48px; height:48px; border-radius:50%;
  display:flex; align-items:center; justify-content:center;
  box-shadow:0 0 14px 1px var(--el-glow, rgba(179,136,255,.30)),
             inset 0 1px 0 rgba(255,255,255,.35);
}
.twin-portrait .tw-mono{
  font-size:20px; font-weight:800; line-height:1; color:#1a1030;   /* same dark ink as on the gold CTA */
}
.twin-portrait .tw-glyph{
  position:absolute; right:-2px; bottom:-2px; width:17px; height:17px; border-radius:50%;
  display:flex; align-items:center; justify-content:center;
  font-size:10px; line-height:1; color:#fff;
  background:rgba(15,12,29,.85); border:1px solid var(--line);
}
.twin-portrait[data-el="fire"]{  background:radial-gradient(120% 120% at 30% 25%, #ffc9a8 0%, #ff8a5c 55%, #c2582f 100%); }
.twin-portrait[data-el="earth"]{ background:radial-gradient(120% 120% at 30% 25%, #a9f2d0 0%, #5be3a7 55%, #2f9067 100%); }
.twin-portrait[data-el="air"]{   background:radial-gradient(120% 120% at 30% 25%, #c4e9ff 0%, #6fd0ff 55%, #3d84b6 100%); }
.twin-portrait[data-el="water"]{ background:radial-gradient(120% 120% at 30% 25%, #b3c6ff 0%, #5b8cff 55%, #3556bd 100%); }

/* ---- .twin-dots — twin switcher (1–3); JS hides the group for a single twin ---- */
.twin-dots{ display:flex; align-items:center; gap:4px; flex:none; }
.twin-dots .tw-dot{
  width:22px; height:22px; padding:0; border:0; background:none; cursor:pointer;   /* tap target ≥22px */
  display:flex; align-items:center; justify-content:center;
}
.twin-dots .tw-dot::before{
  content:""; width:6px; height:6px; border-radius:6px;
  background:rgba(255,255,255,.22); transition:background .15s, width .15s;
}
.twin-dots .tw-dot.on::before{ width:16px; background:var(--accent); }

/* ---- reduce motion — both channels, like the rest of onboarding:
   the media query AND the JS budget class .onb-redesign.rm ---- */
@media (prefers-reduced-motion:reduce){
  .onb-twin{ transition:none !important; animation:none !important; }
  .onb-twin .tw-row, .onb-twin-card{ transition:none !important; transform:none !important; opacity:1 !important; }
}
.onb-redesign.rm .onb-twin{ transition:none !important; animation:none !important; }
.onb-redesign.rm .onb-twin .tw-row,
.onb-redesign.rm .onb-twin-card{ transition:none !important; transform:none !important; opacity:1 !important; }

/* ---- .twin-t1 — Phase B (петля «Зеркало»): T1 share toast on the forecast screen.
   A floating card above the tabbar, product dark-card + accent CTA; the portrait
   reuses .twin-portrait (element gradient / photo / monogram+glyph) so the twin
   looks EXACTLY like the one the user just met in onboarding. ---- */
.twin-t1{
  position:fixed; left:12px; right:12px; bottom:calc(72px + var(--sab, env(safe-area-inset-bottom)));
  z-index:55; max-width:496px; margin:0 auto;
  display:flex; align-items:center; gap:11px; padding:11px 13px;
  border-radius:16px;
  background:linear-gradient(135deg,#2a2150,var(--card));
  border:1px solid var(--line);
  box-shadow:0 14px 34px -10px rgba(0,0,0,.6), 0 0 22px -8px rgba(179,136,255,.45);
  animation:tw1In .38s var(--sheet-ease);
}
.twin-t1.out{ animation:tw1Out .3s ease forwards; }
.twin-t1 .tw1-p{ width:40px; height:40px; }
.twin-t1 .tw1-p .tw-mono{ font-size:17px; }
.twin-t1 .tw1-p .tw-glyph{ width:15px; height:15px; font-size:9px; }
.twin-t1 .tw1-tx{ flex:1; min-width:0; display:flex; flex-direction:column; gap:2px; }
.twin-t1 .tw1-name{
  font-size:13.5px; font-weight:800; line-height:1.25; color:var(--text);
  overflow:hidden; display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical;   /* the NAME is the payload — wrap, never ellipsize it away on narrow phones */
}
.twin-t1 .tw1-sub{ font-size:calc(11.5px * var(--font-scale)); color:var(--hint); line-height:1.2; }
.twin-t1 .tw1-cta{
  flex:none; border:0; cursor:pointer; border-radius:12px; padding:10px 14px; min-height:38px;
  font-weight:800; font-size:13px; color:#1a1030;
  background:linear-gradient(135deg,var(--accent),var(--accent2));
  box-shadow:0 4px 14px -4px rgba(179,136,255,.55);
}
.twin-t1 .tw1-cta.sharing{ opacity:.65; }
.twin-t1 .tw1-x{
  flex:none; background:none; border:0; color:var(--hint); font-size:14px; line-height:1;
  cursor:pointer; padding:8px; margin:-8px -6px -8px -10px;   /* ≥30px tap target without widening the card */
}
@media (max-width:359px){   /* narrow/large-font phones: keep the name readable, compact the CTA */
  .twin-t1{ gap:9px; padding:10px 11px; }
  .twin-t1 .tw1-cta{ padding:9px 11px; font-size:12.5px; }
  .twin-t1 .tw1-sub{ display:none; }
}
@keyframes tw1In{ from{ transform:translateY(130%); opacity:0 } to{ transform:none; opacity:1 } }
@keyframes tw1Out{ to{ transform:translateY(130%); opacity:0 } }
@media (prefers-reduced-motion:reduce){
  .twin-t1{ animation:none !important; }
  .twin-t1.out{ animation:none !important; opacity:0; }
}

/* подсказка «дозаполни поля» под активной CTA онбординга (?v=351) */
.onb-redesign .onb-more-hint{ text-align:center; margin:11px 0 0; font-size:12.5px;
  color:var(--hint,#9b91c4); opacity:.9; }

/* сияние-подсказка на пустых дне/месяце онбординга (?v=353): золотое кольцо с мягким
   пульсом, гаснет по мере заполнения (класс уходит при ререндере пикера) */
.onb-redesign .date-grid .dp-cell{ display:block; position:relative; min-width:0; }
/* ореол на ::after ОБЁРТКИ (span) — iOS WebKit не рисует box-shadow на нативных select */
.onb-redesign .date-grid .dp-cell.dp-glow > select{ border-color:rgba(255,217,138,.60); }
.onb-redesign .date-grid .dp-cell.dp-glow::after{
  content:""; position:absolute; inset:0; border-radius:13px; pointer-events:none;
  /* базовый ореол ЖИВЁТ БЕЗ анимации (Reduce Motion / любой сбой пульса) */
  box-shadow:0 0 14px 4px rgba(255,217,138,.45), 0 0 34px 10px rgba(255,200,110,.25);
  animation:dpGlowPulse 1.6s ease-in-out infinite;
}
/* именно СВЕЧЕНИЕ (излучающий ореол со spread), не обводка: дышит амплитудой */
@keyframes dpGlowPulse{
  0%,100%{ box-shadow:0 0 10px 2px rgba(255,217,138,.30), 0 0 26px 7px  rgba(255,200,110,.16); }
  50%    { box-shadow:0 0 20px 6px rgba(255,217,138,.65), 0 0 48px 16px rgba(255,200,110,.38); }
}
@media (prefers-reduced-motion: reduce){
  .onb-redesign .date-grid .dp-cell.dp-glow::after{ animation:none; }   /* статичный ореол из базового правила */
}

/* время/город рождения спрятаны до взрыва (?v=359) */
.onb-redesign #onb-extra.onb-extra-hidden{ display:none; }

/* ============================================================================
   ПРОФИЛЬ · РЕДАКТОР «возвращение» — .onb-redesign.onb-editor (?v=433)
   Третий модификатор шелла онбординга, НЕ .onb-addperson: у того
   margin-bottom:-70px компенсирует СКРЫТЫЙ таб-бар, а здесь таб-бар ВИДЕН и
   #screen честно держит свои 90px — минус-70 положил бы контент на таб-бар.
   Язык честности (styles.css:1513 «gold astra ✦ = subscribe · dashed violet =
   add data»): ЗАФИКСИРОВАННОЕ = притопленная гравюра (.onb-field-fixed, только
   inset-тень, без свечения), НЕДОСТАЮЩЕЕ = пунктирная фиолетовая карточка
   (.onb-field-add — тот же язык, по которому юзер сюда и тапнул), ЗОЛОТО =
   только CTA и подсказка гейта. Ни одного 🔒 и ни одной ✦ на данных рождения.
   Контракт разметки (app.js: peHead/peFreeGroup/peBirthGroup/peDock):
     <div class="onb-redesign onb-editor[ onb-editor-corr]">
       <div class="onb-content">
         <header class="onb-edit-head"> .onb-edit-ava · h1.onb-kicker.onb-edit-h1
                                       · p.onb-edit-name>.who#pe-who · p.onb-edit-sub
         <div class="onb-form" onclick=onbFormTap>   ← класс ОБЯЗАТЕЛЕН (kb-open / native kb-visible)
           p.onb-grp-cap · .field… · section.onb-fixed-group(.onb-field-fixed |
             .onb-field-add[.is-target] > .onb-fix-sub · footer.onb-fixed-foot)
           .onb-cta-wrap.onb-cta-dock (button#pe-save.btn.onb-cta + #pe-hint + #pe-more|ghost)
         <footer class="onb-edit-danger"> — ТОЛЬКО у чужих профилей, ВНЕ липкого дока
   ============================================================================ */
.onb-redesign.onb-editor{
  /* скрим дока: у онбординга он цвета КОСМОСА (9,7,20), а тут космоса нет и на
     фоне приложения (--bg:#0f0c1d) та же полоса читалась бы как чёрная плашка */
  --onb-cta-scrim:15,12,29;
}

/* ---- шапка: «чей это профиль» отвечает ИМЯ, а h1 держит стабильный текст ----
   manageScreenFocus() сравнивает #screen h1 и при изменении ПЕРЕВОДИТ ФОКУС на
   заголовок (а iOS Telegram WebView скроллит фокус в вид даже с preventScroll) —
   живое имя в h1 дёргало бы экран в начало на первом же тумблере после
   переименования. Поэтому имя живёт в <p>, а h1 сжат до кикера. */
.onb-editor .onb-edit-head{ padding:2px 2px 12px; }
.onb-editor .onb-edit-ava{
  width:44px; height:44px; border-radius:50%; flex:none; overflow:hidden; margin:0 0 10px;
  display:flex; align-items:center; justify-content:center;
  background:var(--bg2); border:1px solid var(--line);
}
.onb-editor .onb-edit-ava img{ width:100%; height:100%; object-fit:cover; display:block; }
.onb-editor .onb-edit-ava .acc-ava-ph{ font-size:22px; line-height:1; opacity:.95; }
.onb-redesign.onb-editor .onb-edit-h1{
  /* золото зарезервировано за CTA → кикер экрана тихий (у онбординга он var(--warn)) */
  color:var(--hint); opacity:.9; letter-spacing:1.6px; margin:0 0 6px;
}
/* R2-MAJ-11: имя — единственный ответ на «чей это профиль», и при одном длинном НЕРАЗРЫВНОМ
   слове (слитно введённое имя/ник) оно вылезало за правый край и молча срезалось
   (body{overflow-x:hidden}) — на 320dp до 80px за экраном. Лечение то же, что уже стоит на
   .ro-val.ro-tap > span (R1-MIN-3): перенос ВНУТРИ слова как последнее средство. */
.onb-editor .onb-edit-name{
  margin:0; font-size:24px; font-weight:800; letter-spacing:-.4px; line-height:1.2;
  min-width:0; overflow-wrap:anywhere; word-break:break-word;
}
.onb-editor .onb-edit-name .who{
  background:linear-gradient(100deg,#fff6df 0%,#ffd98a 55%,#e8b45c 100%);
  -webkit-background-clip:text; background-clip:text;
  -webkit-text-fill-color:transparent; color:transparent;
}
@supports not ((-webkit-background-clip:text) or (background-clip:text)){
  .onb-editor .onb-edit-name .who{ background:none; color:#ffd98a; -webkit-text-fill-color:#ffd98a; }
}
/* wrap, НЕ nowrap как .onb-values: на ru/de/tr/vi «💞 Партнёр · ♌ Лев · 12 августа 1994»
   в 320–400dp в одну строку не влезает */
.onb-editor .onb-edit-sub{
  display:flex; flex-wrap:wrap; gap:4px 10px; margin:8px 0 0;
  font-size:13px; color:var(--hint);
}
.onb-editor .onb-edit-sub > span{ white-space:nowrap; }

/* ---- каптион группы ---- */
.onb-editor .onb-grp-cap{
  margin:18px 2px 6px; font-size:12px; font-weight:700; letter-spacing:.8px;
  text-transform:uppercase; color:var(--hint); opacity:.85;
}
.onb-editor .onb-fixed-group{ display:block; }
.onb-editor .onb-fixed-foot{ display:block; margin:8px 2px 4px; }
.onb-editor .onb-fixed-foot .hint{
  display:block; margin:6px 0 0; font-size:12.5px; line-height:1.4;
  overflow-wrap:anywhere;   /* длинные локали переносятся, а не режутся */
}

/* ---- ГРАВЮРА: значение зафиксировано (притоплено), без внешней тени и свечения ---- */
.onb-redesign.onb-editor .onb-field-fixed{
  background:color-mix(in srgb, var(--bg2) 70%, transparent);
  border-color:var(--line);
  box-shadow:inset 0 1px 0 rgba(0,0,0,.35);
  backdrop-filter:none; -webkit-backdrop-filter:none;
}
/* ОБЯЗАТЕЛЬНЫЙ глушитель: .onb-redesign .field:focus-within подсвечивает карточку как
   редактируемое поле — на залоченной строке (role=button, она получает фокус по тапу)
   это родило бы второй мёртвый тап «поле выглядит открытым, а править нечего». */
.onb-redesign.onb-editor .onb-field-fixed:focus-within{
  background:color-mix(in srgb, var(--bg2) 70%, transparent);
  border-color:var(--line);
  box-shadow:inset 0 1px 0 rgba(0,0,0,.35);
}
.onb-editor .onb-field-fixed .ro-val{ background:rgba(0,0,0,.18); border-color:rgba(255,255,255,.06); }
/* .ro-val.ro-tap:active (styles.css:1299) СОХРАНЯЕТСЯ — палец обязан видеть, что его услышали */

/* ---- ПУНКТИР: недостающее можно дополнить (тот же язык, что .pers-suppressed/.tf-addtime) ---- */
.onb-redesign.onb-editor .onb-field-add{
  border:1px dashed rgba(179,136,255,.5);
  background:rgba(255,255,255,.02);
  box-shadow:none;
}
.onb-editor .onb-field-add > label{ color:#c9bcf0; }
/* интент входа: кольцо на карточке, за которой человек пришёл (openProfileEdit(pid, want)).
   Свой фиолетовый keyframe, а НЕ dpGlowPulse: тот золотой, а золото у нас = премиум/CTA. */
.onb-redesign.onb-editor .onb-field-add.is-target{ position:relative; }
.onb-redesign.onb-editor .onb-field-add.is-target::after{
  content:""; position:absolute; inset:-2px; border-radius:20px; pointer-events:none;
  box-shadow:0 0 0 1px rgba(179,136,255,.55), 0 0 16px 4px rgba(179,136,255,.26);
  animation:peTargetRing 1.8s ease-in-out infinite;
}
@keyframes peTargetRing{
  0%,100%{ box-shadow:0 0 0 1px rgba(179,136,255,.40), 0 0 12px 2px rgba(179,136,255,.16); }
  50%    { box-shadow:0 0 0 1px rgba(179,136,255,.70), 0 0 24px 7px rgba(179,136,255,.34); }
}
@media (prefers-reduced-motion: reduce){
  .onb-redesign.onb-editor .onb-field-add.is-target::after{ animation:none; }   /* статичное кольцо из базового правила */
}
/* вложенный подблок «Добавить год» ВНУТРИ карточки даты: одна карточка — один факт */
.onb-redesign.onb-editor .onb-fix-sub{
  margin-top:12px; padding-top:12px; border-top:1px solid var(--line);
}
.onb-redesign.onb-editor .onb-fix-sub > label{
  display:block; font-size:12.5px; font-weight:600; color:var(--hint);
  margin-bottom:8px; letter-spacing:.2px;
}

/* ---- красная подсказка правила 9: у .hint.err правил в файле НЕТ ВООБЩЕ (была серой) ---- */
.onb-hint-err{
  display:flex; gap:6px; align-items:flex-start; margin:9px 0 0;
  color:var(--bad); font-size:12.5px; font-weight:600; line-height:1.4;
}
/* ---- предупреждение режима коррекции: ЗОЛОТОЕ (внимание/ценность), не красное (ошибка) ---- */
.onb-redesign.onb-editor .onb-corr-note{
  margin:0 0 14px; padding:12px 14px; border-radius:14px;
  border:1px solid rgba(255,217,138,.28); background:rgba(255,217,138,.07);
  color:#ffd98a; font-size:13px; font-weight:600; line-height:1.45;
}

/* ---- липкий док НАД ВИДИМЫМ таб-баром (рецепт .pw-cta): реальную высоту .tabbar
   (растёт от safe-area и OS font-scale) JS кладёт в --pe-tabbar-h при каждом рендере.
   max(…, --sab): скрытый таб-бар честно даёт 0px → кнопка возвращается на 8px от низа,
   но не заезжает в нижний вырез. Таб-бар НЕ скрываем: Back возвращает в таб, и мигание
   бара дралось бы с showApp. ---- */
.onb-redesign.onb-editor .onb-cta-wrap{
  position:sticky;
  /* R3-MAJ-3: ВПЛОТНУЮ к таб-бару, БЕЗ прежних +8px. Скрим онбординга нарисован под
     bottom:0 — его крайние стопы ПРОЗРАЧНЫЕ, потому что нижний просто уходит за кадр.
     Поднятый док вывел эту прозрачную полосу НА экран: под золотой кнопкой (и над ней)
     сквозь док просвечивала рамка карточки «Добавить время», и это читалось как глюч
     («кнопка лежит на карточке»), а не как «контент уходит под скрим». Теперь воздух
     живёт ВНУТРИ дока (padding-bottom), а сам док кончается там, где начинается бар. */
  bottom:max(var(--pe-tabbar-h, calc(54px + var(--sab, env(safe-area-inset-bottom, 0px)))), var(--sab, env(safe-area-inset-bottom, 0px)));
  padding-bottom:14px;   /* --sab уже учтён в измеренной высоте таб-бара (--pe-tabbar-h) */
  /* R3-BLOCKER-1 · СКРИМ НЕПРОЗРАЧЕН. Полупрозрачный градиент оставлял под кнопкой
     ВИДИМЫЕ строки («✎ Исправить ›», тумблер, select года) — палец шёл в них и попадал
     в «Сохранить»: вместо листа коррекции запускался пересчёт и юзера выбрасывало с
     экрана. Что не видно — в то не тапают: сплошной фон приложения (тот же rgb(15,12,29),
     body::before к низу экрана уже полностью прозрачен → шва нет) и только верхние ~26%
     остаются мягким переходом «контент уходит под док». */
  background:linear-gradient(to top,
    rgba(var(--onb-cta-scrim),1) 0%,
    rgba(var(--onb-cta-scrim),1) 74%,
    rgba(var(--onb-cta-scrim),.86) 88%,
    rgba(var(--onb-cta-scrim),0) 100%);
}
/* R3-BLOCKER-16 · НАТИВ / КОРОТКИЙ ЭКРАН: док ОТКЛЕИВАЕТСЯ, когда в прилипшем виде он
   накрыл бы ПЕРВОЕ поле формы. Класс ставит JS (_peAfterRender) по РЕАЛЬНОЙ геометрии:
   медиа-правило ниже мерит высоту ОКНА, а в нативном приложении топбар (54+--sat) и
   таб-бар (54+--sab) съедают ~140px — на 320×568 native полезной высоты 369px, то есть
   порог 480px не срабатывал, и тап по центру видимого «Твоё имя» попадал в «Сохранить».
   Геометрия учитывает и OS font-scale, и длину локали, и вырез — без магических цифр. */
.onb-redesign.onb-editor.onb-dock-static .onb-cta-wrap{ position:static; }
/* R2-MAJ-13 · НИЗКИЙ ВЬЮПОРТ (телефон в ландшафте: 667×375, 812×375, 568×320) — док
   ОТКЛЕИВАЕТСЯ. Механика sticky: элемент остаётся в потоке, но визуально подтягивается к
   своей линии прилипания в пределах содержащего блока — а содержащий блок это .onb-form,
   и он высокий. Когда видимая часть формы короче самого дока, «золотая Сохранить»
   встаёт НА первую карточку: elementFromPoint(центр #pe-name) возвращал pe-save, то есть
   тап по имени попадал в Save (сохранение + уход с экрана), а в 568×320 кнопка уезжала
   ещё и на 10px ПОД таб-бар. В онбординге тот же зажим не виден, потому что там кнопка
   при disabled скрыта, а здесь она по решению спеки видна ВСЕГДА.
   Порог 480px: 320×568/360×740/400×860 (портрет, критерий A10) и проверенные 360×500,
   320×480 остаются липкими; всё, что ниже, честно кладёт кнопку в конец формы —
   перекрытия нет ни при каком скролле, #screen сам держит запас под таб-баром.
   max-height реагирует на поворот устройства сам, без JS-замера. */
@media (max-height:480px){
  .onb-redesign.onb-editor .onb-cta-wrap{ position:static; }
}
/* Кнопку НЕ прячем (осознанное расхождение с онбордингом, где #onb-submit[disabled]
   display:none): там кнопки «ещё не было», здесь она ЯКОРЬ экрана, а живой гейт имени
   переключает disabled на каждой букве — исчезающая кнопка дёргала бы липкий док.
   Каждое disabled-состояние снабжено видимой причиной (#pe-hint). */
.onb-redesign.onb-editor .onb-cta[disabled]{
  opacity:.45; animation:none; filter:grayscale(.4); cursor:default;
  box-shadow:0 0 0 1px var(--line) inset;
}
.onb-redesign.onb-editor .onb-corr-back{ margin:10px 0 0; }

/* ---- удаление: тихая деструктивная ссылка ОТДЕЛЬНЫМ футером, вне липкого дока ---- */
/* R2-MIN-14: воздух снизу. #screen держит фиксированные padding-bottom:90px, а НАТИВНЫЙ
   таб-бар это контент + safe-area (54+34 = 94px при --sab:34px) — последняя строка честного
   пояснения об удалении ложилась ВПЛОТНУЮ к бару (зазор 0px), а при --sab:50px уходила под
   него совсем. Спека требовала ≥24px воздуха у деструктивного футера, и он был только сверху.
   Дока это не касалось (он мерит --pe-tabbar-h) — страдает только контент ПОСЛЕ дока, а он
   есть исключительно у чужих профилей. В Telegram (--sab:0) правило добавляет 24px запаса. */
.onb-editor .onb-edit-danger{
  margin:30px 2px 4px; text-align:center;
  padding-bottom:calc(24px + var(--sab, env(safe-area-inset-bottom, 0px)));
}
.onb-editor .del-link{
  display:inline-block; margin:0; padding:8px 6px; border:0; background:none;
  font-family:inherit; font-size:14px; font-weight:600; color:var(--bad);
  text-decoration:underline; text-underline-offset:3px; cursor:pointer;
  -webkit-tap-highlight-color:transparent;
}
.onb-editor .del-link:active{ opacity:.6; }
.onb-editor .onb-edit-danger .hint{
  margin:8px 0 0; font-size:12.5px; line-height:1.4; opacity:.9;
}

/* ============================================================================
   R1-MIN-22 · ЭКРАН УВАЖАЕТ РАЗМЕР ШРИФТА ПОЛЬЗОВАТЕЛЯ (--font-scale 0.9…1.30)
   Редактор наследовал от .onb-redesign чисто пиксельный язык (спека предписывала
   переиспользование), и НИ ОДИН размер не менялся при --font-scale:1.3. Хуже
   того, `.onb-editor .onb-fixed-foot .hint{12.5px}` перебивал глобальный
   масштабируемый `.hint{calc(14px*var(--font-scale))}` — именно абзацы честности
   становились единственным немасштабируемым текстом экрана.
   Всё умножено на var(--font-scale) и СТРОГО в области .onb-editor: живой
   онбординг (прод) не затронут ни на байт. Липкий док растёт вместе с текстом, а
   его отступ считается от ИЗМЕРЕННОЙ высоты таб-бара (--pe-tabbar-h) — кнопка
   остаётся над баром на любом масштабе (A10/A24).
   ============================================================================ */
.onb-redesign.onb-editor .onb-edit-h1{ font-size:calc(11.5px * var(--font-scale)); }
.onb-redesign.onb-editor .onb-edit-name{ font-size:calc(24px * var(--font-scale)); }
.onb-editor .onb-edit-ava .acc-ava-ph{ font-size:calc(22px * var(--font-scale)); }
.onb-redesign.onb-editor .onb-edit-sub{ font-size:calc(13px * var(--font-scale)); }
.onb-redesign.onb-editor .onb-grp-cap{ font-size:calc(12px * var(--font-scale)); }
.onb-redesign.onb-editor .onb-fixed-foot .hint,
.onb-redesign.onb-editor .onb-edit-danger .hint{ font-size:calc(12.5px * var(--font-scale)); }
.onb-redesign.onb-editor .onb-fix-sub > label{ font-size:calc(12.5px * var(--font-scale)); }
.onb-editor .onb-hint-err{ font-size:calc(12.5px * var(--font-scale)); }
.onb-redesign.onb-editor .onb-corr-note{ font-size:calc(13px * var(--font-scale)); }
.onb-editor .del-link{ font-size:calc(14px * var(--font-scale)); }
/* наследованное от .onb-redesign — переопределяем ТОЛЬКО внутри редактора */
.onb-redesign.onb-editor .field > label{ font-size:calc(13px * var(--font-scale)); }
.onb-redesign.onb-editor .field label .opt{ font-size:calc(12px * var(--font-scale)); }
.onb-redesign.onb-editor input[type=text],
.onb-redesign.onb-editor input[type=time],
.onb-redesign.onb-editor select{ font-size:calc(16px * var(--font-scale)); }
/* R3-MIN-17: ТРИ селекта пикера даты делят одну строку (.date-grid), их ширина задана
   сеткой и от --font-scale НЕ растёт — масштабирование шрифта загоняло «Année»/«Tahun»
   под шеврон (fr/320dp/fs1.3: тексту 60px при 42px внутренних). Ограничиваем размер ещё и
   ДОСТУПНОЙ ШИРИНОЙ (vw): при 400dp+ масштаб работает как раньше, на узких экранах текст
   остаётся внутри своей ячейки. Полноширинный #pe-addyear правило не трогает.
   Наследованная от онбординга обрезка на fr/320dp при fs1 тоже уходит: min() опускает
   размер до ~14px там, где 16px не влезали. */
.onb-redesign.onb-editor .date-grid select{ font-size:clamp(13px, 4.4vw, calc(16px * var(--font-scale))); }
/* R3-MIN-18: плитки пола делят строку на ТРИ колонки, ширина от --font-scale не растёт —
   при 320dp/fs1.3 «Женский»/«Femme» требовали 90px при 63px внутренних, и overflow-wrap:anywhere
   рвал слово по произвольной букве («Femm|e», «Женск|ий»). Тот же приём, что у пикера даты:
   размер ограничен ДОСТУПНОЙ ШИРИНОЙ, поэтому слово влезает целиком и рвать нечего.
   СТРОГО в области редактора — онбординг на проде не затронут (дефект там наследованный,
   но менять живой экран этой задачей нельзя). */
.onb-redesign.onb-editor .choice{ font-size:clamp(12.5px, 4.4vw, calc(16px * var(--font-scale))); }
.onb-redesign.onb-editor .toggle-row .tr-label{ font-size:calc(14px * var(--font-scale)); }
/* R2-MAJ-12: масштабируемая подпись тумблера в наследованной раскладке строки
   (.onb-redesign .toggle-row{justify-content:flex-end} + .tr-label{flex:none}) держала
   max-content-ширину и выдавливала своё НАЧАЛО за левый край карточки и экрана — «Je ne
   connais pas l’heure exacte» на fr/320dp/fs1.3 начиналась на 43px левее вьюпорта. Разрешаем
   ей сжаться и перенестись (свитч по-прежнему прижат вправо, порядок не меняется).
   СТРОГО в области редактора: в онбординге подпись не масштабируется и не переполняется. */
.onb-redesign.onb-editor .toggle-row .tr-label{
  flex:0 1 auto; min-width:0; text-align:right; overflow-wrap:anywhere; line-height:1.3;
}
.onb-editor .ro-val{ font-size:calc(15px * var(--font-scale)); }
.onb-editor .ro-cue{ font-size:calc(13px * var(--font-scale)); }
.onb-redesign.onb-editor .onb-cta{ font-size:calc(17px * var(--font-scale)); min-height:calc(58px * var(--font-scale)); }
.onb-redesign.onb-editor .onb-disabled-hint{ font-size:calc(12.5px * var(--font-scale)); }


/* адаптация текстов карточки близнеца на узких экранах (?v=372) */
@media (max-width:360px){
  .onb-twin .tw-label{ letter-spacing:1.1px; }
  .onb-twin .tw-tier{ font-size:9px; padding:2px 7px; }   /* «SAME DAY & YEAR» целиком; wrap теперь в базовом .tw-top */
  .onb-twin .tw-name{ white-space:normal; }              /* имя в 2 строки, не «…» */
  .onb-twin .tw-foot{ flex-wrap:wrap; }
  .onb-twin .tw-badge{ flex:1 1 100%; -webkit-line-clamp:3; }
}

/* подтверждение выбора дня/месяца: вспышка сияния (?v=373) */
.onb-redesign .date-grid .dp-cell.dp-blink::after{
  content:""; position:absolute; inset:0; border-radius:13px; pointer-events:none;
  animation:dpBlinkA 420ms ease-out forwards;
}
@keyframes dpBlinkA{
  0%  { box-shadow:0 0 22px 8px rgba(255,217,138,.75), 0 0 52px 18px rgba(255,200,110,.42); opacity:1; }
  100%{ box-shadow:0 0 10px 2px rgba(255,217,138,0),   0 0 26px 7px  rgba(255,200,110,0);   opacity:0; }
}
/* знак Солнца справа от имени: место зарезервировано с рендера (пустой слот той же ширины) */
.onb-redesign .onb-title .onb-nb{ white-space:nowrap; }
.onb-redesign .onb-title[data-nm=""] .onb-sun-slot{ display:none; }   /* знак Солнца — у ИМЕНИ; без имени висел у «life» и обрезался краем экрана */
/* Слот НУЛЕВОЙ ширины: глиф висит справа от последнего слова и в переносе строк не участвует.
   С min-width:1.02em слот не влезал в строку и уезжал на невидимую вторую (пустота под
   заголовком), а приклеенный к слову — тянул на вторую строку и само слово (основатель 2026-10-11). */
.onb-redesign .onb-title .onb-sun-slot{
  display:inline-block; width:0; min-width:0; margin-left:0; text-indent:.32em; white-space:nowrap;
  overflow:visible; transform-origin:.8em 50%; vertical-align:baseline;
  color:#ffd98a; font-size:.82em; line-height:1; text-shadow:0 0 14px rgba(255,217,138,.5);
  opacity:0; transform:scale(.6); transition:opacity .3s ease, transform .3s ease;
}
.onb-redesign .onb-title .onb-sun-slot.on{ opacity:1; transform:none; }
.onb-redesign .onb-title .onb-sun-slot.pop{ animation:sunPop 380ms cubic-bezier(.2,1.4,.4,1); }
@keyframes sunPop{ 0%{ transform:scale(.4); } 60%{ transform:scale(1.3); } 100%{ transform:scale(1); } }
/* летящая звезда дата → имя */
.onb-flystar{
  position:fixed; z-index:50; pointer-events:none; color:#ffd98a; font-size:22px;
  text-shadow:0 0 16px rgba(255,217,138,.85), 0 0 34px rgba(255,200,110,.4);
  transition:transform 680ms cubic-bezier(.3,.7,.25,1), opacity 680ms ease; will-change:transform;
}
@media (prefers-reduced-motion: reduce){ .onb-flystar{ display:none; } }

/* === GOLD TICKET promo (?v=389) ==================================================
   «Золотой билет» — промо-капсула «−60%» справа от «+» в шапке Прогноза (30-мин окно,
   MM:SS-таймер, честное сгорание). Капсула — АБСОЛЮТНЫЙ сосед .people-bar внутри
   relative-обёртки .fc-topbar, НЕ внутри самой .people-bar (та overflow-x:auto и
   заклипила бы свечение). Слои:
     .promo-cap        фон #1E1740 + «свеча» + градиентный КОНТУР (двойной background
                       border-box/padding-box — техника как у градиента #onb-submit);
     .promo-cap::before пульсирующее свечение: ГОТОВАЯ тень, анимируется ТОЛЬКО её
                       opacity (никакой анимации box-shadow — правка основателя);
     .promo-clip::after диагональный IDLE-блик (transform-only). Блик живёт на
                       внутреннем клип-слое из разметки (пустой span), а не на ::after
                       капсулы: overflow:hidden на капсуле срезал бы тень ::before,
                       а без клипа блик мазал бы золотом мимо скруглённых углов. */
.fc-topbar{ position:relative; }
/* при видимой капсуле хвост строки профилей получает место под неё: капсула стартует на
   135px (11 паддинг + 52 чип + 10 гэп + 52 «+» + 10 отступ), правый край скролл-контента
   останавливается на 133px — последний чип целиком выезжает из-под капсулы влево.
   Пересчитано 2026-08-03 вместе с усадкой чипа 60→52 и гэпа 12→10. */
.fc-topbar.has-promo .people-bar{ padding-right:calc(100% - 133px); }
/* ≥2 профилей (.promo-stack ставит peopleBar()): зона слева от капсулы (155px) вмещает ровно
   [чип][+] — второй человек уводил «+» ЦЕЛИКОМ под непрозрачную капсулу (тап по «+» открывал
   промо-пейвол). Капсула опускается второй строкой на всю ширину, чипы получают всю ширину назад. */
.fc-topbar.has-promo.promo-stack .people-bar{ padding-right:11px; }
.fc-topbar.has-promo.promo-stack .promo-cap{
  position:relative; top:auto; transform:none; left:0; right:auto; margin-top:-6px; margin-bottom:10px;
  width:100%; justify-content:center;   /* .fc-topbar уже живёт в 16px-паддинге экрана → капсула выравнивается по карточкам */
}
/* сверхузкие экраны (<360px): в зоне справа от «+» текстовой колонке не остаётся места
   (149px − бейдж) → капсула ВСЕГДА уходит в свою полноширинную строку, как при 2+ профилях */
@media (max-width:359px){
  .fc-topbar.has-promo .promo-cap{
    position:relative; top:auto; transform:none; left:0; right:auto; margin-top:-6px; margin-bottom:10px;
    width:100%; justify-content:center;
  }
  .fc-topbar.has-promo .promo-cap .promo-body{ flex:0 1 auto; }
  .fc-topbar.has-promo .people-bar{ padding-right:11px; }
}
.fc-topbar.has-promo.promo-stack .promo-cap .promo-body{ flex:0 1 auto; }
/* iOS «Премиум» (основатель 2026-10-11): та же золотая капсула «Золотого билета», но компактной
   пилюлей у правого края — без скидки и таймера, просто видимый вход в покупку. Центр по кружкам
   профилей (33px: top 11 + 44/2). Строка профилей резервирует ей хвост (≈ ширина пилюли + гэп),
   при многих людях чипы скроллятся из-под неё. */
.fc-topbar.has-prem .people-bar{ padding-right:150px; }
.fc-topbar.has-prem .promo-cap.prem-cap{
  left:auto; right:0; top:11px; min-height:44px; width:auto; max-width:46%;
  padding:5px 14px 5px 5px; gap:9px; border-radius:22px;
}
/* ✦ — SVG той же формы, что премиальная «Астра» (#pg-star), а не символ шрифта: глиф U+2726
   в iOS рисуется заметно мельче, чем в Chromium (основатель 12.10: «всё ещё мелкий»). */
.promo-cap.prem-cap .promo-badge{ min-width:36px; width:36px; height:36px; padding:0; border-radius:18px; display:flex; align-items:center; justify-content:center; }
.promo-cap.prem-cap .promo-badge svg{ width:24px; height:24px; display:block; fill:#1E1740; }
.promo-cap.prem-cap .promo-title{ font-size:15px; white-space:nowrap; }

.fc-topbar.has-promo.promo-stack .promo-cap:active{ transform:scale(.98); }

.promo-cap{
  /* top:4: при базовой высоте 58 центр капсулы = 4+29 = 33px = центр кружков (padding 9 +
     ava 48/2 = 33). Пересчитывалось дважды за 2026-08-03: сперва под усадку аватара 54→44
     (было top:6 при кружках 58), затем под усадку самой капсулы 68→58. min-height вместо height — при OS font-scale строки ПЕРЕНОСЯТСЯ и капсула
     растёт ВНИЗ (top-якорь: рост вверх уводил бы её за край экрана — шапка у самого верха).
     -webkit-text-size-adjust:100% глушит iOS-инфляцию текста (перв. источник обрезания). */
  position:absolute; top:4px; margin-top:0;
  left:135px; right:16px; min-height:58px;
  -webkit-text-size-adjust:100%; text-size-adjust:100%;
  z-index:5; border-radius:17px; border:1.5px solid transparent;
  display:flex; align-items:center; gap:8px;
  padding:7px 10px 7px 9px; margin-bottom:0; cursor:pointer; text-align:left; font-family:inherit;
  -webkit-appearance:none; appearance:none;
  /* фон + «свеча» сверху-справа (padding-box) + КОНТУР 1.5px градиент 135deg (border-box).
     Тёмный фон — ТОЛЬКО как linear-gradient(#1E1740,#1E1740): голый <color> в НЕпоследнем
     слое multi-layer background невалиден по CSS Backgrounds L3 — вся декларация отбрасывалась
     любым движком, капсула рендерилась дефолтной серой UA-кнопкой (QA-блокер ?v=389). */
  background:
    radial-gradient(120% 150% at 84% -12%, rgba(244,200,105,.16) 0%, rgba(244,200,105,0) 58%) padding-box,
    linear-gradient(#1E1740,#1E1740) padding-box,
    linear-gradient(135deg,#FFE9B0 0%,#F4C869 45%,#B98A3E 100%) border-box;
  /* filter .6s — плавная десатурация в пепел при .burned; transform/box-shadow .15s — TAP */
  transition:transform .15s ease, box-shadow .15s ease, filter .6s ease;
}
/* TAP: вспышка контура #FFE9B0 150ms + прожатие */
.promo-cap:active{ transform:scale(.98); box-shadow:0 0 0 1.5px #FFE9B0, 0 0 16px rgba(255,233,176,.45); }

/* ПРАВКА ОСНОВАТЕЛЯ 1 — свечение сильнее по бокам и ПОСТОЯННО пульсирует.
   Тень задана целиком здесь и НЕ анимируется; дышит только opacity псевдоэлемента
   (эффективная яркость = альфа тени × opacity — крутить при тюнинге можно любую). */
.promo-cap::before{
  content:""; position:absolute; inset:0; border-radius:inherit; pointer-events:none;
  /* пульс «точно как в онбординге» (основатель, 2026-07-16): те же тайминги и тени, что
     onbk-halo у #onb-submit (без inset-блика — он для сплошной золотой заливки) */
  animation:promoHalo 5.5s ease-in-out infinite;
  transition:opacity .6s ease;   /* гашение при .burned */
}
@keyframes promoHalo{
  0%,100%{box-shadow:0 0 0 1px rgba(255,217,138,.4), 0 0 16px 2px rgba(255,217,138,.28), 0 14px 34px -10px rgba(255,217,138,.4);}
  50%{box-shadow:0 0 0 1px rgba(255,217,138,.5), 0 0 26px 6px rgba(255,217,138,.45), 0 14px 34px -8px rgba(255,217,138,.55);}
}

/* IDLE-блик: внутренний клип-слой (пустой <span class="promo-clip"> в разметке) +
   transform-only проход ::after — 1.2s движения на 7s цикла (0→17% кейфреймов) */
.promo-cap .promo-clip{
  position:absolute; inset:0; border-radius:15.5px; overflow:hidden; pointer-events:none;
  transition:opacity .6s ease;   /* гашение при .burned */
}
.promo-cap .promo-clip::after{
  content:""; position:absolute; top:-30%; bottom:-30%; left:-45%; width:38%;
  background:linear-gradient(100deg, rgba(255,233,176,0) 0%, rgba(255,233,176,.26) 50%, rgba(255,233,176,0) 100%);
  transform:translateX(0) skewX(-18deg);
  animation:promoShine 7s linear infinite;
}
@keyframes promoShine{
  0%  { transform:translateX(0)    skewX(-18deg); }
  17% { transform:translateX(460%) skewX(-18deg); }   /* полный выход за правый край */
  100%{ transform:translateX(460%) skewX(-18deg); }
}

/* БЕЙДЖ «−60%» — герой: золотая заливка, тёмный текст (инверсия капсулы).
   Anti-truncation: flex:0 0 auto + nowrap + размер от контента (только min-width) —
   при OS font-scale бейдж просто растёт; ellipsis невозможен (нет overflow:hidden). */
.promo-cap .promo-badge{
  position:relative; z-index:1; flex:0 0 auto;
  min-width:43px; padding:8px 9px; border-radius:12px; text-align:center;
  font-size:16px; font-weight:800; line-height:1; letter-spacing:-.3px;
  white-space:nowrap; font-variant-numeric:tabular-nums;
  color:#1E1740;
  background:linear-gradient(160deg,#FFE9B0 0%,#F4C869 55%,#C9973F 100%);
  box-shadow:inset 0 1px 0 rgba(255,246,220,.65), 0 2px 10px rgba(244,200,105,.28); /* статичная — не анимируется */
  transition:font-size .2s ease;
}
/* текстовый стек: min-width:0 разрешает сжатие, строки ПЕРЕНОСЯТСЯ вместо троеточия */
.promo-cap .promo-body{
  position:relative; z-index:1; flex:1 1 auto; min-width:0;
  display:flex; flex-direction:column; align-items:flex-start; gap:2px;
}
/* строка 1: «Скидка на премиум» — процент живёт в бейдже. Градиентный текст;
   -webkit-text-fill-color:transparent специально оставлен перекрываемым: burn красит
   текст пеплом ПОВЕРХ градиента одной анимируемой color-декларацией. */
.promo-cap .promo-title{
  max-width:100%; white-space:normal; overflow:visible; text-overflow:clip; overflow-wrap:break-word;
  font-size:12px; font-weight:700; letter-spacing:-.2px; line-height:1.12;
  background:linear-gradient(135deg,#FFF3D6 0%,#F4C869 100%);
  -webkit-background-clip:text; background-clip:text;
  color:#F4C869;                       /* фоллбэк без clip:text */
  -webkit-text-fill-color:transparent;
  transition:-webkit-text-fill-color .6s ease, font-size .2s ease;
}
/* строка 2: «сгорит через 29:41» — переносима; сам таймер nowrap (29:52 не рвётся) */
.promo-cap .promo-sub{
  white-space:normal;
  font-size:11px; font-weight:600; color:rgba(255,236,196,.82); line-height:1.15;
  transition:color .6s ease, font-size .2s ease;
}
/* таймер: табличные цифры + фикс-ширина под «88:88» — строка не дёргается на тиках */
/* цифры отсчёта — СРАЗУ «горящий» брендовый magenta (основатель 2026-07-16: urgency с первой
   секунды, не только в last5); лейбл «сгорит через» остаётся кремовым — контраст цифр выше */
#promo-timer{
  display:inline-block; min-width:5ch; white-space:nowrap; font-variant-numeric:tabular-nums;
  color:#FF5C8A; font-weight:800;
  text-shadow:0 0 12px rgba(255,92,138,.35);   /* мягкое горение, статичное */
  transition:font-size .2s ease, color .6s ease;
}
/* мигающие двоеточия 1Гц: резкий перескок .4↔1 (парные стопы = steps-поведение) */
.promo-colon{ display:inline-block; animation:promoColonBlink 1s linear infinite; }
@keyframes promoColonBlink{ 0%,49.9%{ opacity:1; } 50%,100%{ opacity:.4; } }

/* ПРАВКА ОСНОВАТЕЛЯ 2 — последние 5 минут: эскалация РАЗМЕРОМ и РИТМОМ, не цветом
   (никакого красного/magenta — таймер укрупняется, оффер уступает, пульс чаще) */
/* последние 5 минут: растёт только таймер (процент теперь в бейдже — title не уступает) */
.promo-cap.last5 #promo-timer{ font-size:17px; font-weight:800; }
.promo-cap.last5::before{ animation-duration:2.75s; }   /* halo-пульс чаще в последние 5 минут (база 5.5s) */

/* СГОРАНИЕ (юзер застал ноль на экране): 600ms десатурация контура+текста в пепел
   #6E6880, свечение и блик гаснут. grayscale-фильтр (анимируемый, в отличие от
   градиентных background-слоёв) ведёт контур/свечу в серый синхронно с текстом. */
.promo-cap.burned{ filter:grayscale(1) brightness(.72); }
.promo-cap.burned .promo-title{ -webkit-text-fill-color:#6E6880; color:#6E6880; }
.promo-cap.burned .promo-sub{ color:#6E6880; }
.promo-cap.burned #promo-timer{ color:#6E6880; text-shadow:none; }
.promo-cap.burned::before{ animation:none; opacity:0; }
.promo-cap.burned .promo-clip{ opacity:0; }
.promo-cap.burned .promo-colon{ animation:none; opacity:1; }
.promo-cap.burned:active{ box-shadow:none; }   /* по пеплу — без золотой вспышки */
/* схлопывание после 4с обучающей паузы (класс ставит JS) */
.promo-cap.collapse{
  /* min-height/padding обнуляем — иначе min-height:68 не даст уйти в 0 (JS пинит height inline) */
  height:0; min-height:0; padding-top:0; padding-bottom:0; margin-top:0; opacity:0; border-width:0; overflow:hidden;
  transition:height .35s ease, min-height .35s ease, padding .35s ease, opacity .35s ease, margin-top .35s ease, border-width .35s ease;
}

/* появление: fade+scale .97→1, 300ms — JS ставит класс 1 раз за сессию */
.promo-cap.promo-appear{ animation:promoCapIn 300ms ease-out; }
/* opacity-only: scale в keyframes перетирал бы translateY-центрирование на 300ms (прыжок на 34px) */
@keyframes promoCapIn{ from{ opacity:0; } to{ opacity:1; } }

/* --- пейвол v2: промо-полоса-«язычок», вплавленная в верхний край контейнера планов ---
   position:absolute top:-13px относительно .plan-grid (position:relative + overflow:visible
   контейнер держит в секции pw3, .plan-grid :1217). Узел id="pw-promo-timer"
   внутри СОХРАНЯЕТСЯ — Promo.mountPaywall() тикает его как раньше. Процент — всегда
   первый токен строки («−60% · сгорит через 29:53», урок обрезанной EN-капсулы);
   без overflow:hidden в цепочке → ellipsis структурно невозможен. Закон money-цепочки
   (build note 10, :1217): на 200% шрифте таймер НЕ обрезается и не даёт странице
   горизонтальный скролл — max-width держит пилюлю внутри вьюпорта (абсолютный
   left:50%+translateX(-50%) без ограничителя вылезал на 320px за оба края), перенос
   вместо nowrap: на узких/крупных комбо пилюля растёт второй строкой, цифры целы. */
/* .pw-promo-strip — алиас на случай, если вёрстка v2 назовёт язычок так (эскалация pw5
   уже ищет .closest(".pw-promo-strip, .pw-promo-timer") — CSS зеркалит тот же контракт) */
.pw-promo-timer, .pw-promo-strip{
  position:absolute; top:-13px; left:50%; transform:translateX(-50%); z-index:2;
  display:flex; align-items:baseline; justify-content:center; flex-wrap:wrap;
  gap:0 6px; white-space:normal; text-align:center;
  /* width:max-content — иначе abspos с left:50% шринкается к ПОЛОВИНЕ контейнера и пилюля
     переносится даже при свободном месте; max-width включает перенос только когда реально
     не влезает (320px × font-scale 2.0) */
  width:max-content; max-width:calc(100% - 8px); box-sizing:border-box;
  padding:4px 14px; border-radius:999px;
  background:linear-gradient(135deg,#3a2a4d,#4d2440);
  border:1px solid rgba(255,92,138,.5);
  font-size:12.5px; font-weight:700; color:#F4C869;
  font-variant-numeric:tabular-nums;   /* наследуется цифрами таймера внутри */
}
/* glow-слой полосы: единственное, что «дышит» в urgent/critical — и только через opacity
   (build note 9: никаких анимаций box-shadow/background, слой готов заранее) */
.pw-promo-timer::before, .pw-promo-strip::before{
  content:""; position:absolute; inset:-1px; border-radius:999px; pointer-events:none;
  box-shadow:0 0 16px 2px rgba(255,92,138,.4); opacity:0;
}
/* цифры на пейволе — тот же горящий magenta, что и на капсуле, кеглем крупнее подписи;
   nowrap: MM:SS — неделимый токен, перенос полосы (выше) не смеет разорвать цифры */
.pw-promo-timer #pw-promo-timer, .pw-promo-timer .promo-timer,
.pw-promo-strip #pw-promo-timer, .pw-promo-strip .promo-timer{
  font-size:14px; color:#FF5C8A; font-weight:800; text-shadow:0 0 12px rgba(255,92,138,.35);
  white-space:nowrap;
}
/* старая цена: v2 несёт её INLINE-зачёркнутой внутри money-строки плана
   («400 ⭐ · ~1000~ · ≈45 ₽/мес») — plan-card-скоуп снят, кегль наследуется от строки;
   в legacy-вёрстке (.pl-price 14px) inline+inherit тоже живёт. Исчезает вместе с
   таймером при 410-burn (ре-рендер buyPremium — механика не тронута). */
.pl-old{
  display:inline; font-size:inherit; font-weight:700; color:var(--hint);
  text-decoration:line-through; opacity:.55; white-space:nowrap;
}

/* узкие экраны: строка 1 капсулы («Скидка −60% ✦» и все локали) обязана влезать целиком.
   389px: при фиксированном left:155px капсулы 16px-шрифту хватает только с ~389px вьюпорта —
   старый брейк 374px оставлял iPhone-ширины 375–388 с обрезанным 16px заголовком */
/* 390–419px (iPhone 14/15/16 Pro): «Скидка на премиум»/«Descuento Premium» (17 симв.)
   на 14px впритык переносились — минус полпикселя кегля возвращает одну строку */
@media (max-width:419px){
  .promo-cap .promo-title{ font-size:11.5px; }
  .promo-cap .promo-sub{ font-size:10.5px; }
}
@media (max-width:389px){
  .promo-cap{ padding:6px 9px 6px 8px; gap:7px; }
  .promo-cap .promo-badge{ font-size:14.5px; min-width:39px; padding:7px 8px; }
  .promo-cap .promo-title{ font-size:11px; }
  .promo-cap .promo-sub{ font-size:10px; }
  .promo-cap.last5 #promo-timer{ font-size:13px; }
}
/* сверхузкие (<360px): плотнее, но защита от обрезания НЕ здесь — она в конструкции (бейдж+перенос) */
@media (max-width:359px){
  .promo-cap{ padding:5px 9px 5px 7px; gap:6px; }
  .promo-cap .promo-badge{ font-size:13.5px; min-width:36px; padding:6px 7px; border-radius:10px; }
  .promo-cap .promo-title{ font-size:10px; }
  .promo-cap .promo-sub{ font-size:9.5px; }
}

/* reduced-motion: пульс/блик/мигание off, статичное мягкое свечение остаётся */
@media (prefers-reduced-motion:reduce){
  /* без keyframes тень бы исчезла совсем (halo задаёт её только в анимации) — статичный кадр 0% */
  .promo-cap::before{ animation:none; box-shadow:0 0 0 1px rgba(255,217,138,.4), 0 0 16px 2px rgba(255,217,138,.28), 0 14px 34px -10px rgba(255,217,138,.4); }
  .promo-cap .promo-clip::after{ animation:none; display:none; }
  .promo-colon{ animation:none; opacity:1; }
  .promo-cap.promo-appear{ animation:none; }
}

/* ============================================================================
   PAYWALL v2 · «золотой момент» (paywall_spec.json, пакет pw4: CTA/trust/motion)
   Вёрстка экрана и лестница планов — секция pw3 выше (:1191, контракт разметки там):
   .pw2-screen корень · .pw2-h1/.pw2-subhead шапка · .plan-grid[.pw2-promo-live] планы.
   ЗДЕСЬ — контракт кнопки/trust/motion под РЕАЛЬНУЮ разметку renderPaywall (pw2):
     .pw2                 — корень экрана (<div class="pw2[ pw2-cascade]">)
     .btn.pw-cta          — sticky кнопка-печать (перебивает .btn ниже по файлу);
                            .pw-cta-sum — опц. span суммы (JS резервирует ширину через --sumw)
     .pw-under-cta        — подпись «Счёт выставит Telegram…»
     .pw-trust / .pw-trust-line / details.pw-stars-how — мост страха Stars
                            (тело аккордеона переиспользует .recov-steps :899)
     Motion-хуки:
       .pw2-cascade — вход-каскад: ставит разметка 1 раз за сессию пейвола (_pwCascaded);
                  stagger строк — nth-child-лестница (inline-переменных в разметке нет)
       .pw-breathe — герой-строка 3m («дыхание» glow-слоя; вешает JS/интеграция)
       .pw-nod / .pw-sum-in — CTA-«кивок» + кроссфейд суммы на selPlan (вешает renderPaywall)
       .pw-sheen — idle-блик CTA (интервал 8с, max 3 — счётчик _pwSheenTick в app.js)
       .pw-pop  — selPop на тапнутой строке (вешает selPlan)
       .pw-urgent / .pw-critical — <5:00 / <1:00, тогглит _pwEscalate (pw5) на полосе + #screen
   Motion-закон (build note 9): только transform/opacity; glow — через opacity ГОТОВЫХ
   ::before/::after-слоёв; никакого backdrop-filter/canvas; ≤2 живых циклов (urgent-таймер
   замещает дыхание героя). Все анимации переживают M13-ре-рендер selPlan: это keyframes
   по классу, а не transition (transition умирает на свежем DOM-узле).
   ========================================================================== */
/* цветовые токены --pw-* живут в корневом :root (:20, пакет pw3) — здесь только motion */
:root{
  --m-ease-out:cubic-bezier(.22,.61,.36,1); --m-ease-spring:cubic-bezier(.34,1.56,.64,1);
}

/* корень: запас снизу, чтобы trust-блок и «Что ещё внутри» доскролливались ВЫШЕ
   sticky-кнопки (она плавает в 8px над fixed .tabbar — см. --pw-tabbar-h у .pw-cta — и
   перекрывает хвост контента; #screen даёт всего 90px под таб-бар — этого мало).
   .pw2-screen — алиас контракта pw3. */
/* Основатель 2026-07-23: было 120px+sab И складывалось с 90px запаса #screen → мёртвая зона
   ~250px под CTA. На максимальном скролле sticky-печать встаёт в потоковое место после
   контента — под ней нужен только воздух; запас под fixed таб-бар несёт #screen, не пейвол. */
.pw2, .pw2-screen{ padding-bottom:calc(16px + var(--sab, env(safe-area-inset-bottom))); scroll-padding-bottom:120px; }

/* «рамка, которая горит» при активном промо: разметка pw2 ставит .pw2-promo — алиас
   к .pw2-promo-live из секции pw3 (:1220), те же декларации; margin-top даёт воздух
   язычку top:-13px, паддинг прячет строки от нависающей пилюли */
.plan-grid.pw2-promo{ margin-top:24px; padding:16px 10px 10px; border-radius:18px;
  border:1px solid rgba(255,92,138,.22); background:rgba(255,92,138,.04); }

/* --- (1) sticky CTA-печать: язык ценности — паспорт/печать; magenta тут запрещён.
   Рост при переносе: min-height 54 + padding → две строки дают ~64px, НИКАКОГО ellipsis
   (white-space:normal; overflow:hidden ниже клипует только ::after-блик, не текст —
   кнопка растёт по контенту). --- */
.pw-cta{
  /* QA device-matrix: bottom учитывает fixed .tabbar (:403) — иначе в stuck-состоянии
     нижние ~51px печати (строка с суммой инвойса!) уходят ПОД таб-бар, а при OS
     font-scale ≥1.3 скрывается вся кнопка. Реальную высоту таб-бара (растёт с
     font-scale) JS кладёт в --pw-tabbar-h при каждом renderPaywall; фолбэк = штатные
     8+22+3+13+8+safe-area ≈ 54px+safe. Свои 8px воздуха — поверх. */
  /* max(…, --sab): при скрытом таббаре JS кладёт --pw-tabbar-h:0px — без max() bottom=8px
     и печать заезжает в нижний вырез iPhone (home-индикатор ложится на CTA, ночной QA:
     наезд 11px при --sab:34px). При видимом таббаре его высота уже включает safe-area
     и всегда ≥ --sab — поведение не меняется. */
  position:sticky; bottom:calc(max(var(--pw-tabbar-h, calc(54px + var(--sab, env(safe-area-inset-bottom, 0px)))), var(--sab, env(safe-area-inset-bottom, 0px))) + 8px); z-index:6;
  display:flex; align-items:center; justify-content:center; gap:7px; flex-wrap:wrap;
  width:100%; min-height:54px; padding:12px 18px; border:0; border-radius:16px;
  background:var(--pw-seal); color:var(--pw-ink-on-gold);
  font-size:17px; font-weight:800; line-height:1.25; text-align:center;
  white-space:normal; overflow:hidden; cursor:pointer;
  box-shadow:0 8px 24px -8px var(--pw-glow);
  transition:transform .12s ease;
  -webkit-tap-highlight-color:transparent;
}
.pw-cta:active{ transform:scale(.98); }
/* Fix #1 (founder 2026-07-18): instant buy-loading state — spinner + «Открываю оплату…»
   overlaying the seal while /payments/invoice fetches the link; the real label is hidden and
   taps are locked, so a slow link never reads as a dead/broken CTA (killed the rage-taps). */
/* color:transparent hides the CTA's BARE TEXT NODE (the label isn't wrapped in an element, so
   visibility:hidden on element children alone left it showing under the overlay); the overlay
   re-declares its own colour so it stays visible. */
.pw-cta.is-loading{ pointer-events:none; cursor:default; color:transparent; }
.pw-cta.is-loading > :not(.pw-cta-load){ visibility:hidden; }
.pw-cta .pw-cta-load{
  position:absolute; inset:0; display:flex; align-items:center; justify-content:center; gap:9px;
  font-size:16px; font-weight:800; color:var(--pw-ink-on-gold);
}
.pw-cta .pw-cta-spin{
  width:16px; height:16px; flex:none; border-radius:50%;
  border:2.5px solid rgba(60,42,12,.28); border-top-color:var(--pw-ink-on-gold, #2a1c06);
  animation:pwCtaSpin .7s linear infinite;
}
@keyframes pwCtaSpin{ to{ transform:rotate(360deg); } }
@media (prefers-reduced-motion:reduce){ .pw-cta .pw-cta-spin{ animation-duration:1.5s; } }
/* сумма на кнопке = РОВНО сумма инвойса (общий хелпер с buyPremium, build note 3);
   ширину под самую длинную локаль JS кладёт в --sumw — кроссфейд не дёргает layout */
.pw-cta .pw-cta-sum{
  display:inline-block; min-width:var(--sumw,0); text-align:center;
  font-variant-numeric:tabular-nums;
}
.pw-cta .pw-cta-sum.pw-sum-in{ animation:pwSumIn .16s ease both; }
@keyframes pwSumIn{ from{opacity:0;} to{opacity:1;} }
/* «кивок» на selPlan — однократный, вечный пульс на CTA запрещён спеком */
.pw-cta.pw-nod{ animation:pwCtaNod .28s var(--m-ease-spring); }
@keyframes pwCtaNod{ 0%{transform:scale(1);} 45%{transform:scale(1.035);} 100%{transform:scale(1);} }
/* idle-блик: готовый ::after-слой, гоняем transform/opacity; клипуется overflow:hidden кнопки */
.pw-cta::after{
  content:""; position:absolute; top:-40%; bottom:-40%; left:0; width:36%;
  background:linear-gradient(105deg,transparent 0%,rgba(255,255,255,.55) 50%,transparent 100%);
  transform:translateX(-160%) rotate(8deg); opacity:0; pointer-events:none;
}
.pw-cta.pw-sheen::after{ animation:pwSheen .9s var(--m-ease-out); }
@keyframes pwSheen{
  0%{ transform:translateX(-160%) rotate(8deg); opacity:0; }
  12%{ opacity:1; }
  100%{ transform:translateX(420%) rotate(8deg); opacity:0; }
}

/* --- (2) подпись под кнопкой --- */
.pw-under-cta{ margin:8px 2px 0; text-align:center; font-size:11px; line-height:1.35; color:#8b83a8; }

/* --- (2b) ЮKassa «Картой / СБП» (не-ru RUB-аудитория): вторичная кнопка под печатью.
   Контурная в тоне золота печати — заметна, но НЕ конкурирует с главной CTA по яркости.
   .pw-stars-cta — та же вторичная одёжка для ru-дефолта (там роли перевёрнуты: золотая
   CTA — карта/СБП, вторичная — «Оплатить в Stars»); нарочно БЕЗ класса .pw-yk, чтобы
   yk-флоу и тесты, ищущие .pw-yk, не находили Stars-кнопку. --- */
.pw-yk, .pw-stars-cta{
  display:flex; align-items:center; justify-content:center; gap:7px; flex-wrap:wrap;
  width:100%; margin:10px 0 0; min-height:46px; padding:11px 16px;
  border:1px solid rgba(244,200,105,.42); border-radius:14px;
  background:rgba(244,200,105,.06); color:var(--pw-gold, #F4C869);
  font-size:14.5px; font-weight:700; line-height:1.25; text-align:center; cursor:pointer;
  transition:transform .12s ease;
  -webkit-tap-highlight-color:transparent;
}
.pw-yk:active, .pw-stars-cta:active{ transform:scale(.98); }

/* --- Шторка выбора способа оплаты (основатель 2026-08-23): строки-методы с ценой. --- */
/* --- Онбординг-гейт (grey-паттерн, BRIEF onb_gate): клетка 5с + «Купить позже». --- */
body.pw-gate-lock .tabbar{display:none;}
.pw-gate-later{display:block;margin:16px auto 4px;background:none;border:0;cursor:pointer;
  color:var(--hint);font-size:13.5px;line-height:1.3;text-decoration:underline;
  text-underline-offset:3px;opacity:0;pointer-events:none;transition:opacity .5s ease;
  -webkit-tap-highlight-color:transparent;}
.pw-gate-later.show{opacity:.85;pointer-events:auto;}
@media (prefers-reduced-motion: reduce){.pw-gate-later{transition:none;}}

/* Пакеты ✨: главная цифра — валюта, звёзды мелкой строкой (основатель 2026-08-24). */
.pack .pk-stars{display:block;margin-top:2px;font-size:12px;color:var(--hint);}

/* Кофейный якорь недели — своей строкой под ценой (основатель 2026-08-24). */
.pw-week-coffee{display:block;margin-top:2px;}

.pm-rows{display:flex;flex-direction:column;gap:10px;margin:4px 0 6px;}
.pm-row{display:flex;align-items:center;gap:12px;width:100%;padding:13px 14px;
  border:1px solid rgba(160,150,220,.22);border-radius:14px;background:rgba(120,110,190,.08);
  color:var(--text);text-align:left;cursor:pointer;transition:transform .12s ease;
  -webkit-tap-highlight-color:transparent;}
.pm-row:active{transform:scale(.985);}
.pm-row.is-loading{opacity:.55;pointer-events:none;}
.pm-ic{flex:0 0 44px;width:44px;height:44px;border-radius:12px;display:flex;align-items:center;
  justify-content:center;background:rgba(160,150,220,.14);}
.pm-ic svg{width:24px;height:24px;}
.pm-ic-yk{color:#8ab0f0;background:rgba(90,130,220,.18);}
.pm-ic-stars{color:var(--pw-gold,#F4C869);background:rgba(244,200,105,.14);}
.pm-ic-stripe{color:#b79df0;background:rgba(150,110,230,.16);}
.pm-tx{display:flex;flex-direction:column;gap:2px;min-width:0;}
.pm-tx b{font-size:14.5px;font-weight:700;line-height:1.2;}
.pm-tx small{font-size:12px;color:var(--hint);line-height:1.25;}
.pm-pr{margin-left:auto;font-weight:700;font-size:14.5px;white-space:nowrap;
  font-variant-numeric:tabular-nums;}
.pm-pr s{opacity:.5;font-weight:600;font-size:12.5px;margin-left:3px;}
.pw-yk .yk-sum{ font-variant-numeric:tabular-nums; }
.pw-yk .yk-old{ opacity:.55; font-weight:600; }
.pw-yk[disabled], .pw-yk.is-loading,
.pw-stars-cta[disabled], .pw-stars-cta.is-loading{ opacity:.55; pointer-events:none; }
/* ru-дефолт: Stars — вторичная мелкая строка «или ⭐N» внутри .pw-bill карточки плана */
.plan-card .pw-stars-alt{ opacity:.8; white-space:nowrap; }
/* Шторка email для чека: input[type=email] не покрыт глобальным правилом (:131 —
   только text/date/time/select) → одеваем в тот же стиль; + подсветка невалидного */
.yk-field input[type=email]{
  width:100%; padding:14px; font-size:max(16px, calc(16px * var(--font-scale)));
  color:var(--text); background:var(--bg2); border:1px solid var(--line); border-radius:12px;
}
.yk-field input.bad{ border-color:#f87171; box-shadow:0 0 0 2px rgba(248,113,113,.25); }
.yk-err{ margin:6px 2px 10px; font-size:12.5px; line-height:1.35; color:#f87171; }
.yk-wait-hint{ margin-top:10px; }
#yk-paid-btn.is-loading{ opacity:.6; pointer-events:none; }

/* --- (3) Stars-блок: ЕДИНАЯ карточка (основатель 2026-07-17) — заголовок + 2 строки
       доверия + details-шаги в одном контейнере, один стиль, никаких разрозненных кусков --- */
.pw-trust{ display:flex; flex-direction:column; gap:7px; margin:14px 0 0;
  padding:13px 14px; border-radius:16px;
  background:rgba(30,23,64,.55); border:1px solid rgba(167,139,250,.22); }
.pw-stars-head{ margin:0 0 1px; font-size:14px; font-weight:800; color:var(--pw-gold); }
.pw-trust-line{ margin:0; font-size:12.5px; line-height:1.4; color:#C4B5FD; }
details.pw-stars-how{ margin:4px 0 0; padding-top:8px; border-top:1px solid rgba(167,139,250,.14); }
details.pw-stars-how summary{
  display:inline-flex; align-items:center; gap:5px; cursor:pointer; list-style:none;
  font-size:13px; font-weight:700; color:var(--pw-gold);
  -webkit-tap-highlight-color:transparent;
}
details.pw-stars-how summary::-webkit-details-marker{ display:none; }
details.pw-stars-how summary::after{ content:"▾"; font-size:11px; transition:transform .16s ease; }
details.pw-stars-how[open] summary::after{ transform:rotate(180deg); }
/* тело = переиспользованные шаги .recov-steps (checks.recovery.s1–s3, ноль новой i18n) */
details.pw-stars-how .recov-steps{ margin:10px 0 2px; }

/* --- (5) MOTION · вход-каскад ≤650мс, 1 раз за сессию пейвола (.pw2-cascade на корне
   ставит разметка через _pwCascaded; in-place ре-рендеры selPlan/410 приходят БЕЗ него).
   pointer-events НЕ блокируются: анимируются только transform/opacity, элементы
   кликабельны с первого кадра. Тайминг: H1 0мс → полоса 120мс → строки планов
   190мс + n·70мс (nth-child-лестница: при активном промо child 1 = язычок, строки
   сдвигаются на ступень — каскад просто начинается тактом позже) → CTA 580мс spring. --- */
.pw2-cascade .pw2-h1, .pw2-cascade .pw2-sub{ animation:pwRise .42s var(--m-ease-out) both; }
.pw2-cascade .pw-promo-timer, .pw2-cascade .pw-promo-strip{ animation:pwRiseStrip .42s var(--m-ease-out) .12s both; }
/* CTO fix: полоса центрируется transform:translateX(-50%) — общий pwRise заканчивается
   transform:none и (fill:both) НАВСЕГДА снял бы центровку; свой keyframe сохраняет её */
@keyframes pwRiseStrip{ from{ opacity:0; transform:translateX(-50%) translateY(10px); }
  to{ opacity:1; transform:translateX(-50%); } }
.pw2-cascade .plan-grid > .plan-card{ animation:pwRise .42s var(--m-ease-out) .19s both; }
.pw2-cascade .plan-grid > .plan-card:nth-child(2){ animation-delay:.26s; }
.pw2-cascade .plan-grid > .plan-card:nth-child(3){ animation-delay:.33s; }
.pw2-cascade .plan-grid > .plan-card:nth-child(4){ animation-delay:.40s; }
.pw2-cascade .plan-grid > .plan-card:nth-child(5){ animation-delay:.47s; }
.pw2-cascade .pw-cta{ animation:pwCtaIn .46s var(--m-ease-spring) .58s both; }
@keyframes pwRise{ from{ opacity:0; transform:translateY(10px); } to{ opacity:1; transform:none; } }
@keyframes pwCtaIn{ from{ opacity:0; transform:translateY(10px) scale(.97); } to{ opacity:1; transform:none; } }

/* «дыхание» героя 3m: glow-слой ::before, только opacity, цикл 3.2s (живой цикл №1) */
.pw-breathe{ position:relative; }
.pw-breathe::before{
  content:""; position:absolute; inset:-1.5px; border-radius:inherit; pointer-events:none;
  box-shadow:0 0 22px -6px var(--pw-glow); opacity:.35;
  animation:pwBreath 3.2s ease-in-out infinite;
}
@keyframes pwBreath{ 0%,100%{opacity:.35;} 50%{opacity:.7;} }

/* selPop на тапнутой строке (переезд золотого контура уже в transition .plan-card, pw3 :1230) */
.pw-pop{ animation:pwPop .24s var(--m-ease-spring); }
@keyframes pwPop{ 0%{transform:scale(.97);} 60%{transform:scale(1.02);} 100%{transform:scale(1);} }

/* тик секунд таймера: уходящий/входящий спаны (вешает Promo._paint внутри #pw-promo-timer);
   .promo-ss — якорь: уходящая цифра абсолютом ПОВЕРХ входящей, ширина пилюли не дёргается */
#pw-promo-timer .promo-ss{ position:relative; display:inline-block; }
#pw-promo-timer .tk-out{ position:absolute; left:0; top:0; animation:pwTickOut .18s ease both; }
#pw-promo-timer .tk-in{ display:inline-block; animation:pwTickIn .18s ease both; }
@keyframes pwTickOut{ from{ opacity:1; transform:none; } to{ opacity:0; transform:translateY(-6px); } }
@keyframes pwTickIn{ from{ opacity:0; transform:translateY(6px); } to{ opacity:1; transform:none; } }

/* эскалация честного дефицита (_pwEscalate/pw5 тогглит классы на ДВУХ узлах: сама полоса —
   для её glow-слоя, и #screen — для потомков вне полосы: дыхание героя и вспышка .pl-old):
   <5:00 urgent — magenta-дыхание glow-слоя полосы 2s, дыхание героя ГАСИТСЯ (лимит 2 циклов);
   <1:00 critical — цикл 1s + вспышка .pl-old (первый кандидат на выключение при сомнениях) */
.pw-promo-timer.pw-urgent::before, .pw-promo-strip.pw-urgent::before{ animation:pwStripBreath 2s ease-in-out infinite; }
.pw-promo-timer.pw-critical::before, .pw-promo-strip.pw-critical::before{ animation:pwStripBreath 1s ease-in-out infinite; }
@keyframes pwStripBreath{ 0%,100%{opacity:0;} 50%{opacity:1;} }
.pw-urgent .pw-breathe::before, .pw-critical .pw-breathe::before{ animation:none; opacity:.35; }
.pw-critical .pl-old{ animation:pwOldFlash 1s ease-in-out infinite; }
@keyframes pwOldFlash{ 0%,100%{opacity:.5;} 50%{opacity:1;} }

/* --- (6) reduced-motion: ВСЕ циклы/каскад/вспышки off (образец — блок .promo-cap выше).
   animation:none на pwRise/pwCtaIn безопасен: from-кадры живут только в keyframes,
   без анимации элементы в естественном opacity:1 — экран статичен, но целиком виден. --- */
@media (prefers-reduced-motion:reduce){
  .pw2-cascade .pw2-h1, .pw2-cascade .pw2-sub,
  .pw2-cascade .pw-promo-timer, .pw2-cascade .pw-promo-strip,
  .pw2-cascade .plan-grid > .plan-card, .pw2-cascade .pw-cta{ animation:none; }
  /* Правило про «висящие» глифы переехало ОТСЮДА в reduced-motion колеса (см. .fc-wheel
     ниже по файлу): здесь оно было и не по смыслу (блок пейвола), и мертво — селекторы
     `.fc-wheel .fcw-un` / `.fcw-un-halo` посимвольно совпадают с объявлениями анимаций,
     которые стоят ПОЗЖЕ в документе, а при равной специфичности выигрывает последний. */
  .pw-breathe::before{ animation:none; opacity:.5; }          /* статичное мягкое свечение героя */
  .pw-cta.pw-sheen::after{ animation:none; }
  .pw-cta.pw-nod, .pw-pop, .pw-cta .pw-cta-sum.pw-sum-in{ animation:none; }
  #pw-promo-timer .tk-in{ animation:none; }
  #pw-promo-timer .tk-out{ animation:none; display:none; }    /* без анимации старая цифра просто исчезает */
  .pw-promo-timer.pw-urgent::before, .pw-promo-strip.pw-urgent::before,
  .pw-promo-timer.pw-critical::before, .pw-promo-strip.pw-critical::before{
    animation:none; opacity:.6;                               /* статичная magenta-свеча = маркер дефицита без пульса */
  }
  .pw-critical .pl-old{ animation:none; opacity:.8; }
}

/* ===== iOS native app (Capacitor) · safe-area верха — IOS_SPEC §15.2 =====
   Класс native-app на <html> ставит tg-shim.js ТОЛЬКО внутри Capacitor-оболочки
   (гейт D14). В Telegram/браузере класса нет и env(safe-area-inset-top)=0 —
   блок мёртв, рендер байт-в-байт прежний. Низ уже обвязан по всему файлу
   (env(safe-area-inset-bottom) — таббар, CTA, тосты); здесь ТОЛЬКО верх:
   четыре прижатых к top:0 поверхности, которые на iPhone уезжают под
   Dynamic Island / notch. viewport-fit=cover уже стоит в index.html.
   --sat/--sab: переменные-обёртки над env() — в native-app каскадом дают те же
   env-значения, но переопределяемы (тесты/эмуляция вырезов); в Telegram класса
   нет → var() падает в env(), где env=0 — поведение байт-в-байт прежнее. */
html.native-app { --sat: env(safe-area-inset-top); --sab: env(safe-area-inset-bottom); }
/* Глобальный топбар (сосед #screen, sticky у верха вьюпорта) — единственный, кто несёт
   +sat набивкой: он обязан закрыть зону статус-бара собственным фоном. */
html.native-app #topbar.topbar { padding-top: calc(10px + var(--sat, env(safe-area-inset-top))); }
/* Ин-контентный топбар совместимости живёт ВНУТРИ #screen (набивка экрана уже отвела зону
   статус-бара) — ему нужен только sticky-offset ниже скрима, НЕ вторая набивка (основатель
   2026-07-23: двойной отступ). Паттерн ровно как у .pers-seg. */
html.native-app .compat-screen .topbar { top: var(--sat, env(safe-area-inset-top)); }
html.native-app .pers-seg { top: var(--sat, env(safe-area-inset-top)); }
html.native-app #screen { padding-top: calc(16px + var(--sat, env(safe-area-inset-top))); }
/* ФИКС ДВОЙНОГО ОТСТУПА (основатель 2026-07-23, 5 скринов): на экранах С глобальным топбаром
   (пейвол, редактор, add-person, детали Личности, инвайт) вырез уже оплачен топбаром — #screen
   возвращается к штатным 16px, иначе под топбаром зияли лишние ~60px мёртвого места.
   Специфичность (2 id) бьёт правило выше независимо от порядка. */
html.native-app #topbar:not(.hidden) ~ #screen { padding-top: 16px; }
/* Скрим статус-бара: contentInset='never' кладёт webview ПОД часы/батарею, и при
   скролле контент читается в полосе 0..var(--sat) (QA: Личность, липкий .pers-seg
   встаёт на top:var(--sat), а полоса над ним прозрачная). Фикс — фикс-слой той же
   фактуры, что .pers-seg/.topbar (rgba(20,16,40,.92) + blur), высотой ровно в
   safe-area: на Личности читается бесшовным продолжением сегмент-бара, на прочих
   экранах закрывает тот же класс дыры. z-index:18 — над контентом (карточки ≤6),
   ПОД .pers-seg(19)/.topbar(20) и всеми оверлеями (шиты 60, тосты 80, FX 100000).
   body::after свободен (::before занят glow-слоем). В Telegram/браузере класса
   native-app нет → блок мёртв, рендер байт-в-байт прежний; и даже в native при
   sat=0 высота 0 — слой невидим. */
html.native-app body::after {
  content: ""; position: fixed; top: 0; left: 0; right: 0; z-index: 18;
  height: var(--sat, env(safe-area-inset-top));
  /* Основатель 2026-08-18 (скрин iPhone): плотная rgba(20,16,40,.92) читалась ЧУЖОЙ
     полосой над фоном — glow-слой body::before под ней темнел, и по нижней кромке шёл
     резкий шов. Теперь цвет = базовый фон (15,12,29) и растворение к низу: на верху
     скролла полоса неотличима от страницы, а читаемость часов при прокрутке держит
     blur — контент под safe-area размывается, плотный цвет для этого не нужен. */
  background: linear-gradient(to bottom, rgba(15,12,29,.78), rgba(15,12,29,.30) 72%, rgba(15,12,29,0));
  -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px);
  pointer-events: none;
}

/* ── P3 Dynamic Type (путь A) — глобальный пин ──────────────────────────────
   Гасит НЕуправляемую iOS-инфляцию px-текста (урок .plan-card / капсулы), чтобы
   работал ТОЛЬКО наш клампованный --font-scale [0.9…1.30], выставляемый шимом.
   Scoped на html.native-app: в Telegram/вебе этого класса НЕТ → правило мёртво,
   нулевой регресс. Инпуты уже защищены полом max(16px, …) от focus-zoom. */
html.native-app { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }

/* ===== iOS native keyboard (P4 · @capacitor/keyboard) =====
   --kb-h (высота клавиатуры) и класс kb-visible ставит ТОЛЬКО tg-shim.js (блок 7.5) —
   и только внутри Capacitor-оболочки С установленным плагином Keyboard (после rebuild
   P5/P7). В Telegram/браузере ни класса html.native-app, ни kb-visible, ни --kb-h нет →
   весь блок мёртв, а web-хак .onb-form.kb-open (стр. 2662, 48vh) остаётся дословно.
   На нативе webview уже сжимается плагином (resize:"native", §5.A), поэтому вместо 48vh
   даём ровно высоту клавиатуры + запас, чтобы последнее поле и его city-dropdown встали
   НАД клавиатурой, а не впритык к её краю. */
html.native-app { --kb-h: 0px; }
html.native-app.kb-visible .onb-form { padding-bottom: calc(var(--kb-h) + 24px); }
html.native-app.kb-visible { scroll-padding-bottom: var(--kb-h); }
/* Гашение двойного зазора (R1): нативная ветка app.js .kb-open НЕ вешает, но если он всё же
   просочится (гонка) ПРИ активном нативном resize (--kb-h выставлен, класс kb-visible есть) —
   48vh обнуляется, чтобы не сложиться с нативным сжатием фрейма. КРИТИЧНО: гейт .kb-visible.
   Без него правило срабатывало ТОЛЬКО когда плагина Keyboard нет (__kbNative=false → app.js
   вешает .kb-open, а kb-visible шим НЕ ставит) — т.е. ровно в деградированной iOS-сборке до
   P5/P7, где нативного resize НЕТ и 48vh как раз нужен: обнуление убивало скролл-запас
   онбординга (scrollMax 638→348, city застревал на y=370 вместо 135, dropdown уходил под
   клавиатуру). .kb-open и .kb-visible взаимоисключающи (плагин есть ⇒ нет .kb-open; плагина
   нет ⇒ нет .kb-visible), поэтому в живой деградации это правило теперь НЕ матчится и 48vh
   остаётся. Специфичность 0,4,1 по-прежнему бьёт 48vh (0,3,0) в редком leak-случае. */
html.native-app.kb-visible .onb-form.kb-open { padding-bottom: 0; }

/* ═══════════════════════════════════════════════════════════════════════════
   ТУР «ПРОВОДНИК» — КАРКАС (?v=443). Только машина: геометрия, слои, состояния.
   Такты (тексты/якоря) приезжают отдельно и не трогают ни одного правила ниже.

   Слои (жёстко):  .tour-scrim / .tour-lens = 28  → ПОД .tabbar (30): таб-бар не
   затемнён, живой и тапабельный всю дорогу — уход по вкладке это результат, а не
   побег.  .tour-bubble = 55 → НАД таб-баром, но ПОД .sheet-back (60): открывшаяся
   шторка обязана перекрыть тур (JS в этот момент прячет его целиком).
   #tour сам — СТАТИЧНЫЙ див без z-index/position: он не создаёт stacking context,
   иначе оба ребёнка схлопнулись бы в один слой и разнести 28/55 было бы нечем.

   Ни backdrop-filter, ни blur, ни filter, ни анимируемого box-shadow: 88-93% парка —
   дешёвый LatAm-Android, а .tabbar уже несёт свой backdrop-filter. Двигаются ТОЛЬКО
   opacity и статичные rect (left/top/width/height ставит JS).
   ЗОЛОТА В ТУРЕ НЕТ НИ РАЗУ: золото = премиум/замок, золотая подсветка превратила бы
   любой подсвеченный блок в пейвол.
   ═══════════════════════════════════════════════════════════════════════════ */
#tour { position: static; }            /* никакого stacking context — см. шапку */
#tour[hidden] { display: none; }       /* tourHide(): шторка/пауза — весь оверлей вон */

/* ЗАТЕМНЕНИЕ БЕЗ ОКНА — состояние «якорь потерян»: подсвечивать пустоту нельзя,
   но и мигать чёрным на ре-рендере тоже, поэтому фон остаётся, окно гаснет. */
.tour-scrim {
  position: fixed; inset: 0; z-index: 28; pointer-events: none;
  background: rgba(11, 8, 24, .88);
  opacity: 0; transition: opacity .14s linear;
}
/* ОКНО СВЕТА. Затемнение и дырка — ОДИН узел: box-shadow 0 0 0 9999px красит всё
   вокруг прямоугольника, поэтому со .tour-scrim они взаимоисключающи (иначе фон
   сложился бы вдвое и «свет» перестал быть светом). Геометрия — из JS, мгновенно;
   интерполяции rect нет ни одной (это полноэкранный repaint каждый кадр). */
.tour-lens {
  position: fixed; z-index: 28; pointer-events: none;
  left: 0; top: 0; width: 0; height: 0;
  border-radius: 16px;
  box-shadow: 0 0 0 9999px rgba(11, 8, 24, .88);
  opacity: 0; transition: opacity .18s linear;
}
/* ОБОДОК — ОТДЕЛЬНЫЙ УЗЕЛ НА z-55, И ЭТО НЕ ИЗБЫТОЧНОСТЬ. Линза лежит на 28, а
   .tabbar на 30: такт «одна вкладка, не четыре» подсвечивает КНОПКУ ТАБ-БАРА, и
   любое кольцо, нарисованное линзой, оказалось бы ПОД ней — на скриншоте 320×568 у
   кнопки «Personnalité» не было ровно ничего. Кольцо живёт на слое пузыря (55) и
   поэтому умеет обвести элемент, стоящий над затемнением.
   Фиолетовый, не золотой: золото у нас = премиум/замок, золотая подсветка превратила
   бы подсвеченный блок в пейвол. Дыхание — существующий @keyframes peTargetRing
   (styles.css ~3313) на ::after: у самого кольца box-shadow занят обводкой. */
.tour-ring {
  position: fixed; z-index: 55; pointer-events: none;
  left: 0; top: 0; width: 0; height: 0;
  border-radius: 16px;
  box-shadow: inset 0 0 0 1px rgba(179, 136, 255, .55);
  opacity: 0; transition: opacity .18s linear;
}
.tour-ring::after {
  content: ""; position: absolute; inset: -2px; border-radius: 18px; pointer-events: none;
  animation: peTargetRing 1.8s ease-in-out infinite;
}
/* ТАБ-БАР — ЕДИНСТВЕННОЕ, ЧТО ЗАТЕМНЕНИЕ НЕ БЕРЁТ. Он на z30, линза с заливкой на z28
   (см. доктрину слоёв выше — таб-бар обязан оставаться живым и тапабельным всю дорогу,
   уход по вкладке это результат, а не побег). Побочный эффект: на такте про вкладки все
   четыре кнопки светились ровно одинаково, и подсказка «остальное — потом» не читалась
   вовсе. Гасим ЯРКОСТЬЮ и только ею: pointer-events не трогаем ни на кадр, тап по любой
   вкладке работает как работал. Подсвеченная кнопка остаётся в полную силу — её ещё и
   обводит .tour-ring на z55. */
body.tour-live .tabbar .tab { opacity: .32; transition: opacity .18s linear; }
body.tour-at-tabs .tabbar .tab[data-tab="personality"] { opacity: 1; }
/* Такт, ведущий В МАТРИЦУ, и такт, ведущий из неё в «Личность». Без этих двух строк
   подсвеченная вкладка оставалась притушенной до 32% — тур обводил её кольцом, а сама
   кнопка была тёмной, и цель подсветки читалась наоборот. */
body.tour-at-mx_tab  .tabbar .tab[data-tab="matrix"]      { opacity: 1; }
body.tour-at-tabs_mx .tabbar .tab[data-tab="personality"] { opacity: 1; }
@media (prefers-reduced-motion: reduce) {
  body.tour-live .tabbar .tab { transition: none; }
}
#tour.on .tour-lens, #tour.on .tour-ring { opacity: 1; }
#tour.on.blind .tour-lens, #tour.on.blind .tour-ring { opacity: 0; }
#tour.on.blind .tour-scrim { opacity: 1; }

/* ТЁМНАЯ ЗОНА НЕ ПРИНИМАЕТ ТАПЫ — но ловушкой служит НЕ узел, а страж событий на window
   (_tourGuard в app.js). Прозрачный фиксированный див здесь не годится: страница
   скроллится через document.body, а фиксированный оверлей не входит в её цепочку
   скролла — палец переставал листать экран. Поэтому скрим и линза остаются
   pointer-events:none (условие концепта), а решение «пропустить тап» принимает JS по
   прямоугольнику окна света. */

/* ПУЗЫРЬ. Геометрия дословно с .twin-t1 (styles.css ~3130) — она уже проверена на
   320px и в html.native-app. Позицию по вертикали ставит JS: либо top (якорь в
   верхних 55% вьюпорта → пузырь ПОД ним), либо класс .dock-bottom. */
.tour-bubble {
  position: fixed; left: 12px; right: 12px; z-index: 55;
  /* ДЕФОЛТ — нижняя посадка, и это не вкусовщина: пока не разрешился tourSettle (до
     1.2с при активной инерции WebView), пузырь уже видим. Без top/bottom position:fixed
     кладёт его на СТАТИЧЕСКОЕ место в потоке — то есть под весь контент Прогноза,
     куда-нибудь за экран, и первый кадр тура был бы прыжком. */
  top: auto; bottom: calc(72px + var(--sab, env(safe-area-inset-bottom)));
  max-width: 496px; margin: 0 auto;
  padding: 12px 14px 11px; border-radius: 16px;
  background: linear-gradient(135deg, #2a2150, var(--card));
  border: 1px solid rgba(179, 136, 255, .28);
  box-shadow: 0 14px 34px -10px rgba(0, 0, 0, .6), 0 0 22px -8px rgba(179, 136, 255, .45);
  opacity: 0; transition: opacity .14s linear;
}
#tour.on .tour-bubble { opacity: 1; }
/* Невидимый пузырь НЕ ЛОВИТ ТАПЫ. Он прозрачен трижды: до посадки первого такта, во
   время паузы «дочитай раскрытую сферу» и все 200мс гашения после выхода — и всё это
   время он лежал поверх контента и съедал бы тап пальцем, который целился в экран.
   Ловушка тапа работает только когда её видно. */
#tour:not(.on) .tour-bubble { pointer-events: none; }
/* нижняя посадка: над таб-баром + safe-area (в Telegram обёртка даёт 0) */
.tour-bubble.dock-bottom { top: auto; bottom: calc(72px + var(--sab, env(safe-area-inset-bottom))); }   /* = дефолт; класс оставлен как читаемый маркер состояния */

.tour-hd { display: flex; align-items: center; gap: 8px; margin: 0 0 5px; }
/* .fc-sec-lbl несёт типографику, но его font-size:12px — без множителя, и в нативном
   iOS при Dynamic Type 1.30 тело росло до 17.55px, а заголовок оставался 12px: в
   единственном оверлее, который видит каждый новичок, самый мелкий текст игнорировал
   системную настройку «сделай крупнее». Множитель добавлен здесь, а не в .fc-sec-lbl,
   чтобы не трогать сетку заголовков секций Прогноза. */
/* ЗАГОЛОВОК ПЕРЕНОСИТСЯ, А НЕ ОБРЕЗАЕТСЯ. .fc-sec-lbl несёт white-space:nowrap (он
   рассчитан на однострочный лейбл секции с линией-хвостом), и вместе с
   overflow:hidden+ellipsis это резало заголовок такта: fr «Les 4 sphères de ta journée»
   = 310px при доступных 245 → «LES 4 SPHÈRES DE TA …» (приёмка концепта идёт ИМЕННО на
   fr при --font-scale 1.30 на 320px), а «Trois proximités différentes» не влезал даже
   при масштабе 1 — то есть в обычном Telegram на 320px в 16 локалях из 18.
   Две строки максимум: заголовок такта — это фраза, а не ярлык. */
.tour-title {
  flex: 1; min-width: 0; font-size: calc(12px * var(--font-scale));
  white-space: normal; overflow: hidden; text-overflow: clip;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  line-height: 1.25;
}
/* Тихие точки прогресса. Цифрового «шаг 1 из 3» на экране НЕТ (счётчик читается как
   обязательство) — номер живёт только в aria-label пузыря. */
/* СЧЁТЧИК ТАКТОВ «1/3». Был ряд точек — язык карусели, который обещает свайп; жеста нет,
   и попытка листнуть пузырь дала бы мёртвый тап в фиче, которая борется с мёртвыми тапами.
   Табличные цифры — чтобы ширина не прыгала на переходе 1/3 → 2/3 и не дёргала заголовок. */
.tour-dots {
  flex: none; font-size: 12px; font-weight: 700; letter-spacing: .04em;
  color: rgba(179, 136, 255, .85); font-variant-numeric: tabular-nums;
}
.tour-dots i {
  width: 5px; height: 5px; border-radius: 50%; background: rgba(179, 136, 255, .28);
  transition: background .14s linear;
}
.tour-dots i.on { background: rgba(179, 136, 255, .85); }
/* Тело: без serif и без новой типографики — на fr при --font-scale 1.30 на 320px
   Georgia даёт четыре строки и наезд на подсвечиваемый блок. Две строки на нормальном
   экране; clamp стоит на 4, потому что на 320px при 1.30 самая длинная локаль (fr) —
   это ровно 4 строки, и клип на трёх обрывал реплику на полуслове («Touche un cercle :
   je…»). Замеряно, а не на глаз: qa/tour_beats_e2e.mjs при QA_W=320 QA_FS=1.30. */
.tour-body {
  margin: 0; font-size: calc(13.5px * var(--font-scale)); line-height: 1.4; color: var(--text);
  overflow: hidden; display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical;
}
/* РЯД ДЕЙСТВИЙ ПЕРЕНОСИТСЯ, А ТЕКСТ — НЕТ. На 320×568 при --font-scale 1.30 CTA
   «Открыть «Личность»» требует 205px, а рядом с «Пропустить» (91px) остаётся 177 —
   и единственный настоящий CTA тура обрезался в «Открыть «Личн…» (то же на de/uk/nl;
   приёмку гоняли на fr, где влезает). Клип на CTA недопустим, ужимать «Пропустить»
   до «Проп…» — тоже. Поэтому: flex-wrap + запрет сжатия у кнопки (flex-shrink 0) —
   когда пара не влезает в строку, CTA уезжает на СВОЮ строку во всю ширину пузыря
   (258px > 205px) и читается целиком. На 375/390px ряд остаётся в одну строку. */
.tour-acts { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin: 10px 0 0; }
/* «Пропустить» — скучная muted-ссылка, а не соблазн; и она видна на КАЖДОМ кадре. */
.tour-skip {
  flex: none; background: none; border: 0; cursor: pointer; padding: 9px 2px; margin: -9px 0;
  min-height: 38px; color: var(--hint); font-size: calc(12.5px * var(--font-scale));
  text-decoration: underline; text-underline-offset: 3px;
}
.tour-next {
  flex: 1 0 auto; min-width: 0; border: 0; cursor: pointer; border-radius: 12px;
  padding: 10px 14px; min-height: 38px;
  font-weight: 800; font-size: calc(13px * var(--font-scale)); color: #1a1030;
  background: linear-gradient(135deg, var(--accent), var(--accent2));
  box-shadow: 0 4px 14px -4px rgba(179, 136, 255, .55);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
@media (max-width: 359px) { .tour-bubble { left: 8px; right: 8px; padding: 11px 12px 10px; } }
/* ЛЕСТНИЦА ОТСТУПЛЕНИЯ ПУЗЫРЯ: сначала ВОЗДУХ (.snug), потом сдвиг СТРАНИЦЫ, и только
   потом ТЕКСТ (.tight). Обе ступени ставит JS (tourPlaceBubble) и только когда чистой
   посадки нет, поэтому на нормальном экране их не бывает вовсе.
   .snug — плотнее отступы и кнопки, НИ ОДНОГО СИМВОЛА НЕ ТЕРЯЕТСЯ. Этой ступени не
   существовало, и первым же ответом на 8px наезда шёл клип текста: на приёмочной
   комбинации концепта (fr, --font-scale 1.30, 320×568) после обычной прокрутки пальцем
   исчезал «Touche un cercle : je dis pourquoi» — единственный CTA такта. */
.tour-bubble.snug { padding: 9px 12px 9px; }
.tour-bubble.snug .tour-hd { margin-bottom: 3px; }
.tour-bubble.snug .tour-acts { margin-top: 7px; gap: 8px; }
.tour-bubble.snug .tour-next, .tour-bubble.snug .tour-skip { min-height: 34px; padding-top: 7px; padding-bottom: 7px; }
/* УЖАТЫЙ ПУЗЫРЬ — не «мелкий шрифт для красоты», а ПОСЛЕДНЯЯ ступень перед наездом на
   подсвечиваемый блок. На 568×320 (поворот телефона) при --font-scale 1.30 обычный
   пузырь не влезал НИ под якорь, НИ над ним и садился прямо на кольца, которые в этот
   момент называет (замер: 40px перекрытия). Правила идут ПОСЛЕ .snug: когда стоят оба
   класса, побеждает .tight. */
.tour-bubble.tight { padding: 8px 12px 8px; }
.tour-bubble.tight .tour-hd { margin-bottom: 3px; }
/* Клип — но НЕ до ярлыка: заголовок такта остаётся фразой (2 строки, как в базе), тело
   теряет максимум одну строку из четырёх. Прежние «1 строка заголовка + 2 строки тела»
   срезали на fr при 1.30 весь CTA реплики («Touche un cercle : je dis pourquoi»), то
   есть ровно то, ради чего такт показывают. Замер: 320×440, fr, 1.30 — с этими числами
   пузырь по-прежнему садится без наезда (overlap 0). */
.tour-bubble.tight .tour-body { -webkit-line-clamp: 3; font-size: calc(12.5px * var(--font-scale)); }
/* САМОЕ ДНО ЛЕСТНИЦЫ. Ставится, только если и ужатый пузырь наезжает на подсвечиваемый
   блок (320×440 = поворот телефона + fr + 1.30): наезд на то, что такт объясняет, хуже
   обрыва фразы, поэтому здесь текст всё-таки клампится. На приёмочных 320×568 эта
   ступень не наступает ни в одной локали. */
.tour-bubble.tight.tighter .tour-title { -webkit-line-clamp: 1; }
.tour-bubble.tight.tighter .tour-body { -webkit-line-clamp: 2; }
.tour-bubble.tight .tour-acts { margin-top: 7px; gap: 8px; }
.tour-bubble.tight .tour-next, .tour-bubble.tight .tour-skip { min-height: 34px; padding-top: 7px; padding-bottom: 7px; }
/* ТОЛЧОК — видимый ответ на тап, который ничего не двигает: по тёмному (ловушка выше) и
   по пузырю внутри дебаунса продвижения. Молчащий тап — это ровно тот dead/rage-сигнал,
   которым фичу же меряют, поэтому «ничего не произошло» здесь не бывает. */
@keyframes tourNudge { 0% { transform: none; } 35% { transform: translateY(-3px); } 100% { transform: none; } }
.tour-bubble.nudge { animation: tourNudge .22s ease-out; }

/* REDUCED MOTION — «та же история мягче», а не «сцены нет»: все такты, вся хаптика,
   всё удержание остаются, уходит ТОЛЬКО интерполяция (iOS-юзеры уже жаловались на
   «пропавшую анимацию»). Класс .rm ставит JS из _persReducedMotion — второй раз
   matchMedia не зовём; media-запрос продублирован для прямого системного случая. */
#tour.rm .tour-scrim, #tour.rm .tour-lens, #tour.rm .tour-ring, #tour.rm .tour-bubble { transition: none !important; }
#tour.rm .tour-ring::after { animation: none !important; }
#tour.rm .tour-bubble.nudge { animation: none !important; }
@media (prefers-reduced-motion: reduce) {
  .tour-scrim, .tour-lens, .tour-ring, .tour-bubble { transition: none !important; }
  .tour-ring::after { animation: none !important; }
  .tour-bubble.nudge { animation: none !important; }
}

/* ── «Закрепить аккаунт» — веб-поверхность (WEB_SURFACE_SPEC §5, ?v=452) ──────────────
   Тихая карточка в конце ленты Прогноза (только веб, uid<0): обычный .card без золота и
   градиентных CTA — сохранение аккаунта не продажа, поэтому кнопка компактная (.btn.sm),
   а «Позже» — приглушённая ссылка. Лёгкий фиолетовый акцент рамки (как у .acc-invite,
   но тише), чтобы карточка читалась как действие, а не как ещё один абзац прогноза. */
.linkb{ border-color:rgba(167,139,250,.28); transition:opacity .25s; }
.linkb .lb-head{ display:flex; align-items:center; gap:12px; }
.linkb .lb-ic{ flex:none; width:40px; height:40px; border-radius:12px; display:grid; place-items:center;
  font-size:20px; background:rgba(167,139,250,.14); }
.linkb .lb-tx{ flex:1; min-width:0; }
.linkb .lb-tx h3{ font-size:15.5px; font-weight:800; }
.linkb .lb-tx .hint{ margin-top:2px; line-height:1.3; }
.linkb .lb-row{ display:flex; align-items:center; gap:16px; margin-top:12px; }
/* «Позже» — тап-мишень ≥30px без визуального веса кнопки (это отказ, он не должен спорить с CTA) */
.linkb .lb-later{ background:none; border:0; font-size:13.5px; padding:8px 6px; }
/* шит ожидания привязки: вертикальный ритм кнопок + спиннер по центру */
.link-wait .btn{ margin-top:14px; }
.link-wait .btn.ghost{ margin-top:8px; }
.link-wait .spinner{ margin:14px auto 0; }

/* =========================================================================
   ЖИВОЙ КОСМОС — интерактивное натальное колесо на экране Прогноз (#fc-wheel).
   ЖЕЛЕЗНОЕ ПРАВИЛО дешёвого LatAm-Android: в анимации ТОЛЬКО opacity и transform.
   Свечение — статичный radial-gradient. НЕТ filter/blur/backdrop-filter,
   НЕТ анимируемого box-shadow, НЕТ :has(). Всё namespace .fcw-*, keyframes fcw-*.
   ========================================================================= */
.fc-wheel{ position:relative; margin:6px 0 2px; }
/* сцена: квадрат ≤ ширины экрана; статичное свечение ядра — radial-gradient (не фильтр) */
.fc-wheel .fcw-stage{ position:relative; width:min(92vw,420px); aspect-ratio:1/1;
  margin:2px auto 4px; touch-action:manipulation; }
.fc-wheel .fcw-stage::before{ content:""; position:absolute; inset:-6%; border-radius:50%;
  background:radial-gradient(circle at 50% 50%, rgba(179,136,255,.26) 0%, rgba(126,140,224,.10) 34%, transparent 66%);
  z-index:0; pointer-events:none; }

/* фоновые звёзды — ПЛОСКИЕ точки (без box-shadow), мерцают только opacity */
.fc-wheel .fcw-stars{ position:absolute; inset:0; z-index:0; pointer-events:none; overflow:hidden; }
/* will-change НЕ ставим на 34 звезды — бюджет слоёв только для .halo и .rotor (ТЗ §4) */
.fc-wheel .fcw-star{ position:absolute; width:2px; height:2px; border-radius:50%;
  background:#dfe6ff; opacity:.5; animation:fcw-tw 5s ease-in-out infinite; }
@keyframes fcw-tw{ 0%,100%{opacity:.15} 50%{opacity:.75} }

/* РОТОР — единственное вращающееся тело: кольцо + планеты крутятся ЖЁСТКО вместе,
   поэтому связь «планета-в-знаке» никогда не рвётся (Лев остаётся во Льве). */
.fc-wheel .fcw-rotor{ position:absolute; inset:0; transform-origin:50% 50%; z-index:1; }
.fc-wheel .fcw-rotor.spin{ animation:fcw-spin 180s linear infinite; will-change:transform; }
@keyframes fcw-spin{ to{ transform:rotate(360deg) } }
.fc-wheel .fcw-layer{ position:absolute; inset:0; width:100%; height:100%; overflow:visible; }

/* планеты — HTML-узлы поверх SVG в тех же % координатах (viewBox 1000 → /10 = %) */
.fc-wheel .fcw-planet{ position:absolute; transform:translate(-50%,-50%); z-index:3;
  /* ТОЛЬКО translate-центрирование. Был ещё margin:-22px -22px → двойной сдвиг на 31px:
     планета съезжала вверх-влево от своей точки, а нити аспектов шли в правильную точку
     → линии мимо глифов, «из ниоткуда в никуда» (основатель 2026-08-02, замер 31px→0). */
  cursor:pointer; width:44px; height:44px; }
.fc-wheel .fcw-body{ position:relative; width:100%; height:100%; display:grid; place-items:center; }
/* контр-вращение ровно на -360° той же длительности → глиф всегда «стоит» вертикально */
.fc-wheel .fcw-rotor.spin .fcw-body{ animation:fcw-spinrev 180s linear infinite; }
@keyframes fcw-spinrev{ to{ transform:rotate(-360deg) } }

/* гало — статичный radial-gradient; «дыхание» = только scale+opacity */
.fc-wheel .fcw-halo{ position:absolute; width:52px; height:52px; border-radius:50%;
  background:radial-gradient(circle, var(--pc,#fff) 0%, transparent 62%); opacity:.85;
  animation:fcw-breathe 6s ease-in-out infinite; will-change:transform,opacity; }
@keyframes fcw-breathe{ 0%,100%{transform:scale(.9);opacity:.7} 50%{transform:scale(1.12);opacity:1} }
.fc-wheel .fcw-glyph{ position:relative; font-size:19px; line-height:1; color:var(--gold-hi,#fff6df);
  text-shadow:0 0 6px rgba(6,4,20,.6); font-variant-emoji:text; }
.fc-wheel .fcw-hedge .fcw-glyph{ opacity:.55; }        /* hedge:true — приглушённый глиф */
.fc-wheel .fcw-hedge .fcw-halo{ opacity:.5; }
.fc-wheel .fcw-retro{ position:absolute; top:-2px; right:-11px; font-size:10px; font-weight:800;
  color:var(--amber,#ff9a5c); }

/* узлы / Лилит — тонкие приглушённые метки (не тапаются: у них нет аспектов в данных) */
.fc-wheel .fcw-mark{ position:absolute; transform:translate(-50%,-50%); z-index:2;
  width:22px; height:22px; margin:-11px 0 0 -11px; display:grid; place-items:center; pointer-events:none; }
.fc-wheel .fcw-node{ font-size:13px; color:#b9aee0; text-shadow:none; opacity:.85; }

/* Глифы знаков и подписи осей — HTML-оверлей с КОНТР-ВРАЩЕНИЕМ: позиция орбитально едет
   с ротором, а сам символ/текст всегда СТОИТ ПРЯМО (основатель 2026-08-02: и надписи, и
   значки горизонтально). pointer-events:none — они информативны, не кликабельны (убираем
   ложное «тыкаемо, но мертво»). */
.fc-wheel .fcw-signpos,.fc-wheel .fcw-axname{ position:absolute; transform:translate(-50%,-50%);
  z-index:2; pointer-events:none; display:grid; place-items:center; }
.fc-wheel .fcw-signrot{ font-size:23px; color:var(--gold,#ffd98a); opacity:.92; line-height:1;
  display:inline-block; font-variant-emoji:text; text-shadow:0 0 5px rgba(6,4,20,.5); }
/* Asc/MC — компактнее и тише (основатель 2026-08-02: были слишком большими) */
.fc-wheel .fcw-axrot{ font-size:10px; font-weight:700; color:var(--gold,#ffd98a); opacity:.72;
  line-height:1; display:inline-block; letter-spacing:.06em; }
/* Асцендент КЛИКАБЕЛЕН (у него есть разбор). Ярче + подчёркивание = видимая аффорданс,
   pointer-events:auto перебивает :none базового .fcw-axname. MC остаётся некликабельным. */
.fc-wheel .fcw-axname.fcw-axtap{ pointer-events:auto; cursor:pointer; }
.fc-wheel .fcw-axtap .fcw-axrot{ opacity:1; text-decoration:underline; text-underline-offset:2px;
  text-decoration-color:rgba(255,217,138,.5); }
.fc-wheel .fcw-axtap:active .fcw-axrot{ opacity:.6; }
.fc-wheel .fcw-rotor.spin .fcw-signrot,
.fc-wheel .fcw-rotor.spin .fcw-axrot{ animation:fcw-spinrev 180s linear infinite; }

/* SVG кольцо / оси / нити */
.fc-wheel .fcw-ring-o,.fc-wheel .fcw-ring-i{ fill:none; stroke:rgba(255,217,138,.20); stroke-width:1; }
.fc-wheel .fcw-tick{ stroke:rgba(255,217,138,.14); stroke-width:1; }
.fc-wheel .fcw-orbit{ fill:none; stroke:rgba(179,136,255,.09); stroke-width:1; }
.fc-wheel .fcw-signglyph{ fill:var(--gold,#ffd98a); font-size:26px; text-anchor:middle;
  dominant-baseline:central; opacity:.9; }
.fc-wheel .fcw-axis{ stroke:rgba(255,217,138,.5); stroke-width:1.4; stroke-dasharray:5 6; }
.fc-wheel .fcw-axislab{ fill:var(--gold-hi,#fff6df); font-size:15px; font-weight:700;
  text-anchor:middle; dominant-baseline:central; }
/* Нити аспектов: ФОНОВОЕ мерцание — тихо пульсируют всегда, каждая своей фазой
   (основатель 2026-08-02: связи мерцают между планетами, кому интересно — засмотрится).
   Длительность/задержка приходят инлайном (разнофазность). Тап по планете → её нити
   вспыхивают ярче (.lit). Только opacity (перф). */
/* Базовые нити почти невидимы — иначе весь аспект-веб виден сразу и «идёт не из планет»
   (основатель 2026-08-02). JS-цикл (fcwCycle) по очереди зажигает связи ОДНОЙ планеты:
   её нити вспыхивают (.lit) и мягко пульсируют, потом гаснут, очередь идёт к следующей.
   Так линии явно исходят из конкретной планеты и не перегружают. Только opacity (перф). */
.fc-wheel .fcw-aspect{ stroke-width:1.3; opacity:.05; fill:none; stroke-linecap:round; transition:opacity .6s ease; }
.fc-wheel .fcw-aspect.harm{ stroke:var(--teal,#6fe3c0); }
.fc-wheel .fcw-aspect.tense{ stroke:var(--accent2,#ff7eb6); }
.fc-wheel .fcw-aspect.soft{ stroke:var(--indigo,#7e8ce0); }
.fc-wheel .fcw-aspect.lit{ opacity:.85; stroke-width:1.7; animation:fcw-thread 3.2s ease-in-out infinite; }
@keyframes fcw-thread{ 0%,100%{opacity:.45} 50%{opacity:.9} }
/* планета, чьи связи сейчас горят — её гало чуть ярче, подсказывая источник линий */
.fc-wheel .fcw-planet.cyc .fcw-halo{ transform:scale(1.12); opacity:1; transition:transform .5s ease,opacity .5s ease; }

/* заморозка: наведение (десктоп) / .frozen по касанию — гипнотический стоп-кадр */
.fc-wheel .fcw-stage:hover .fcw-rotor.spin,
.fc-wheel .fcw-stage.frozen .fcw-rotor.spin{ animation-play-state:paused; }
.fc-wheel .fcw-stage:hover .fcw-rotor.spin .fcw-body,
.fc-wheel .fcw-stage.frozen .fcw-rotor.spin .fcw-body{ animation-play-state:paused; }
/* выбор планеты: она ярче/крупнее, остальные тускнеют до 32% */
.fc-wheel .fcw-stage.selecting .fcw-planet:not(.sel){ opacity:.32; transition:opacity .35s ease; }
.fc-wheel .fcw-planet.sel{ z-index:6; }
.fc-wheel .fcw-planet.sel .fcw-halo{ animation:fcw-breathe 3.2s ease-in-out infinite; transform:scale(1.15); opacity:1; }
.fc-wheel .fcw-planet.sel .fcw-glyph{ color:#fff; opacity:1; }

/* подсказка + честные подписи подавления + CTA + легенда нитей */
/* Одна подсказка «коснись — раскроется» на два прибора: натальное колесо и роза матрицы.
   Селектор расширен, а не продублирован — копия стиля разошлась бы с оригиналом при
   первой же правке, а две подсказки одного назначения обязаны выглядеть одинаково. */
.fc-wheel .fcw-hint,
.mx-hint{ text-align:center; font-size:11.5px; color:var(--muted,#a99fd0); margin:2px 0 0; opacity:.85; }
/* Подсказка стоит РОВНО ПОСЕРЕДИНЕ между видимым низом прибора и отсечкой «1 / 5»
   (основатель 2026-08-03). Числа не на глаз: замер дал 6px сверху и 26px снизу при
   просвете 48px и высоте строки 16px — значит по 16px с каждой стороны, то есть
   margin-top 12 (2 + 10) и margin-bottom 8 (18 − 10). Отрицательный нижний отступ
   .mx-rose при этом остаётся: он и создаёт этот просвет. */
.mx-hint{ margin-top:19px; margin-bottom:0; }
/* Нижний зазор задаётся ЯВНО на соседе, а не отрицательной маржой у подсказки: у .mx-block
   собственный margin-top 26px, и он схлопывается с нашим по максимуму — то есть любое
   значение меньше 26 у подсказки просто не имело бы эффекта (замерено: правка margin-bottom
   не двигала ничего). Здесь мы перебиваем сам отступ блока, и оба зазора становятся
   управляемыми: 19px сверху и 19px снизу при просвете 54px и строке 16px. */
.mx-hint + .mx-block{ margin-top:19px; }
/* ── ВИСЯЩИЕ ТЕЛА ────────────────────────────────────────────────────────────────────
   То, чего на карте ещё нет (Асцендент без времени/места; Луна, когда её знак зависит от
   часа или когда без места мы его вообще не знаем).

   Основатель 2026-08-03: «хочу, чтобы летали эти значки тоже, где-нибудь в подобных зонах,
   по размеру похожи на планеты, так же светились, только серым». Поэтому анатомия ровно
   такая же, как у .fcw-planet — гало плюс глиф, — но обесцвеченная. Пунктирный кружок,
   который был раньше, убран: он говорил языком поля ввода и читался как приклеенная
   карточка, а не как тело рядом с картой.

   Живут в углах квадратной сцены, снаружи обода: колесо — вписанная окружность, углы к
   графику не относятся. Дрейф — только transform, гало «дышит» только scale+opacity;
   ни filter, ни box-shadow не анимируется (перф-доктрина). */
.fc-wheel .fcw-unplaced{ position:absolute; inset:0; z-index:4; pointer-events:none; }
/* ДРЕЙФ СИДИТ НА СОДЕРЖИМОМ, А НЕ НА КНОПКЕ (2026-08-03). Раньше animation стояла на
   самой .fcw-un — и тап-цель 52px непрерывно уезжала из-под пальца (Playwright 30 секунд
   отказывался кликать: «element is not stable», 56 повторов). Промах по движущейся
   мишени = молчаливое ничего, а за этой кнопкой стоит единственный вход в лист достройки
   данных. Теперь бокс кнопки СТАТИЧЕН, а плавает её содержимое: картинка та же, попадание
   детерминированное. animation-delay:inherit доносит до детей per-слотовый сдвиг фазы,
   который JS ставит инлайном на кнопке. */
.fc-wheel .fcw-un{ position:absolute; width:52px; height:52px; margin:-26px 0 0 -26px;
  display:grid; place-items:center; padding:0; border:0; background:none; cursor:pointer;
  pointer-events:auto; font-family:inherit; -webkit-tap-highlight-color:transparent; }
/* гало — тот же статичный radial-gradient, что у планет, но серо-фиолетовый */
.fc-wheel .fcw-un-halo{ position:absolute; width:52px; height:52px; border-radius:50%;
  background:radial-gradient(circle, #8d86ad 0%, transparent 62%); opacity:.72;
  animation:fcw-breathe 6s ease-in-out infinite, fcw-un-drift 11s ease-in-out infinite;
  animation-delay:inherit; }
.fc-wheel .fcw-un-g{ position:relative; font-size:19px; line-height:1; color:#cfc9e6;
  text-shadow:0 0 6px rgba(6,4,20,.6); font-variant-emoji:text;
  animation:fcw-un-drift 11s ease-in-out infinite; animation-delay:inherit; }
.fc-wheel .fcw-un:active .fcw-un-halo{ opacity:1; }
.fc-wheel .fcw-un:active .fcw-un-g{ opacity:.6; }
/* палец бьёт по 52px — тап-цель уже достаточна, расширитель не нужен */
@keyframes fcw-un-drift{
  0%,100%{ transform:translate(0,0); }
  25%    { transform:translate(4px,-5px); }
  50%    { transform:translate(-3px,-7px); }
  75%    { transform:translate(-5px,-2px); }
}

/* Старый лист «этого тела ещё нет на карте» (.fcw-un-sheet/-hero/-need/-alt/-body) удалён:
   он был чужеродной карточкой рядом с системой печатей, а .fcw-un-alt красил два
   кандидатных знака Луны премиальным металлом — то есть подписывал «за деньги»
   единственное честное астрологическое утверждение экрана. Замена — блок .un-seal
   в конце файла. НЕ ПУТАТЬ с .fcw-un/.fcw-un-halo/.fcw-un-g выше: это глифы на самом
   колесе, другие вещи с похожими именами. */

.fc-wheel .fcw-note{ text-align:center; font-size:12px; color:var(--indigo,#7e8ce0); margin:6px 8px 0; line-height:1.45; }
.fc-wheel .fcw-note.fcw-sys{ color:var(--muted,#a99fd0); opacity:.8; font-size:11px; }
.fc-wheel .fcw-cta{ color:var(--gold,#ffd98a); font-weight:700; cursor:pointer; white-space:nowrap; }
.fc-wheel .fcw-cta:active{ opacity:.5; }
.fc-wheel .fcw-legintro{ text-align:center; font-size:12px; color:var(--indigo,#7e8ce0); margin:8px 8px 4px; line-height:1.4; }
.fc-wheel .fcw-legend{ display:flex; gap:14px; justify-content:center; flex-wrap:wrap; margin:2px 0 2px;
  font-size:10.5px; color:var(--muted,#a99fd0); }
.fc-wheel .fcw-legend span{ display:inline-flex; align-items:center; gap:5px; }
/* Блоб-образец связи: светящийся кружок в языке гало планет. Радиальный градиент
   (яркое ядро → цвет → прозрачность) даёт свечение БЕЗ box-shadow/filter (перф-бюджет). */
.fc-wheel .fcw-lg{ width:13px; height:13px; border-radius:50%; display:inline-block; }
.fc-wheel .fcw-lg.harm{ background:radial-gradient(circle at 50% 42%, #eafff8 0%, var(--teal,#6fe3c0) 52%, rgba(111,227,192,0) 100%); }
.fc-wheel .fcw-lg.tense{ background:radial-gradient(circle at 50% 42%, #ffe6f2 0%, var(--accent2,#ff7eb6) 52%, rgba(255,126,182,0) 100%); }
.fc-wheel .fcw-lg.soft{ background:radial-gradient(circle at 50% 42%, #e8ecff 0%, var(--indigo,#7e8ce0) 52%, rgba(126,140,224,0) 100%); }

/* reduced-motion: космос ЗАМИРАЕТ (дрейф гаснет), карта статична — плюс JS-страховка (класс .spin не вешаем) */
@media (prefers-reduced-motion:reduce){
  .fc-wheel .fcw-rotor.spin,
  .fc-wheel .fcw-rotor.spin .fcw-body,
  .fc-wheel .fcw-rotor.spin .fcw-signrot,
  .fc-wheel .fcw-rotor.spin .fcw-axrot,
  .fc-wheel .fcw-halo,
  .fc-wheel .fcw-star,
  /* «Висящие» тела — сюда, и с !important: их собственные объявления (.fc-wheel .fcw-un,
     .fc-wheel .fcw-un-halo) имеют ТУ ЖЕ специфичность (0,2,0), поэтому гасить их можно
     только правилом, которое стоит ПОСЛЕ них по документу и повышено !important — как
     уже сделано для .fcw-halo/.fcw-star/.fcw-aspect в этой же строке. */
  .fc-wheel .fcw-un-halo,
  .fc-wheel .fcw-un-g,
  .fc-wheel .fcw-aspect{ animation:none !important; }   /* мерцание нитей тоже гаснет */
  .fc-wheel .fcw-aspect{ transition:none; opacity:.28; }  /* статичные тихие связи */
}

/* =========================================================================
   «МАТРИЦА РОЖДЕНИЯ» (.mx-*) — отдельный экран, роза ветров + разбор
   -------------------------------------------------------------------------
   СЕМЬЯ. Экран обязан читаться как родной натальному колесу .fcw-* и
   «самоцветам-печатям» .seal-*: тот же золотой ВОЛОСОК rgba(255,217,138,.20)
   ТОЙ ЖЕ толщины 1px, что у .fcw-ring-o (толщина — половина семейного
   сходства; «тот же цвет, втрое толще» это уже другой предмет), те же
   мерцающие звёзды, то же дыхание гало.
   ТОКЕНЫ. --gold ТОЛЬКО премиум/замок; --accent2 (magenta) не встречается
   НИ В ОДНОМ состоянии — она у нас значит «время заканчивается».
   ЗОЛОТО НИКОГДА не касается ЧИСЛА: цифры узлов и самоцветов — var(--text).
   ПЕРФ. Анимируются ТОЛЬКО opacity и transform. Ни blur, ни filter, ни
   backdrop-filter, ни drop-shadow, ни анимируемого box-shadow, ни :has(),
   ни will-change, ни анимации геометрии. Свечение — статичный radial-gradient.
   Постоянно живых узлов: 14 двухпиксельных звёзд + 1 гало ядра. Астры ✦
   ограничены 24 циклами базовым правилом .pg и через ~77с встают.
   ========================================================================= */

/* ── 1 · ШАПКА ─────────────────────────────────────────────────────────── */
.mx-screen{ padding:0 0 8px; }
/* «i» в правом верхнем углу шапки — вход в лист «Что это за язык».
   Абсолютная, чтобы не толкать заголовок и не ломать его перенос на узких экранах;
   .mx-head получает position:relative. Хит-зона расширена ::before до ~44px — глиф
   маленький, а промах по кружку читается как «кнопка не работает» (тот же приём, что
   у крестика шитов). Ни filter, ни тени: только цвет и transform на нажатии. */
.mx-head{ position:relative; }
.mx-info{ position:absolute; top:2px; right:2px; width:30px; height:30px; border-radius:50%;
  border:1px solid rgba(255,255,255,.20); background:rgba(255,255,255,.05); color:var(--hint,#9b91c4);
  font-weight:700; font-size:15px; line-height:1; font-family:inherit; font-style:italic;
  display:grid; place-items:center; cursor:pointer; -webkit-tap-highlight-color:transparent;
  transition:background .15s ease, color .15s ease, transform .08s ease; z-index:2; }
.mx-info::before{ content:""; position:absolute; inset:-7px; }
/* ПЕРЕЛИВ (основатель: «чтобы её хотелось тыкнуть»). Кольцевой блик, обходящий кнопку
   по кругу. Механика — вращение конического градиента через transform: круг
   поворотно-симметричен, поэтому двигается только блик, а не форма. Ни filter, ни
   box-shadow, ни background-position: доктрина производительности разрешает лишь
   opacity / transform / stroke-dashoffset, и здесь ровно transform.
   Клипа не нужно вовсе — а он бы и навредил: overflow:hidden срезал бы ::before, то есть
   расширенную до 44px зону нажатия, и кнопка стала бы 30px.
   Проходов 10 (~66 с), не бесконечно: экран пересобирается при каждом заходе, так что
   приглашение повторяется на входе, а не мельтешит всё время чтения. Тот же приём, что
   у премиального глифа (24 цикла и стоп). */
.mx-info::after{ content:""; position:absolute; inset:0; border-radius:50%;
  pointer-events:none;
  background:conic-gradient(from 0deg, rgba(255,255,255,0) 0deg,
    rgba(255,255,255,.17) 42deg, rgba(255,255,255,0) 108deg, rgba(255,255,255,0) 360deg);
  animation:mx-info-sheen 6.6s linear 10; }
@keyframes mx-info-sheen{ to{ transform:rotate(360deg); } }
@media (prefers-reduced-motion:reduce){
  .mx-info::after{ animation:none; opacity:.5; }
}
.mx-info:active{ transform:scale(.92); background:rgba(255,255,255,.11); color:var(--text,#f2eefb); }
/* заголовок не заезжает под кнопку */
/* 44px, а не 40: на 320px русский «Матрица рождения» оставлял до кнопки всего 11px —
   запаса на локаль подлиннее не было бы вовсе. */
/* ── ВЫБОР ЧЕЛОВЕКА ────────────────────────────────────────────────────────
   Не чип и не аватар: это тот же разделитель «волосок · знак · волосок», что живёт
   внутри листов (.rule), только вместо знака стоит имя. Селектор сделан из детали
   самой страницы, а не приклеен к ней.
   Волоски ЗОЛОТЫЕ: в этой розе золото означает «личное» (личный квадрат золотой,
   родовой — фиолетовый), и селектор человека говорит ровно об этом.
   Кегль и разрядка — от подписей узлов розы (.mx-node em), чтобы строка читалась
   как часть прибора, а не как элемент управления поверх него. */
/* z-index ОБЯЗАТЕЛЕН, и это не украшение. Роза подтянута вверх отрицательной маржой, и её
   сцена начинается ВЫШЕ низа этого переключателя: прозрачная коробка .mx-svg (inset:0,
   z-index:1) накрывала его целиком и съедала все нажатия — кнопка выглядела рабочей и
   молчала. Поймано только живым тапом: замер налезания смотрел на ВИДИМЫЙ лимб (8.6% от
   верха сцены), а накрывала невидимая часть.
   6 — выше всего, что есть внутри сцены (числа 3, ядро 4, тап-цель хорды 5). */
.mx-who{ position:relative; z-index:6;
  display:flex; align-items:center; gap:10px; width:100%; margin:10px 0 0;
  padding:0; border:0; background:none; cursor:pointer; font:inherit;
  -webkit-tap-highlight-color:transparent; }
.mx-who i{ flex:1; height:1px;
  background:linear-gradient(90deg,rgba(255,217,138,0),rgba(255,217,138,.28)); }
.mx-who i:last-child{ background:linear-gradient(90deg,rgba(255,217,138,.28),rgba(255,217,138,0)); }
.mx-who b{ font-size:11px; font-weight:800; letter-spacing:.14em; text-transform:uppercase;
  color:#cdc3ee; }
.mx-who s{ text-decoration:none; font-size:11px; line-height:1; color:var(--hint);
  transition:transform .12s ease; }
.mx-who:active s{ transform:translateY(1px); }
.mx-who:focus-visible{ outline:2px solid var(--accent); outline-offset:3px; border-radius:6px; }
/* Список в листе — строки без аватаров: на приборе человек опознаётся именем, а
   цветной кружок принёс бы сюда язык Прогноза. */
.mx-prof-list{ display:flex; flex-direction:column; margin-top:4px; }
.mx-prof{ display:flex; align-items:center; justify-content:space-between; gap:12px;
  padding:14px 2px; border:0; border-bottom:1px solid var(--line); background:none;
  color:var(--text); font:inherit; font-size:16px; text-align:left; cursor:pointer; }
.mx-prof:last-child{ border-bottom:0; }
.mx-prof.sel .mx-prof-n{ font-weight:700; }
.mx-prof-ck{ color:var(--accent); font-weight:800; }

.mx-head .mx-h1{ padding-right:44px; }

/* лист «Что это за язык» */
.mx-about h2{ margin:0 0 14px; font-size:19px; }
.mx-about p{ margin:0 0 12px; color:var(--hint,#9b91c4); font-size:14.5px; line-height:1.55; }
.mx-about .mx-about-hon{ color:var(--text,#f2eefb); }
/* Микро-тег в листе — та же капсула, что была на экране: рамка отличает знак-оговорку
   от прозы вокруг. Переиспользуем .mx-tag (он остался в CSS), обёртка лишь центрирует
   и держит верхний отступ; сам .mx-about-tag больше не нужен. */
.mx-lad-note{ text-align:center; color:var(--hint,#9b91c4); font-size:14px; line-height:1.55; margin:0; }
/* Первый абзац листа — «что это вообще»: чуть светлее прозы-оговорок под ним. */
.mx-about .mx-about-what{ color:var(--text,#f2eefb); }
.mx-about-chip{ margin:18px 0 0; text-align:center; }
.mx-about-chip .mx-tag{ display:inline-block; }
.mx-about .mx-about-tag{ margin-top:16px; font-size:12px; letter-spacing:.04em;
  text-transform:uppercase; opacity:.6; }
@media (prefers-reduced-motion:reduce){ .mx-info{ transition:none; } }
.mx-head{ padding:2px 2px 0; }
.mx-h1{ margin:0; font-size:26px; line-height:1.14; font-weight:800; letter-spacing:-.01em; color:var(--text); }
.mx-pos{ margin:9px 0 0; font-size:14.5px; line-height:1.42; color:#cdb8ff; font-weight:700; }
.mx-why{ margin:8px 0 0; font-size:12.5px; line-height:1.5; color:var(--hint); }
.mx-tag{ display:inline-block; margin:11px 0 0; padding:4px 10px; border-radius:999px;
  border:1px solid rgba(179,136,255,.24); background:rgba(179,136,255,.07);
  font-size:10px; font-weight:700; letter-spacing:.07em; text-transform:uppercase; color:#b9aee0; }

/* ── 2 · ГЕОМЕТРИЯ · РОЗА ВЕТРОВ ───────────────────────────────────────── */
/* НИЖНИЙ БЛОК ПОДТЯНУТ К РОЗЕ (основатель 2026-08-03: «хочется поближе видеть нижний
   блок»). Пустота под фигурой была не в разметке, а ВНУТРИ холста: сцена квадратная
   (aspect-ratio 1/1), а рисунок занимает по вертикали 86..914 из 1000 единиц viewBox —
   то есть снизу остаётся 8.6% пустой высоты. Отрицательный отступ в ПРОЦЕНТАХ (а не в
   px) съедает ровно её и масштабируется вместе с холстом: процент считается от ширины
   контейнера, а холст квадратный, поэтому 8.6% ширины = 8.6% высоты на любом экране.
   Дальше первому блоку задан собственный зазор — так «поближе» не превращается в
   «слиплось». Замер до: 57px между дугой лимба и строкой «1 / 4»; после: 18px. */
/* Сцена квадратная, а прибор в неё вписан кругом: сверху и снизу остаётся по 8.6%
   пустого поля (внешний лимб начинается с y=86 из 1000). Снизу это поле давно съедалось
   отрицательной маржой, сверху — нет, и над розой копился лишний зазор: замер дал 48px,
   из которых лишь 16 были собственно отступом, а 32 — пустотой внутри сцены.
   Теперь поле съедается с ОБЕИХ сторон, и воздух над прибором равен воздуху под ним. */
.mx-rose{ margin:-3.6% 0 -8.6%; }
.mx-rose + .mx-block{ margin-top:18px; }
.mx-stage{ position:relative; width:100%; aspect-ratio:1/1; margin:0 auto; overflow:visible;
  touch-action:manipulation; }
/* клип звёзд ПРЯМОУГОЛЬНЫЙ: круглая маска над 14 анимируемыми точками стоила бы
   отдельного mask-слоя даром — точки и так лежат внутри круга по координатам */
.mx-sky{ position:absolute; inset:0; z-index:0; pointer-events:none; overflow:hidden; }
.mx-star{ position:absolute; width:2px; height:2px; border-radius:50%; background:#dfe6ff; opacity:.5;
  animation:mx-tw 5s ease-in-out infinite; }
@keyframes mx-tw{ 0%,100%{ opacity:.14 } 50%{ opacity:.7 } }
.mx-svg{ position:absolute; inset:0; width:100%; height:100%; z-index:1; overflow:visible; }
/* ВСЕ штрихи — non-scaling-stroke. Без него viewBox 1000, сжатый в ~358px,
   превращает stroke-width:1 в 0.36px, и ОБА КВАДРАТА (главное требование канона)
   физически исчезают. Замерено: первый прогон макета был пустым. */
.mx-svg line,.mx-svg circle,.mx-svg rect{ vector-effect:non-scaling-stroke; }
.mx-ring-o{ fill:none; stroke:rgba(255,217,138,.20); stroke-width:1; }
.mx-ring-b{ fill:none; stroke:rgba(255,217,138,.10); stroke-width:1; }
.mx-ring-i{ fill:none; stroke:rgba(179,136,255,.09); stroke-width:1; }
.mx-sq{ fill:none; stroke-width:1; }
.mx-sq--self{ stroke:rgba(255,217,138,.20); }   /* личный квадрат — золотой волосок-чертёж */
.mx-sq--rod{  stroke:rgba(179,136,255,.09); }   /* родовой квадрат — фиолетовый волосок */
.mx-ray{ stroke:rgba(179,136,255,.09); stroke-width:1; }
.mx-ray--card{ stroke:rgba(255,217,138,.14); }
.mx-tick{ stroke:rgba(255,217,138,.10); stroke-width:1; }
.mx-tick--maj{ stroke:rgba(255,217,138,.20); stroke-width:1.2; }
.mx-pt-l{ fill:rgba(255,217,138,.05); }
.mx-pt-d{ fill:rgba(179,136,255,.042); }
.mx-pip{ fill:#a99fd0; opacity:.42; }
/* штифт пустого восьмого гнезда: честная заклёпка вместо натянутого числа */
/* Запертая строка хорды. Ни размытия, ни 🔒 — золотая «Астра», как во всём продукте.
   Число и название аркана остаются видимы: заперта проза, а не факт. */
.mx-ls-shut span{ color:var(--hint); }
.mx-ls-lock{ display:inline-flex; vertical-align:-2px; margin-left:4px; cursor:pointer; }
.mx-card--shut .mx-ctitle{ color:var(--hint); }
.mx-card--shut .describe-cue{ opacity:.5; }
/* Раздел хорды В СКРОЛЛЕ. Карточки строк — те же .mx-card, что во всех блоках, поэтому
   собственных правил у них нет и быть не должно: любая своя ширина/отступ здесь означала
   бы, что раздел разъедется с соседними при первой правке общих стилей.
   Своё тут ровно одно — заголовки групп ❤/$ между карточками. */
.mx-block--line .mx-ls-h{ margin:18px 0 8px; }
.mx-block--line .mx-ls-h:first-of-type{ margin-top:14px; }
/* Лист хорды. Ведёт СМЫСЛ, а не арифметика: два блока — что линия даёт в близости и
   что в деньгах, — и в каждом числа со своими арканами. Денежный выделен, потому что
   его привязку подтверждают все источники; остальные читаются вместе, потому что
   источники расходятся, какая точка за что отвечает поодиночке. */
.mx-ls-h{ display:flex; align-items:center; gap:8px; margin:18px 0 8px; }
.mx-ls-h b{ font-size:12px; font-weight:700; letter-spacing:.08em; text-transform:uppercase;
  color:var(--hint); }
.mx-ls-g{ display:grid; place-items:center; width:22px; height:22px; flex:0 0 22px;
  border-radius:50%; font-size:12px; font-weight:800; line-height:1; }
.mx-ls-h--heart .mx-ls-g{ background:rgba(179,136,255,.14); }
.mx-ls-h--heart .mx-ls-g svg{ width:13px; height:13px; display:block;
  fill:#cdc3ee; stroke:none; }
.mx-ls-h--money .mx-ls-g{ background:rgba(255,217,138,.16); color:#ffd98a; }
.mx-ls-l{ list-style:none; margin:0; padding:0; }
.mx-ls-l li{ display:flex; align-items:baseline; gap:10px; padding:7px 0;
  border-bottom:1px solid var(--line); }
.mx-ls-l li:last-child{ border-bottom:0; }
.mx-ls-l b{ flex:0 0 30px; font-size:19px; font-weight:800; color:#cdc3ee;
  font-variant-numeric:tabular-nums; text-align:right; }
.mx-ls-l span{ font-size:14px; line-height:1.45; color:var(--text); }
.mx-ls-l i{ font-style:normal; font-weight:700; }
.mx-ls-p{ margin:10px 0 0; font-size:14px; line-height:1.5; color:var(--text); }
.mx-ls-p em{ font-style:normal; font-weight:700; color:#cdc3ee; }
/* ── ХОРДА ЮГО-ВОСТОКА: линия любви и денег ───────────────────────────────────
   Гравюра на приборе, а не наклейка: ни одного числа, ни одной новой альфы.
   Нить идёт по средней линии треугольника C–E–D. Цвет — ТЕ ЖЕ чернила, что у знаков
   (#a99fd0), а не золото прибора: на первом рендере золотая нить с фиолетовыми знаками
   читалась как два несвязанных объекта, и грамматика «надето на нить» пропадала.
   Концы гаснут в ноль, чтобы не заявлять, будто нить выходит из P3 и EARTH — чужих
   чисел, стоящих в тех же местах.
   Глифы — чернила пипа #a99fd0 @ .42: единственный уровень, выживающий малым
   изолированным пятном на дешёвом OLED (золото .20 там даёт 1.6:1 и пропадает).
   ГРАММАТИКА ФОРМЫ: доллар ВРЕЗАН в нить (нить вокруг него разорвана) — R2 подтверждён,
   знак не сдвинуть.
   Сердце НАДЕТО бусиной и нить идёт сквозь него — школы расходятся, какая точка
   «под сердцем», и форма говорит это без слов.
   path не покрыт правилом vector-effect выше (там только line/circle/rect) — без
   этой строки контур рендерился бы штрихом 0.36px, то есть никак. */
.mx-svg path{ vector-effect:non-scaling-stroke; }
.mx-line{ animation:mx-linein .45s ease 1480ms backwards; }
@keyframes mx-linein{ from{ opacity:0 } to{ opacity:1 } }
.mx-thread{ fill:none; stroke:url(#mxThread); stroke-width:1; stroke-linecap:round; }
.mx-coin{ fill:none; stroke:#a99fd0; opacity:.42; stroke-width:1.2;
  stroke-linejoin:round; stroke-linecap:round; }
/* Сердце залито фоном приложения: нить видно на входе и выходе — значит надето, — но
   внутри её нет, и знак читается сплошным телом. Заливка идёт ВМЕСТЕ с обводкой, поэтому
   opacity на группе бы погасила и её: прозрачность вынесена в сам цвет обводки. */
.mx-bead{ fill:var(--bg,#0f0c1d); stroke:rgba(169,159,208,.42); stroke-width:1.2;
  stroke-linejoin:round; stroke-linecap:round; }
/* на 320px сцена ~292px и сердце падает до 7.6px: держим ТОЛЩИНУ, не размер —
   тот же приём, что у .mx-tick--maj */
@media (max-width:360px){ .mx-bead,.mx-coin{ stroke-width:1.4; } }
/* Тап-цель. z-index 5 — ВЫШЕ узлов (3) и ядра (4): глифы лежат внутри невидимых
   боксов P2 и EARTH, и без перебивки тап по сердцу открыл бы чужой разбор.
   14% сцены ≈ 50px на 358px и 41px на 320px — палец достаёт. */
.mx-line-hit{ position:absolute; left:59.5%; top:57.5%; transform:translate(-50%,-50%);
  width:14%; height:14%; z-index:5; border:0; padding:0; background:none;
  border-radius:50%; cursor:pointer; -webkit-tap-highlight-color:transparent; }
.mx-line-hit:focus-visible{ outline:2px solid var(--accent); outline-offset:2px; }
@media (prefers-reduced-motion:reduce){
  .mx-line{ animation:none !important; opacity:1; }
}
.mx-pin line{ stroke:rgba(179,136,255,.26); stroke-width:1.2; stroke-linecap:round; }
/* игла — ФИОЛЕТОВАЯ: золото зарезервировано за премиумом */
.mx-needle{ transform-box:view-box; transform-origin:500px 500px;
  animation:mx-settle 1.5s cubic-bezier(.22,.9,.28,1) .25s backwards; }
@keyframes mx-settle{
  0%{ transform:rotate(-7deg); opacity:0 }
  22%{ opacity:1 }
  58%{ transform:rotate(2.4deg) }
  80%{ transform:rotate(-.8deg) }
  100%{ transform:rotate(0deg); opacity:1 } }
.mx-nd-l{ fill:rgba(179,136,255,.34); }
.mx-nd-d{ fill:rgba(179,136,255,.15); }
.mx-core-disc{ fill:#1a1338; stroke:rgba(255,217,138,.20); stroke-width:1; }
.mx-core-rim{ fill:none; stroke:rgba(179,136,255,.16); stroke-width:1; }

/* УЗЛЫ — HTML поверх SVG, в тех же координатах (viewBox 1000 → /10 = %).
   Размеры в ПРОЦЕНТАХ сцены, а не в px: при фиксированных px на 320px экране
   ядро съедало по углу у внутренних узлов (замерено). В процентах зазор
   сохраняется на любой ширине. */
.mx-node{ position:absolute; transform:translate(-50%,-50%); z-index:3;
  width:16%; height:16%; border:0; padding:0; background:none; color:inherit; font:inherit;
  display:grid; place-items:center; cursor:pointer;
  animation:mx-nodein .5s cubic-bezier(.2,.8,.25,1) var(--d,0ms) backwards; }
/* fill-mode = BACKWARDS, а НЕ both. При `both` финальный кадр навсегда прибивает
   opacity:1 и перебивает `.mx-stage.sel .mx-node:not(.on){opacity:.30}` — выбор
   узла визуально не срабатывает ВООБЩЕ. Это уже наступленные грабли: не «улучшать».
   Плюс структурный иммунитет: вход живёт на РОДИТЕЛЕ (.mx-node), а выбор — на
   ДОЧЕРНЕМ (.mx-halo), так что каскады физически не пересекаются. */
@keyframes mx-nodein{ from{ opacity:0; transform:translate(-50%,-50%) scale(.72) }
                      to{ opacity:1; transform:translate(-50%,-50%) scale(1) } }
.mx-halo{ position:absolute; width:94%; height:94%; border-radius:50%; pointer-events:none;
  background:radial-gradient(circle,rgba(179,136,255,.26) 0%,rgba(179,136,255,.06) 42%,rgba(15,12,29,0) 68%); }
.mx-node b{ position:relative; font-size:25px; line-height:1; font-weight:800; color:var(--text);
  text-shadow:0 1px 3px rgba(6,4,20,.85); }
.mx-node em{ position:absolute; top:100%; left:50%; transform:translateX(-50%); margin-top:1px;
  width:96px; font-style:normal; text-align:center; line-height:1.15;
  font-size:8.5px; font-weight:700; letter-spacing:.08em; text-transform:uppercase;
  color:var(--hint); opacity:.9; }
/* угловые узлы: подпись СНАРУЖИ обода, в пустых углах квадратной сцены. Правило
   выведено замером: при «вниз у всех» на 320px «Твой вклад» садится на «Портрет». */
.mx-node--up em{ top:auto; bottom:100%; margin:0 0 1px; }
/* внутреннее кольцо: подписи НЕТ (смысл несут aria-label и живая строка под розой) —
   тринадцать nowrap-подписей 8.5px в 358px гарантированно наезжают друг на друга на
   восемнадцати локалях, а «Ступень земли» по-французски вдвое длиннее русского */
.mx-node--in{ width:12.5%; height:12.5%; }
.mx-node--in b{ font-size:15px; font-weight:700; color:#cdc3ee; }
.mx-node--in em{ display:none; }
/* невидимое расширение тап-зоны: визуально узел мал, палец — нет */
.mx-node--in::before{ content:""; position:absolute; inset:-7px; border-radius:50%; }
.mx-node--core{ width:20%; height:20%; z-index:4; }
.mx-node--core b{ font-size:34px;
  background:linear-gradient(180deg,#ffffff,#cdb8ff 130%);
  -webkit-background-clip:text; background-clip:text; color:transparent; text-shadow:none; }
.mx-node--core em{ margin-top:4px; font-size:9px; letter-spacing:.14em; color:#b9aee0; width:110px; }
/* гало ядра НАМЕРЕННО ужато до 108%: на 136% оно накрывало кончики иглы, и
   полуторасекундная усадка на север — главный жест концепта — проходила незаметно */
.mx-node--core .mx-halo{ width:108%; height:108%;
  background:radial-gradient(circle,rgba(179,136,255,.34) 0%,rgba(179,136,255,.10) 44%,rgba(15,12,29,0) 70%);
  animation:mx-breathe 6s ease-in-out infinite; }
@keyframes mx-breathe{ 0%,100%{ transform:scale(.9); opacity:.72 } 50%{ transform:scale(1.1); opacity:1 } }
/* выбор: остальные тускнеют. Только opacity — ни один пиксель геометрии не двигается. */
.mx-stage.sel .mx-node:not(.on){ opacity:.30; transition:opacity .35s ease; }
.mx-node.on{ z-index:6; }
.mx-node.on .mx-halo{ transform:scale(1.16); transition:transform .35s ease; }
.mx-node:active{ opacity:.6; }
.mx-node:focus-visible{ outline:2px solid var(--accent); outline-offset:2px; border-radius:12px; }
/* узкий экран: роза сжимается, подписи — нет */
@media (max-width:360px){
  .mx-node b{ font-size:22px; }
  .mx-node em{ font-size:7.5px; letter-spacing:.04em; width:84px; }
  .mx-node--core b{ font-size:30px; }
  .mx-node--in b{ font-size:13px; }
}
/* ЖИВАЯ ПОДПИСЬ — оглавление розы. Меняется по выбору узла и проговаривает арифметику
   словами. min-height держит два состояния без прыжка; запас взят под системный
   масштаб шрифта Android 1.3×, поэтому 54px, а не «ровно под стоковый кегль». */
/* ПУСТАЯ ПОДПИСЬ СХЛОПЫВАЕТСЯ. Сначала я оставил под неё резерв min-height, чтобы тап
   по числу не двигал макет, — но резерв дал видимую дыру под розой, и основатель её
   вычеркнул (2026-08-02). Компромисс: пустая не занимает места вовсе, а min-height
   работает уже на заполненной, поэтому ПЕРЕКЛЮЧЕНИЕ между числами по-прежнему не
   дёргает страницу. Сдвиг остаётся только у самого первого тапа — там человек
   смотрит на число, под которым подпись и появляется. */
/* .mx-cap и .mx-hint здесь были СИРОТАМИ — остались от подписи под розой, снятой
   2026-08-03 вместе с mxSetCaption. Проверено по HEAD~1: ноль употреблений в app.js.
   Удалены не ради чистоты, а потому что имя .mx-hint я только что занял под новую
   подсказку — и мёртвое правило, стоящее НИЖЕ живого, молча перебивало его отступы
   (поймано замером: правка margin не давала никакого эффекта). */

/* ── БЛОКИ ─────────────────────────────────────────────────────────────── */
.mx-block{ margin:26px 0 0; }
.mx-eyebrow{ display:flex; align-items:center; gap:8px; margin:0 2px 3px;
  font-size:10px; font-weight:800; letter-spacing:.14em; text-transform:uppercase; color:#8d83b8; }
.mx-eyebrow i{ flex:1; height:1px; background:linear-gradient(90deg,rgba(179,136,255,.22),rgba(179,136,255,0)); }
.mx-open{ color:var(--good); font-weight:700; letter-spacing:.02em; text-transform:none;
  font-size:10px; max-width:62%; text-align:right; }
.mx-btitle{ margin:0 2px 4px; font-size:19px; font-weight:800; line-height:1.2; color:var(--text); }
.mx-bsub{ margin:0 2px 12px; font-size:12.5px; line-height:1.48; color:var(--hint); }
.mx-noyear-note{ margin-top:10px; color:#cdc3ee; }

.mx-card{ background:var(--card); border:1px solid var(--line); border-radius:16px;
  padding:12px 13px; margin:0 0 9px; }
.mx-card.on{ border-color:rgba(179,136,255,.34); }
.mx-crow{ display:flex; align-items:center; gap:12px; cursor:pointer; }
.mx-crow:focus-visible{ outline:2px solid var(--accent); outline-offset:3px; border-radius:12px; }
/* самоцвет — уменьшенная родня .seal-hero .gem: те же три градиента, тот же внутренний
   кант. box-shadow СТАТИЧЕН (анимировать тень запрещено бюджетом). Цифра — var(--text),
   НИКОГДА не золотая: это бесплатный контент, а золото у нас значит «заперто». */
.mx-gem{ position:relative; flex:none; width:50px; height:50px; border-radius:15px;
  display:grid; place-items:center;
  background:
    radial-gradient(120% 120% at 30% 22%,rgba(255,255,255,.20) 0%,rgba(255,255,255,0) 32%),
    radial-gradient(140% 120% at 72% 84%,rgba(179,136,255,.30) 0%,rgba(0,0,0,0) 48%),
    linear-gradient(158deg,#4a3690 0%,#2c2154 46%,#1a1338 100%);
  border:1px solid rgba(179,136,255,.30);
  box-shadow:0 0 0 3px rgba(15,12,29,.9),0 10px 20px -12px rgba(0,0,0,.8),
             inset 0 1px 1px rgba(255,255,255,.20),inset 0 -10px 18px -9px rgba(0,0,0,.55); }
.mx-gem::after{ content:""; position:absolute; inset:7px; border-radius:9px; pointer-events:none;
  border:1px solid rgba(179,136,255,.20); }
.mx-gem b{ position:relative; z-index:2; font-size:22px; font-weight:800; color:var(--text); }
.mx-gem--core{ width:58px; height:58px; border-radius:18px; }
.mx-gem--core b{ font-size:26px; }
.mx-cmid{ flex:1; min-width:0; }
.mx-ctitle{ font-size:16.5px; font-weight:800; line-height:1.22; color:var(--text); }
.mx-crh{ margin-top:3px; font-size:9.5px; font-weight:700; letter-spacing:.11em;
  text-transform:uppercase; color:var(--hint); }
.mx-card .describe-cue{ flex:none; }
.mx-card .mx-body{ margin-top:2px; }

/* вопрос-подводка позиции — бесплатный крючок, не разбор */
.mx-q{ margin:12px 2px 0; font-size:13.5px; line-height:1.5; color:#cdb8ff; font-style:italic; }
.mx-rule{ display:flex; align-items:center; gap:10px; margin:14px 2px 2px; }
/* делитель ФИОЛЕТОВЫЙ, а не золотой: тратить золото на бесплатный текст нельзя */
.mx-rule i{ height:1px; flex:1;
  background:linear-gradient(90deg,rgba(179,136,255,0),rgba(179,136,255,.34),rgba(179,136,255,0)); }
.mx-rule b{ color:#b9aee0; font-size:10px; font-weight:800; letter-spacing:.12em; text-transform:uppercase; }
/* ТЕНЬ — один абзац по шаблону «перекос → выход», никогда приговором */
.mx-shift{ margin:14px 0 0; border-left:2px solid rgba(179,136,255,.26); padding:2px 0 2px 11px; }
.mx-shift span{ display:block; font-size:9.5px; font-weight:800; letter-spacing:.12em;
  text-transform:uppercase; margin-bottom:4px; color:#a99fd0; }
.mx-shift p{ margin:0; font-size:13.5px; line-height:1.55; color:#ddd5f2; }
/* традиционное имя аркана — подписью в глубине листа, и ПОД замком тоже: нейтральный
   титул нужен рынку, но скрыть традиционное имя совсем значило бы переименовать
   без раскрытия */
.mx-trad{ margin:14px 2px 0; font-size:11.5px; line-height:1.5; color:#8d83b8; }
.mx-trad b{ color:#a99fd0; font-weight:700; }
/* тизер — НАСТОЯЩЕЕ начало платной прозы, без размытия и без ••••: заперт текст, не пиксели */
.mx-teaser{ margin:12px 2px 0; font-size:14px; line-height:1.6; color:#bdb3dc; }
.mx-selfonly{ margin:12px 2px 0; font-size:12.5px; line-height:1.5; color:var(--hint); }

/* ── ПРЕМИУМ-ЗАМОК: астра ТОЛЬКО на строке разбора, никогда рядом с цифрой ── */
.mx-lock{ display:flex; align-items:flex-start; gap:10px; margin:11px 0 0; padding:10px 11px;
  border-radius:12px; border:1px solid rgba(244,200,105,.24); background:rgba(244,200,105,.07);
  cursor:pointer; }
.mx-lock:focus-visible{ outline:2px solid var(--pw-gold); outline-offset:2px; }
.pg--lock{ width:22px; height:22px; flex:none; }
.mx-lk-tx{ min-width:0; }
.mx-lk-t{ display:block; font-size:13.5px; font-weight:700; line-height:1.3; color:var(--gold); }
.mx-lk-s{ display:block; margin-top:3px; font-size:11.5px; line-height:1.45; color:#bdae8e; }
/* ЛЕНТА РАЗБЛОКИРОВКИ — одна на экран, в конце премиум-зоны */
.mx-unlock{ display:flex; align-items:center; justify-content:center; gap:9px; width:100%;
  margin:14px 0 0; padding:15px 14px; border-radius:15px; cursor:pointer;
  border:1px solid rgba(244,200,105,.42);
  background:linear-gradient(180deg,rgba(244,200,105,.17) 0%,rgba(244,200,105,.07) 100%);
  color:var(--gold); font:inherit; font-size:15px; font-weight:800; letter-spacing:.01em; }
.mx-unlock:active{ transform:scale(.985); }
.mx-unlock-sub{ margin:7px 4px 0; text-align:center; font-size:11.5px; line-height:1.45; color:#8d83b8; }

/* ── СТУПЕНИ: видимое сложение (своего разбора нет — ни замка, ни ✦) ────── */
.mx-lad{ display:flex; align-items:center; gap:10px; padding:10px 12px; margin:0 0 8px;
  border-radius:13px; background:rgba(255,255,255,.03); border:1px solid var(--line); }
.mx-lad.on{ border-color:rgba(179,136,255,.34); }
.mx-lad-nm{ flex:1; min-width:0; font-size:11.5px; line-height:1.35; color:var(--hint); }
.mx-lad-nm b{ display:block; font-size:12.5px; font-weight:700; color:#cdc3ee; margin-bottom:1px; }
.mx-sum{ flex:none; display:flex; align-items:center; gap:6px; font-size:14.5px; font-weight:700; color:#cdc3ee; }
.mx-sum s{ text-decoration:none; color:var(--hint); font-weight:600; }
.mx-sum u{ text-decoration:none; font-size:20px; font-weight:800; color:var(--text); }

/* ── СКВОЗНАЯ ЭНЕРГИЯ (только при реальном n ≥ 3; демо-плашек нет) ─────── */
.mx-thread{ display:flex; gap:13px; align-items:flex-start; margin:22px 0 0; padding:14px;
  border-radius:16px; border:1px solid rgba(179,136,255,.26);
  background:linear-gradient(180deg,rgba(179,136,255,.10) 0%,rgba(34,26,61,.7) 100%); }
.mx-thread-n{ flex:none; width:56px; text-align:center; }
.mx-thread-n b{ display:block; font-size:32px; font-weight:800; line-height:1; color:var(--text); }
.mx-thread-n s{ display:block; text-decoration:none; margin-top:4px; font-size:11px; font-weight:800;
  letter-spacing:.08em; color:#cdb8ff; }
.mx-thread-b{ min-width:0; }
.mx-thread-t{ font-size:15.5px; font-weight:800; line-height:1.25; color:var(--text); }
.mx-thread-p{ margin:7px 0 0; font-size:13.5px; line-height:1.55; color:#ddd5f2; }
.mx-thread-f{ margin:9px 0 0; font-size:11.5px; line-height:1.45; color:#8d83b8; }

/* ── РАЗРЫВ + ЛИЧНЫЙ РИТМ (ДРУГАЯ ТРАДИЦИЯ) ───────────────────────────── */
.mx-break{ display:flex; align-items:center; justify-content:center; gap:12px; margin:38px 0 22px; }
.mx-break i{ height:1px; flex:1; background:linear-gradient(90deg,rgba(179,136,255,0),rgba(179,136,255,.20)); }
.mx-break i+i{ background:linear-gradient(90deg,rgba(179,136,255,.20),rgba(179,136,255,0)); }
.mx-break b{ font-size:11px; letter-spacing:.16em; color:#7e75a8; font-weight:700; white-space:nowrap;
  text-transform:uppercase; }
/* другой КОРПУС, а не .mx-card: ритм нельзя дать спутать с арканом */
.mx-rhythm{ border:1px solid rgba(179,136,255,.22); border-radius:18px; padding:15px 14px;
  background:linear-gradient(180deg,rgba(26,21,48,.9),rgba(34,26,61,.6)); }
/* ── ЛИЧНЫЙ РИТМ. Число и имя года — ОДНА СТРОКА: «5 — Перемены». Раньше число стояло
   отдельно в правом углу шапки, а титул начинался абзацем ниже, и связь между ними
   приходилось додумывать (основатель 2026-08-03). Число крупнее и цветом акцента, имя
   года — обычным текстом заголовка: видно, что имя принадлежит числу, а не соседствует
   с ним. Подпись «Число 2026 года» стоит над строкой и объясняет, откуда число взялось. */
.mx-rh-lbl{ display:block; font-size:12.5px; font-weight:700; letter-spacing:.03em;
  text-transform:uppercase; color:var(--hint,#9b91c4); opacity:.75; }
.mx-rh-t{ display:flex; align-items:baseline; gap:9px; margin:8px 0 0;
  font-size:19px; font-weight:800; color:var(--text,#f2eefb); }
.mx-rh-big{ font-size:34px; font-weight:800; line-height:1; color:var(--accent,#b388ff); }
.mx-rh-dash{ font-style:normal; font-weight:400; color:var(--hint,#9b91c4); opacity:.55; }
.mx-rh-p{ margin:7px 0 0; font-size:14px; line-height:1.6; color:#ddd5f2; }
.mx-rh-school{ margin:13px 0 0; padding:10px 11px; border-radius:11px; background:rgba(255,255,255,.03);
  border:1px solid var(--line); font-size:11.5px; line-height:1.5; color:#8d83b8; }

/* ── ХВОСТ РАСКРЫТИЯ ──────────────────────────────────────────────────── */
.mx-tail{ margin:30px 0 0; padding:16px 14px; border-radius:18px; border:1px solid var(--line);
  background:rgba(255,255,255,.02); }
.mx-tail p{ margin:0 0 15px; font-size:12.5px; line-height:1.58; color:#a99fd0; }
.mx-tail p:last-child{ margin:0; }
.mx-tail-last{ color:#cdc3ee !important; }

/* ── СОСТОЯНИЕ «ГОД НЕИЗВЕСТЕН» (геометрии нет вообще) ────────────────── */
.mx-honest{ margin:14px 0 0; padding:13px; border-radius:14px; border:1px solid rgba(179,136,255,.22);
  background:rgba(179,136,255,.06); font-size:12.5px; line-height:1.55; color:#cdc3ee; }
.mx-honest b{ display:block; margin-bottom:5px; font-size:13.5px; color:var(--text); }
/* рамка СПЛОШНАЯ: пунктир 4 4 у нас читается как «приблизительно» */
.mx-ghost{ display:block; width:100%; margin:11px 0 0; padding:12px; border-radius:12px;
  border:1px solid rgba(179,136,255,.42); background:rgba(179,136,255,.10);
  color:#cdb8ff; font:inherit; font-size:14px; font-weight:700; cursor:pointer; }
.mx-ghost:active{ transform:scale(.985); }

/* ── ДВЕРЬ (лента Прогноза · низ «Характера») ─────────────────────────── */
/* НА ДВЕРИ НОЛЬ ЧИСЕЛ И НОЛЬ АРКАНОВ: дверь обещает раздел, а не выдаёт его.
   И ноль золота: раздел бесплатен по числам, дверь не имеет права выглядеть замком. */
.mx-door{ display:flex; align-items:center; gap:13px; width:100%; margin:14px 0 0; padding:14px 13px;
  text-align:left; border:1px solid rgba(179,136,255,.22); border-radius:16px;
  background:linear-gradient(180deg,rgba(179,136,255,.09),rgba(34,26,61,.55)); }
.mx-door-fig{ flex:none; width:40px; height:40px; }
.mx-door-fig svg{ width:100%; height:100%; display:block; }
.mx-door-sq{ fill:none; stroke:rgba(255,217,138,.20); stroke-width:1; vector-effect:non-scaling-stroke; }
.mx-door-sq--r{ stroke:rgba(179,136,255,.30); }
.mx-door-c{ fill:rgba(179,136,255,.55); }
.mx-door-tx{ flex:1; min-width:0; }
.mx-door-tx b{ display:block; font-size:15.5px; font-weight:800; line-height:1.25; color:var(--text); }
.mx-door-tx i{ display:block; margin-top:3px; font-style:normal; font-size:12px; line-height:1.4; color:var(--hint); }

/* ── ЛИСТ РАЗБОРА: переиспользуем премиальный .seal-sheet ─────────────── */
/* Отличия от планетной печати ровно два, и оба продиктованы законом токенов:
   (1) в самоцвете стоит ЧИСЛО, значит ни золотой оправы, ни золотого кольца —
       иначе золото касается цифры на бесплатном экране;
   (2) буквица манускрипта ФИОЛЕТОВАЯ, а не золотая (в .seal-sheet она золотая,
       но там весь текст платный, а здесь — блок «Ты» бесплатен целиком).
   Плюс снимаем mix-blend-mode с граней: смешивание заставляет слой читать backdrop
   на каждом кадре, а это цена запрещённого filter, просто не ловится грепом. */
.mx-sheet .seal-hero .gem{ width:104px; height:104px; border-radius:28px;
  border:1px solid rgba(179,136,255,.34);
  box-shadow:0 0 0 5px rgba(15,12,29,.9),
             0 18px 34px -12px rgba(0,0,0,.75),
             inset 0 1px 1px rgba(255,255,255,.24),
             inset 0 -14px 26px -10px rgba(0,0,0,.6); }
.mx-sheet .seal-hero .gem::before{ mix-blend-mode:normal; opacity:.55; }
.mx-sheet .seal-hero .gem::after{ inset:8px; border-radius:21px; border-color:rgba(179,136,255,.22); }
.mx-sheet .seal-hero .gem b{ position:relative; z-index:2; font-size:44px; font-weight:800; color:var(--text); }
.mx-sheet .manuscript p.lead::first-letter{
  background:var(--pw-seal-cold);       /* значение то же, теперь общий токен с листом .un-seal */
  -webkit-background-clip:text; background-clip:text; color:transparent; }
.mx-sheet .mx-unlock{ margin-top:12px; }

/* ── REDUCED MOTION: движение гаснет, НИЧЕГО не пропадает ─────────────── */
/* Деградация — в ПОЛНУЮ ЯРКОСТЬ и полный финальный кадр: узлы видны, игла стоит
   на севере, замки читаются (иначе locked стал бы неотличим от disabled). */
@media (prefers-reduced-motion:reduce){
  .mx-star,.mx-needle,.mx-node,.mx-node--core .mx-halo{ animation:none !important; }
  .mx-node,.mx-needle{ opacity:1; }
  .mx-node--core .mx-halo{ transform:none; opacity:1; }
  .mx-stage.sel .mx-node:not(.on){ transition:none; }
  .mx-node.on .mx-halo{ transition:none; }
  .mx-unlock:active,.mx-ghost:active{ transform:none; }
}

/* =========================================================================
   «НЕЗАПЕЧАТАННАЯ ПЕЧАТЬ» (.un-seal) — лист тела, которое ещё не встало на карту
   (openUnplacedSheet). ТРЕТЬЕ состояние того же предмета, что .seal-sheet (разбор
   планеты) и .mx-sheet (лист матрицы).

   ЗАКОН БЛОКА: печать — это ФОРМА, а не МЕТАЛЛ.
     тёплый металл  = отчеканено: знак известен и/или доступ платный;
     холодный + пунктир = форма есть, чеканки нет — не хватает данных рождения.
   ЧИСЛО МЕДАЛЬОНОВ = МЕРА ЗНАНИЯ: один (эталон) — знак известен; два — развилка,
   знак ровно один из двух; пустое гнездо — назвать нельзя ни одного.

   Чего здесь нет и не может появиться: премиального металла (в системе «Астра» он
   значит «есть, но платно», а тут «нет, потому что не хватает данных»), розового
   токена дефицита (он значит время и обратный отсчёт, а «время рождения» — поле
   анкеты, а не дедлайн), премиум-глифа системы и символа замка: замок ОТКАЗЫВАЕТ,
   а пустое гнездо ПРОСИТ — это разные глаголы.

   Лист сидит на КОРНЕ эталона (.seal-sheet), а не в параллельном неймспейсе: всё
   ниже только перебивает эталон более специфичным селектором. Дивиденд родства —
   блок prefers-reduced-motion эталона (стр. ~1487) перечисляет .gem/.sign-badge/
   .el-chip/h2.seal-title/.rule поимённо и гасит наши анимации даром. Эталон
   (1367–1492) не редактируется ни строкой.
   ========================================================================= */
.seal-sheet.un-seal{
  /* СУСТАВ СЕМЬИ: эталон гоняет весь металл через один --pw-seal (глиф, титул,
     буквица). Один локальный оверрайд перечеканивает все эти места разом — и
     автоматически подхватит любое место, которое эталон добавит завтра. */
  --pw-seal:var(--pw-seal-cold);
  /* .45 давало 2.37:1 на фоне шита — ниже порога WCAG 1.4.11 (3:1) для границы, которая
     является ЕДИНСТВЕННЫМ признаком интерактивности капсулы. .62 = 3.42:1. */
  --un-line:rgba(179,136,255,.62);   /* пунктир «дозаполнить данные», как у .onb-field-add */
  --un-hair:rgba(179,136,255,.38);
  text-align:center;
}
/* --- КАМЕНЬ: геометрия эталона целиком, снят ТОЛЬКО тёплый слой ободка -------
   Размер не уменьшаем: в приложении ровно два размера печати (132 полноразмерная и
   104 у .mx-sheet), третий раздробил бы систему. Ранг здесь несут металл и пустота. */
.seal-sheet.un-seal .seal-hero .gem{
  border:1px solid rgba(179,136,255,.34);
  box-shadow:
     0 0 0 5px rgba(15,12,29,.9),
     0 18px 34px -12px rgba(0,0,0,.75),
     inset 0 1px 1px rgba(255,255,255,.24),
     inset 0 -14px 26px -10px rgba(0,0,0,.6); }
/* mix-blend-mode заставляет слой граней читать backdrop КАЖДЫЙ кадр — это цена
   запрещённого filter, только грепом не ловится. Тот же снос уже стоит у .mx-sheet. */
.seal-sheet.un-seal .seal-hero .gem::before{ mix-blend-mode:normal; opacity:.55; }
.seal-sheet.un-seal .seal-hero .gem::after{ border-color:rgba(179,136,255,.20); }
/* ФОЛБЭК ПЕРВЫМ. Без background-clip:text заливка красит БОКС элемента: под глифом
   встала бы градиентная плашка, а поперёк титула — полоса. Поэтому в базовой ветке
   градиент СНЯТ и цвет плоский, а гравировка возвращается только там, где клип
   поддержан. #cfc9e6 — байт-в-байт цвет .fcw-un-g, того самого висящего глифа, по
   которому человек тапнул: лист читается как приближение к тому же предмету.

   ГРАБЛИ, НА КОТОРЫЕ УЖЕ НАСТУПИЛИ (2026-08-03, семь проверяющих подряд): здесь стоял
   СОКРАЩЁННЫЙ `background:`, а шорткат сбрасывает background-clip в border-box и по
   специфичности перебивает эталонные longhand'ы (styles.css:1422/1453). В итоге фолбэк
   САМ вызывал ровно ту аварию, от которой страховал: титул рисовался сплошной лавандовой
   полосой, глиф — прямоугольником, буквы исчезали (color:transparent эталона оставался).
   Поэтому ниже — ТОЛЬКО longhand background-image и ЯВНЫЙ клип в обеих ветках.
   Приёмка ведётся замером computed background-clip === 'text', а не чтением кода. */
.seal-sheet.un-seal .seal-hero .gem .pl,
.seal-sheet.un-seal h2.seal-title{ background-image:none; color:#cfc9e6;
  -webkit-background-clip:border-box; background-clip:border-box;
  -webkit-text-fill-color:currentColor; }
.seal-sheet.un-seal h2.seal-title{ color:#efe6ff; }
@supports ((-webkit-background-clip:text) or (background-clip:text)){
  .seal-sheet.un-seal .seal-hero .gem .pl,
  .seal-sheet.un-seal h2.seal-title{ background-image:var(--pw-seal);
    -webkit-background-clip:text; background-clip:text;
    color:transparent; -webkit-text-fill-color:transparent; }
}
/* --- ПУНКТИРНОЕ КОЛЬЦО на месте сплошного: ЧИСЛО ДУГ = ЧИСЛУ КАНДИДАТОВ.
   Периметр rect 146.5×146.5 r40 = 517.3 → 2 дуги: 190+68.66; 12 дуг: 26+17.11.
   Появляется через opacity и всё. Анимировать stroke-dashoffset тут НЕЛЬЗЯ: обе
   раскладки дают целое число периодов узора, поэтому «прорисовка» превратилась бы
   в бегущие муравьи — лист читался бы как «грузится». Кольцо — ТИХИЙ, второй
   носитель числа (нижние углы ему перекрывают медальоны); первый и главный —
   сами медальоны и полоса из двенадцати.
   ФАЗА И ОТСТУП (2026-08-03): при inset:-8px кольцо садилось вплотную к тёмному ореолу
   камня (box-shadow 0 0 0 5px) и читалось как вторая рамка, а оба разрыва развилки
   ложились на ЛЕВУЮ половину — «две дуги» на скриншоте не собирались. inset:-11px
   отодвигает кольцо от ореола, stroke-dashoffset выводит разрывы на ВЕРХ и НИЗ по
   центру, где их не перекрывают медальоны. dashoffset статичен — не анимируется. */
.seal-sheet.un-seal .un-ring{ position:absolute; inset:-11px; display:block;
  pointer-events:none; z-index:1; animation:unRingIn .5s ease .12s both; }
.seal-sheet.un-seal .un-ring rect{ fill:none; stroke:rgba(179,136,255,.55);
  stroke-width:1.5; stroke-linecap:round; }
/* Арифметика фазы. Путь rect стартует в (x+rx, y) — на верхней грани левее центра — и
   идёт по часовой; период узора 190+68.66 = 258.66, он же ровно половина периметра
   517.32, поэтому обе дуги симметричны. Верхний центр лежит на s = 66.5/2 = 33.25,
   центр разрыва в узоре — на (190+258.66)/2 = 224.33 → offset = 224.33 − 33.25 ≈ 191.
   Второй разрыв тогда автоматически садится ровно на нижний центр (s = 291.91), где его
   не перекрывают медальоны нижних углов. */
.seal-sheet.un-seal[data-un="fork"] .un-ring rect{ stroke-dasharray:190 68.66;
  stroke-dashoffset:191; }
.seal-sheet.un-seal[data-un="void"] .un-ring rect{ stroke-dasharray:26 17.11; }
/* деградация и будущие тела: ровный пунктир БЕЗ счётных дуг — число дуг есть утверждение
   о числе кандидатов, и там, где мы его не знаем, утверждать нечего */
.seal-sheet.un-seal[data-un="plain"] .un-ring rect{ stroke-dasharray:2 5.185; }
@keyframes unRingIn{ from{ opacity:0; } to{ opacity:1; } }
/* --- МЕДАЛЬОНЫ. Два — зеркально по нижним углам, эталонные -6/-6 сохранены.
   ОБА ИДЕНТИЧНЫ ДО ПИКСЕЛЯ, и это осознанный выбор: сервер отдаёт знаки на КРАЯХ
   суток, порядок хронологический, доли он не считает — значит любой перевес одного
   над другим был бы ранжированием, выдуманным в вёрстке. Равенство тоже утверждение
   («мы не знаем, какой»), и оно как раз правда. data-el стоит на самом бейдже →
   эталонное правило .sg красит каждого кандидата ЕГО стихией, ноль новой логики. */
.seal-sheet.un-seal .sign-badge{ border-color:var(--un-line); }
.seal-sheet.un-seal .sign-badge.badge-l{ left:-6px; right:auto; }
.seal-sheet.un-seal .sign-badge.badge-r{ animation-delay:.30s; }
/* ПУСТОЕ ГНЕЗДО. Внутрь нельзя ни «?» (выдуманное сомнение — мы не сомневаемся, мы
   знаем, что назвать нельзя), ни премиум-глифа, ни замка. Тонкое внутреннее кольцо —
   чтобы пустота читалась как ОПРАВА, а не как баг рендера. */
.seal-sheet.un-seal .sign-badge.is-empty{
  background:linear-gradient(160deg,#2a2150,#1b1538);
  border:1px dashed var(--un-line); }
.seal-sheet.un-seal .sign-badge.is-empty::after{
  content:""; position:absolute; inset:5px; border-radius:50%;
  border:1px solid rgba(179,136,255,.16); }
/* --- ЧИП: эталонная пилюля. У развилки две точки-стихии (кандидатов два — видно до
   всякого чтения), у оси карты одна ПОЛАЯ: стихии нет, потому что нет знака. Точки
   не сдвигаем друг на друга — со свечением радиусом больше диаметра они слились бы
   в одно пятно на 320dp, и «их два» перестало бы читаться. */
.seal-sheet.un-seal .el-chip{ border-color:rgba(179,136,255,.28);
  flex-wrap:wrap; max-width:min(300px,92%); justify-content:center; line-height:1.35; }
.seal-sheet.un-seal .el-chip .dot.dot-hollow{
  background:none; border:1px solid rgba(179,136,255,.6); box-shadow:none; }
/* --- ТИТУЛ: та же гравировка, другой сплав. Союз получает собственный
   text-fill-color, иначе клип родителя съест его цвет. */
.seal-sheet.un-seal h2.seal-title{
  font-size:clamp(calc(19px * var(--font-scale)),6.2vw,calc(24px * var(--font-scale)));
  text-wrap:balance; overflow-wrap:break-word; }
/* .55 давало 3.90:1 при 600/19.8px (это НЕ large text по WCAG: bold начинается с 700) —
   провал AA ровно на 320/360dp, то есть на дешёвом Android. .66 = 5.0:1, и союз всё
   равно вдвое тише самих имён знаков. padding .32em → .06em: настоящие пробелы вокруг
   союза теперь стоят в РАЗМЕТКЕ (см. app.js), и старый padding удвоил бы зазор. */
.seal-sheet.un-seal h2.seal-title .fork{
  -webkit-text-fill-color:rgba(201,188,240,.66); color:rgba(201,188,240,.66);
  font-weight:600; padding:0 .06em; white-space:nowrap; }
/* --- ДЕЛИТЕЛЬ: орган эталона сохранён, в метке стоит глиф САМОГО ТЕЛА. Премиум-глиф
   системы сюда нельзя даже перекрашенным: на быстром тапе он прочтётся как значок
   подписки, а лист ничего не продаёт. */
.seal-sheet.un-seal .rule i{
  background:linear-gradient(90deg,rgba(179,136,255,0),var(--un-hair),rgba(179,136,255,0)); }
.seal-sheet.un-seal .rule b{ color:#b9aee0; font-size:12px; opacity:.75; }
/* --- ДВЕНАДЦАТЬ, в слоте манускрипта: буквальное «за сутки ось проходит все
   двенадцать, поэтому назвать нельзя ни одного», сказанное формой — ноль строк,
   18 локалей по построению.
   ЖЁСТКО: ни один глиф НИКОГДА не подсвечивается и не пробегается по очереди. В любой
   кадр, где горит один из них, человек скринит и уносит с собой Асцендент, которого мы
   никогда не считали. По той же причине нет и стихийной раскраски: подсветка или вес
   любого глифа = названный знак на скриншоте.
   Форма — ряд, а не кольцо вокруг камня: кольцо радиусом ~92–100px первым вылезет
   за края на 320dp при --font-scale:1.30.

   СЕТКА, А НЕ ПЕРЕНОС (2026-08-03). Было flex-wrap + max-width:264px, и на ЛЮБОЙ ширине
   получалось 11+1: контенту нужно было 243px при внутренних 242px — промах в один пиксель.
   Одинокая ♓ во второй строке выделена сильнее любой подсветки, то есть полоса, чей
   единственный тезис «все двенадцать РАВНЫ», утверждала обратное. Двенадцать жёстких
   колонок 1fr: ряд ВСЕГДА один, сиротства не бывает ни при какой метрике шрифта и ни на
   какой ширине, а высота блока падает с 50px до 31px — те самые ~20px, которых не
   хватало кнопке на 320dp.
   ПУНКТИР СНЯТ: он в этом листе — токен «дозаполнить данные» и стоит на КНОПКАХ-капсулах
   ниже. Мёртвая (pointer-events:none, role=img) полоса в той же подаче собирала мёртвые
   тапы — ровно то, что лист лечит. Осталась волосяная сплошная рамка без заливки. */
.seal-sheet.un-seal .un-band{
  display:grid; grid-template-columns:repeat(12,1fr); align-items:center;
  justify-items:center; gap:0;
  margin:10px auto 0; max-width:288px; padding:7px 6px;
  border:1px solid rgba(179,136,255,.14); border-radius:14px;
  background:none; pointer-events:none;
  animation:fadeUp .5s ease .46s both; }
.seal-sheet.un-seal .un-band span{ font-size:13px; line-height:1; color:rgba(207,201,230,.45); }
/* --- ЧТО ДОБАВИТЬ: капсула r999 (родня .el-chip), а не полноширинный слэб — слэб
   читается как поле ввода и был половиной прежней чужеродности листа.
   Капсулы ВСЕГДА кнопки, даже когда она одна: на тач-устройстве нетапабельная плашка
   44px с рамкой и фоном неотличима от кнопки и собирает мёртвые тапы — ровно то, что
   этот редизайн лечит. Мягкая избыточность с CTA дешевле мёртвого тапа. */
.seal-sheet.un-seal .un-need{
  display:flex; flex-wrap:wrap; justify-content:center; gap:8px; margin:12px 0 0;
  animation:fadeUp .5s ease .52s both; }
.seal-sheet.un-seal .un-ask{
  display:inline-flex; align-items:center; justify-content:center;
  min-height:44px; padding:11px 16px; border-radius:999px;
  border:1px dashed var(--un-line); background:rgba(179,136,255,.07);
  color:var(--text); font-size:calc(13.5px * var(--font-scale));
  font-weight:700; line-height:1.25;
  font-family:inherit; }
.seal-sheet.un-seal button.un-ask{ cursor:pointer; -webkit-tap-highlight-color:transparent; }
.seal-sheet.un-seal button.un-ask:active{ transform:scale(.985); opacity:.85; }
/* outline-offset обязателен: кольцо фокуса того же тона слилось бы с пунктиром рамки */
.seal-sheet.un-seal button.un-ask:focus-visible{ outline:2px solid var(--accent); outline-offset:3px; }
/* --- CTA: полновесная фиолетовая заливка. НЕ .btn — его розовый акцент по закону
   токенов значит время и дефицит, а здесь ничего не горит. Белый даёт 6.7:1 на
   #5b3fd6 и 4.5:1 на #7f5ce8 — по всей развёртке не ниже AA. */
.seal-sheet.un-seal .un-cta{
  display:block; width:100%; min-height:52px; margin:13px 0 0; padding:14px 16px;
  border:0; border-radius:14px; cursor:pointer; font-family:inherit;
  background:linear-gradient(135deg,#5b3fd6 0%,#7f5ce8 100%); color:#fff;
  font-size:calc(15.5px * var(--font-scale)); font-weight:800; line-height:1.25;
  -webkit-tap-highlight-color:transparent;
  animation:fadeUp .5s ease .58s both; }
.seal-sheet.un-seal .un-cta:active{ transform:scale(.985); opacity:.9; }
.seal-sheet.un-seal .un-cta:focus-visible{ outline:2px solid #fff; outline-offset:2px; }
/* --- УЗКИЙ И НИЗКИЙ ЭКРАН: главная кнопка обязана быть ВИДНА без скролла.
   Замер до правки (320×568, ru/pt/es/fr/pl/uk, Асцендент + need=time_place): контент
   листа 559px против потолка 92vh = 522px, .un-cta уходил нижним краем на 585px при
   высоте окна 568 — человек видел верхнюю треть кнопки. Виновата пара капсул, которая
   в этих локалях не влезает в один ряд (299px против колонки 282px) поверх полосы из 12.
   Здесь мы 1) возвращаем капсулы в ОДИН ряд, ужав горизонтальный padding и кегль, и
   2) собираем вертикаль по 2–6px на каждом шве. Гем и медальоны НЕ трогаем: их размер —
   ранг предмета, а в приложении ровно два размера печати. */
@media (max-width:359px),(max-height:640px){
  .seal-sheet.un-seal .el-chip{ margin-top:12px; }
  .seal-sheet.un-seal h2.seal-title{ margin-top:12px; }
  .seal-sheet.un-seal .rule{ margin:12px 2px 2px; }
  .seal-sheet.un-seal .un-band{ margin-top:8px; padding:6px 4px; }
  .seal-sheet.un-seal .un-need{ margin-top:10px; gap:6px; }
  .seal-sheet.un-seal .un-ask{ padding:11px 12px; font-size:calc(12.5px * var(--font-scale)); }
  .seal-sheet.un-seal .un-cta{ margin-top:11px; min-height:50px; padding:13px 14px; }
}
/* --- НИЗКИЙ ЭКРАН (320×480 — реальный размер дешёвого Android и Mini-App с урезанным
   viewportHeight): даже после сжатия выше самая высокая ветка не влезает в потолок 92vh
   = 441px, потому что в pt/es/fr пара капсул физически не собирается в один ряд («Cidade
   de nascimento» + «Horário de nascimento» = 326px при колонке 282px, и уменьшать кегль
   дальше 12.5px уже нельзя). Поэтому главное действие ПРИЖИМАЕТСЯ к нижней кромке листа:
   объяснение над ним доскроллится, а кнопка видна всегда. position:sticky композитится и
   не нарушает перф-доктрину — ни filter, ни анимации геометрии здесь нет, а собственная
   непрозрачная заливка CTA не даёт содержимому просвечивать под ней. */
@media (max-height:560px){
  .seal-sheet.un-seal .un-cta{ position:sticky; bottom:0; z-index:2; }
}
/* --- пока лист открыт, колесо под ним не молотит: скрим шита сам по себе дорогой,
   каждый живой кадр под ним стоит вдвое. Класс на сцене ставит JS (не селектором
   родителя — он запрещён перф-доктриной). .un-open, а НЕ .selecting: .selecting гасит
   все невыбранные планеты до 32%, а здесь не выбрана ни одна — погасло бы всё колесо. */
.fc-wheel .fcw-stage.un-open .fcw-un-halo,
.fc-wheel .fcw-stage.un-open .fcw-un-g,
/* Пауза покрывала 2 узла из ~48, а комментарий обещал «колесо не молотит». Живыми под
   скримом оставались 34 звезды (.fcw-star, fcw-tw 3–7s) и гало КАЖДОЙ планеты
   (.fcw-halo, fcw-breathe 6s, да ещё с постоянным will-change). Звёзды лежат в
   .fcw-stars — СОСЕДЕ .fcw-stage, а не потомке, поэтому им нужен свой якорь: тот же
   класс JS вешает и на корневой .fc-wheel. */
.fc-wheel .fcw-stage.un-open .fcw-halo,
.fc-wheel.un-open .fcw-star{ animation-play-state:paused; }
/* --- reduced-motion: деградация в ПОЛНЫЙ финальный кадр. Ничего не пропадает —
   иначе пустое гнездо стало бы неотличимо от бага рендера. */
@media (prefers-reduced-motion:reduce){
  .seal-sheet.un-seal .un-ring,
  .seal-sheet.un-seal .un-band,
  .seal-sheet.un-seal .un-need,
  .seal-sheet.un-seal .un-cta{ animation:none; }
}

/* ═══════════════════════════════════════════════════════════════════════════════
   F3 · «РИТУАЛ ДНЯ» — CSS ИНЖЕНЕРА B: карточка блока, три шага-огня, премиум-плашки,
   хвост «Читать целиком», строка-вход в карточке колец.
   Разметку собирает fcRitualHtml() в app.js. Ниже по файлу идёт блок инженера C
   (трек, отклик, созвездие, нить, шеринг, пульс кольца) — он опирается на токены
   отсюда (--sph-*, --sc/--scb/--scc, --rit-glow) и обязан оставаться последним.
   Селекторы инженера C здесь НЕ переопределяются.

   Три правила, которые нельзя ослаблять правкой стилей:
   1) отметка — ОГОНЬ, а не галочка: .rit-step.lit не сереет, он светится цветом
      своей сферы (--sc), поэтому нигде нет ни grayscale, ни opacity на зажжённом;
   2) цвет нити слева — служебный код сферы, тот же, что у колец «Орбиты дня».
      Занимать его под настроение дня запрещено: в низком тоне тяжесть несут
      бейдж и сноска (--warn), а НЕ перекраска нитей;
   3) свечение — слой radial-gradient + переход opacity. Ни filter:blur(), ни
      анимированных box-shadow, ни color-mix(): дешёвые Android и WebView < 111.
   ═══════════════════════════════════════════════════════════════════════════════ */

/* ── токены сфер: БАЙТ В БАЙТ из живых колец (.rings .ring-item[data-sphere]).
      Все lit-состояния заданы явными rgba — color-mix() здесь не используется. */
.rit{ --sph-moon:#cfc4ee; --sph-none:#9b91c4; --rit-glow:1; }
.rit-step[data-sphere="moon"]   { --sc:#cfc4ee; --scb:rgba(207,196,238,.34); --scc:rgba(207,196,238,.65); }
.rit-step[data-sphere="love"]   { --sc:#ff6b8a; --scb:rgba(255,107,138,.34); --scc:rgba(255,107,138,.65); }
.rit-step[data-sphere="career"] { --sc:#4cc9f0; --scb:rgba( 76,201,240,.34); --scc:rgba( 76,201,240,.65); }
.rit-step[data-sphere="health"] { --sc:#5be3a7; --scb:rgba( 91,227,167,.34); --scc:rgba( 91,227,167,.65); }
.rit-step[data-sphere="luck"]   { --sc:#c792ea; --scb:rgba(199,146,234,.34); --scc:rgba(199,146,234,.65); }
/* СЕМЬЯ И ФИНАНСЫ — БЕЗ ЦВЕТНОГО МОСТА, И ЭТО НЕ ЗАБЫВЧИВОСТЬ. Цвет такта здесь значит
   ровно одно (CONCEPT §6.1): «это цвет кольца твоей сферы этажом выше». Колец рисуется
   четыре — love/career/health/luck (FC_RING_AREAS); family/finance живут строками разбора
   под «Показать полностью» и кольца не имеют НИКОГДА. У премиума фаворитом или риском дня
   законно становится именно они — и такт красился в #f0a35e, которого нет ни на одном
   кольце (а золото вдобавок спорит с системой «Астра», где золотой глиф = премиум-замок).
   Поэтому мост честно отсутствует: нить нейтральна, кольцо не пульсирует (ritRingPulse),
   а САМА СФЕРА никуда не девается — она названа словом в поводе («финансы — тонкий лёд»). */
.rit-step[data-sphere="family"],
.rit-step[data-sphere="finance"]{ --sc:#9b91c4; --scb:rgba(155,145,196,.34); --scc:rgba(155,145,196,.65); }
.rit-step[data-sphere="none"]   { --sc:#9b91c4; --scb:rgba(155,145,196,.34); --scc:rgba(155,145,196,.65); }

/* ── карточка блока. Свет — тот же приём, что у колец: мягкий радиальный источник
      в углу, «дыхание, а не мигание». Без него блок читался бы плоским листом
      рядом со светящимися соседями. В низком тоне свет приглушён (--rit-glow). */
.rit{ position: relative; overflow: hidden; }
/* СВЕТ СТАТИЧЕН. Здесь стояло бесконечное «дыхание» фона (7s infinite) — и это был
   ЕДИНСТВЕННЫЙ вечный цикл в блоке помимо разрешённого (4-секундное дыхание собранного
   созвездия, F3_SPEC §4.4 / CONCEPT §8). Он перерисовывал 220-пиксельный радиальный
   градиент каждый тик с первой секунды показа, независимо от состояния дня, — на дешёвых
   Android это лишний кадр вечно. Свечение никуда не делось, оно просто не мигает. */
.rit::before{
  content: ""; position: absolute; right: -40px; top: -70px; width: 220px; height: 220px;
  border-radius: 50%; pointer-events: none; opacity: var(--rit-glow);
  background: radial-gradient(circle, rgba(179,136,255,.20) 0%, rgba(179,136,255,0) 68%);
}
.rit[data-tone="low"]{ --rit-glow: .4; }

/* ── шапка: капс-подпись остаётся узнаваемой (h3 — ПЕРВЫЙ узел карточки) */
.rit-head{ display: flex; align-items: center; justify-content: space-between; gap: 10px; position: relative; }
.rit-head h3{
  margin: 0; font-size: calc(10px * var(--font-scale)); font-weight: 700;
  letter-spacing: .16em; text-transform: uppercase; color: var(--hint);
}
.rit.rit-full .rit-head h3{ color: var(--accent); }   /* «День собран» — единственная смена капса */

/* ── фраза дня: то, что человек унесёт, если больше ничего не прочтёт.
      Перенос НЕ захардкожен (<br> запрещён): балансировка + жёсткий потолок в три
      строки, чтобы самый длинный перевод (es/fr) не утопил третий такт под сгиб.
      -webkit-line-clamp ЗДЕСЬ — СТРАХОВКА, А НЕ РАБОЧИЙ МЕХАНИЗМ. Кегль подгоняет
      замером ritFitPhrase() в app.js: спека запрещает не только четвёртую строку, но и
      ellipsis, а самый длинный VoC-перевод (fr) на 390px при 24px честно занимал
      четыре строки — клэмп срезал ровно инструктивный хвост фразы. Теперь кегль
      уступает первым, и до троеточия дело не доходит ни в одной локали. */
.rit-phrase{
  margin: 11px 0 0; font-size: calc(24px * var(--font-scale)); line-height: 1.22;
  font-weight: 600; letter-spacing: -.015em; text-wrap: balance; color: var(--text);
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; overflow: hidden;
}
.rit-sky{ margin: 7px 0 0; font-size: calc(12.5px * var(--font-scale)); color: var(--hint); letter-spacing: .005em; }
.rit-sky b{ color: #cfc4ee; font-weight: 500; }
/* ☽ — не типографский знак, а маленькое тело со свечением, как все тела у нас */
.rit-lu{ color: #efe9ff; text-shadow: 0 0 9px rgba(207,196,238,.85), 0 0 20px rgba(179,136,255,.45); margin-right: 2px; }

/* тяжесть дня несёт --warn и НИКОГДА --bad: это про темп, а не про беду */
.rit-badge{
  display: inline-block; margin-top: 9px; padding: 3px 8px; border-radius: 9px;
  font-size: calc(10px * var(--font-scale)); font-weight: 700; letter-spacing: .13em; text-transform: uppercase;
  color: var(--warn); background: rgba(255,209,102,.10); border: 1px solid rgba(255,209,102,.20);
}
/* КАПС ЧИТАЕТСЯ И В ДВЕ СТРОКИ. Формулировка про пояс («день в твоём поясе закрылся ·
   только просмотр») длиннее короткого «вчера · только просмотр» и на 360–390px честно
   переносится — при line-height:1.2 и padding 3px вторая строка липла к нижней рамке. */
.rit-ro-cap, .rit-td-cap{
  display: inline-block; margin-top: 9px; padding: 4px 9px; border-radius: 9px;
  font-size: calc(10px * var(--font-scale)); font-weight: 700; letter-spacing: .13em; text-transform: uppercase;
  line-height: 1.45; color: var(--hint); background: rgba(255,255,255,.05); border: 1px solid var(--line);
}
/* «в твоём поясе это ещё сегодня» — не запрет, а разрешение: день ЖИВОЙ, кнопки на месте,
   и капс объясняет, почему живой ритуал стоит на колонке, которую рейл считает прошлой.
   Поэтому он лунно-лиловый (тот же голос, что у ☽-подсказок), а не серый «только просмотр». */
.rit-td-cap{
  color: #b9afdc; background: rgba(179,136,255,.08); border-color: rgba(179,136,255,.18);
}
.rit-hr{ height: 1px; background: var(--line); margin: 13px 0; }

/* ── подсказка первого раза стоит НАД карточками, сразу под строкой неба: под
      кнопкой «читать целиком» на 360×640 это ~600px вниз — вне экрана ровно в тот
      момент, когда она должна вербовать. Показывается один раз и больше никогда. */
.rit-hint{
  display: flex; gap: 8px; align-items: flex-start; margin: 0 0 10px; padding: 9px 11px;
  font-size: calc(12px * var(--font-scale)); line-height: 1.4; color: var(--hint);
  background: rgba(179,136,255,.07); border: 1px solid rgba(179,136,255,.14); border-radius: 12px;
  overflow: hidden;
}
/* ⟨РАУНД 1 ФИКС-ЦИКЛА, добивка правки 8⟩ ПОДСКАЗКА УХОДИЛА НЕ В ТОТ ЖЕ ТИК, ЧТО ТАП:
   display:none снимал 47 px под пальцем, и весь блок карточек мгновенно уезжал вверх.
   Лечилось отложенной на 2.45 с transition.
   ⟨РАУНД 2 ФИКС-ЦИКЛА⟩ ЛЕЧЕНИЕ ОТМЕНЕНО ЦЕЛИКОМ: ЗАДЕРЖКА НЕ УБИРАЛА СКАЧОК, А ПЕРЕНОСИЛА
   ЕГО НА 2.45 с — то есть ровно в тот момент, когда палец уже ушёл, но глаз читает
   карточки и целится в следующую кнопку. Замер: низ блока уезжал вверх на 47/63/64 px
   (390/360/320), и точка, где до тапа стоял центр кнопки 3-го такта, после схлопывания
   давала мёртвую зону карточки. Правка 8 («вёрстка не двигается — ни в момент тапа, ни
   позже») закрыта единственным способом, который держит оба конца: подсказка НЕ
   схлопывается живьём вовсе. Её жизнь кончается там же, где началась, — в разметке
   блока (условие «ноль огней» + флаг as_rit_hint_seen), поэтому при следующей сборке —
   собранный день, смена дня или вкладки, новый вход — её просто нет. «Один раз и больше
   никогда» держит флаг, а не таймер. Класс .rit-hint-off больше не назначается никем;
   правило оставлено как страховка на случай старой разметки в кэше — и оно тоже мгновенное
   и без анимации, потому что анимировать теперь нечего. */
.rit-hint.rit-hint-off{ display: none; }
/* МАРКЕР ПОДСКАЗКИ — ЛУННЫЙ, А НЕ ЗОЛОТОЙ. Золотая ✦ в приложении значит ровно одно:
   премиум-замок (доктрина «Астра»). Эта строка вербует в БЕСПЛАТНУЮ механику — с
   платным глифом она читалась бы как «а это уже в подписке», то есть закрывала бы вход
   ровно в том месте, где концепт его открывает. ☽ — то же тело, что в строке неба. */
.rit-hint-ic{
  flex: none; line-height: 1.4; color: #efe9ff;
  text-shadow: 0 0 8px rgba(207,196,238,.8), 0 0 18px rgba(179,136,255,.4);
}

/* ── карточки-шаги: три одинаковых по структуре блока = РИТМ, а не стена текста */
.rit-steps{ display: flex; flex-direction: column; gap: 9px; }
.rit-step{
  position: relative; display: flex; gap: 11px; align-items: flex-start;
  background: linear-gradient(180deg, rgba(255,255,255,.045) 0%, rgba(255,255,255,0) 46%), var(--bg2);
  border: 1px solid rgba(255,255,255,.05); border-radius: 16px;
  padding: 11px 11px 11px 15px; overflow: hidden;
  animation: rit-rise .42s cubic-bezier(.2,.7,.3,1) both;
}
.rit-step:nth-child(1){ animation-delay: .02s }
.rit-step:nth-child(2){ animation-delay: .08s }
.rit-step:nth-child(3){ animation-delay: .14s }
@keyframes rit-rise{ from{ opacity: 0; transform: translateY(3px) } to{ opacity: 1; transform: none } }
.rit-step .rit-thread{
  position: absolute; left: 0; top: 11px; bottom: 11px; width: 2px; border-radius: 2px;
  background: var(--sc); opacity: .75;
}
/* свечение зажжённого — СЛОЙ градиента с переходом opacity (не box-shadow, не blur) */
.rit-step .rit-glow{
  position: absolute; inset: 0; pointer-events: none; opacity: 0; transition: opacity .6s ease;
  background: radial-gradient(120% 80% at 0% 50%, var(--sc) 0%, rgba(0,0,0,0) 58%);
}
.rit-step.lit{ border-color: var(--scb); }
.rit-step.lit .rit-glow{ opacity: calc(.13 * var(--rit-glow)); }
.rit-step.lit .rit-thread{ opacity: 1; }
.rit-main{ flex: 1; min-width: 0; position: relative; }
/* капс-такт ОТДЕЛЬНОЙ строкой, повод — строкой ниже с переносом. nowrap/ellipsis
   запрещены: первым обрезался бы хвост со сферой, и связь с кольцами умерла бы в es/pt/fr. */
.rit-kick{
  font-size: calc(10px * var(--font-scale)); font-weight: 700; letter-spacing: .14em;
  text-transform: uppercase; color: var(--sc); line-height: 1.2;
  white-space: normal; overflow-wrap: break-word;
}
.rit-kick em{
  display: block; font-style: normal; font-size: calc(11px * var(--font-scale)); font-weight: 500;
  line-height: 1.3; letter-spacing: .005em; text-transform: none; color: var(--hint); margin-top: 4px;
}
.rit-kick em::before{
  content: ""; display: inline-block; width: 5px; height: 5px; border-radius: 50%;
  background: var(--sc); margin-right: 6px; vertical-align: middle; opacity: .9;
}
.rit-title{ font-size: calc(16px * var(--font-scale)); font-weight: 600; line-height: 1.25; margin-top: 6px; letter-spacing: -.01em; }
/* КЛЭМПА ЗДЕСЬ НЕТ СОЗНАТЕЛЬНО. Спека просила «максимум 2 строки», но -webkit-line-clamp
   рубит живое предложение посреди слова («…confort, lenteur et beso…») — в es/fr это
   случалось КАЖДЫЙ день, и обрезанная фраза читается как сломанный рендер, а не как
   лаконичность. Пояснение и так одно предложение; ровный ритм карточек держат рамка,
   нить и одинаковая структура, а не одинаковая до пикселя высота. */
.rit-text{ font-size: calc(13px * var(--font-scale)); line-height: 1.42; color: var(--hint); margin-top: 5px; }
.rit-note{ margin-top: 5px; font-size: calc(11.5px * var(--font-scale)); line-height: 1.35; color: #8a81b4; }
/* остальные позиции дневного каталога — премиуму содержимым, а не обещанием.
   СЛУЖЕБНОЙ ПОДПИСИ «ЕЩЁ ИЗ КАТАЛОГА ДНЯ» БОЛЬШЕ НЕТ (правка 5): она называла кухню,
   а не смысл, и была серой — то есть ничем не связывала список с тактом. Теперь
   принадлежность несут два канала, и оба работают ДО чтения:
   · подводка «Тоже в тему» / «Тоже не сегодня» — в цвете сферы такта (--sc), тем же
     голосом, что капс-метка карточки;
   · сам список — с левой нитью и точками-маркерами в том же цвете: глаз видит
     продолжение «ОБОЙДИ», а не отдельный список. */
.rit-more-lead{
  margin-top: 9px; font-size: calc(10.5px * var(--font-scale)); font-weight: 700;
  letter-spacing: .10em; line-height: 1.25; color: var(--sc); opacity: .95;
}
.rit-more{
  list-style: none; margin: 5px 0 0; padding: 0 0 0 9px;
  border-left: 1px solid var(--sc); border-color: var(--scb, var(--line));
}
.rit-more li{
  position: relative; padding-left: 12px;
  font-size: calc(13px * var(--font-scale)); line-height: 1.5; color: var(--hint);
}
.rit-more li + li{ margin-top: 2px; }
.rit-more li::before{
  content: "·"; position: absolute; left: 2px; top: -.06em;
  color: var(--sc); font-weight: 700; opacity: .9;
}
/* ✦-СТРОКА КАТАЛОГА — КОНТУРНАЯ КНОПКА, НЕ ЗОЛОТАЯ ПИЛЮЛЯ. Заливка+рамка+радиус делали
   из неё самый заметный объект карточки и обещали кнопку, которой тогда не было (тап
   ничего не делал). По доктрине «Астра» золото в приложении — это ГЛИФ замка, «никакой
   золотой заливки»: вид один в один с .rt-lock (замок нити), тач-цель добирается
   вертикальными отступами, а не рамкой. */
/* ⟨ПРАВКА 5 ОСНОВАТЕЛЯ, раунд 4⟩ Строка стала ФРАЗОЙ, а не двумя словами («ещё 2 шага» →
   «Ещё 2 варианта к этому шагу — в Premium»), и на 320px в самом длинном переводе честно
   занимает две строки. Поэтому: align-items:flex-start (глиф держится ПЕРВОЙ строки, а не
   уезжает в вертикальный центр абзаца), явный line-height и перенос длинных слов. */
.rit-more-lock{
  display: inline-flex; align-items: flex-start; gap: 6px; margin-top: 8px;
  padding: 6px 0; background: none; border: 0; border-radius: 0;
  font-family: inherit; text-align: left; cursor: pointer;
  font-size: calc(11.5px * var(--font-scale)); font-weight: 600; color: var(--gold);
  line-height: 1.4; overflow-wrap: anywhere;
}
/* глиф не сжимается и сидит на базовой линии первой строки */
.rit-more-lock .pg{ flex: none; margin-top: 1px; }
.rit-more-lock:active{ opacity: .7; }

/* ── кнопка-отметка. Незажжённый огонь — НЕ серый кружок, а звезда перед восходом:
      кольцо уже несёт цвет своей сферы, внутри слабое ядро. Иначе три главных
      действия дня выглядели бы мёртвыми чекбоксами рядом со светящимися кольцами. */
/* СЛОТ РАСТЁТ ПОД ПОДПИСЬ, А НЕ РЕЖЕТ ЕЁ. Ширина была жёсткой (68/60px), и на
   поддерживаемой шкале --font-scale 1.30 русское «ОТМЕТИТЬ» выходило за карточку на
   ~6px, где его срезал .rit-step{overflow:hidden} — на экране читалось «ОТМЕТИТI».
   nowrap+ellipsis запрещены концептом, поэтому лечим шириной: flex-базис = max-content
   (width:auto), фиксированное значение стало МИНИМУМОМ (тач-таргет 44px неприкосновенен),
   потолок держит текст шага от схлопывания. Место забирается у .rit-main, который умеет
   переносить строки, — обрезать нечего ни на одной ширине. */
.rit-mark{
  flex: 0 0 auto; width: auto; min-width: 68px; max-width: 40%;
  min-height: 44px; text-align: center; background: none; border: 0;
  padding: 2px 2px; font-family: inherit; cursor: pointer; position: relative; color: inherit;
}
.rit-circ{
  display: block; width: 32px; height: 32px; border-radius: 50%; margin: 1px auto 0; position: relative;
  border: 1.5px solid var(--scb, rgba(255,255,255,.16));
  background: radial-gradient(circle at 50% 50%, rgba(255,255,255,.10) 0%, rgba(255,255,255,.02) 62%, rgba(255,255,255,0) 100%);
  box-shadow: inset 0 0 10px -4px var(--sc, #fff);
  transition: border-color .35s ease, background .35s ease;   /* box-shadow НЕ анимируется — перф-доктрина */
}
.rit-circ::after{
  content: ""; position: absolute; inset: 5px; border-radius: 50%; background: var(--sc);
  opacity: 0; transform: scale(.4);
  transition: opacity .4s ease, transform .4s cubic-bezier(.2,.9,.3,1.2);
}
.rit-circ::before{
  content: ""; position: absolute; inset: -9px; border-radius: 50%; opacity: 0;
  background: radial-gradient(circle, var(--sc) 0%, rgba(0,0,0,0) 66%);
  transition: opacity .6s ease;
}
.rit-vb{
  display: block; margin-top: 5px; font-size: calc(10px * var(--font-scale)); font-weight: 700;
  letter-spacing: .06em; line-height: 1.2; min-height: 24px; text-transform: uppercase;
  color: #a99fd0; transition: color .35s ease;
  /* если слот всё же упёрся в потолок (очень длинный перевод + крупная шкала) —
     подпись ПЕРЕНОСИТСЯ, а не обрезается: нечитаемый огрызок хуже второй строки */
  white-space: normal; overflow-wrap: anywhere;
}
.rit-step.lit .rit-circ{ border-color: var(--scc); background: transparent; box-shadow: none; }
.rit-step.lit .rit-circ::after{ opacity: 1; transform: scale(1); }
.rit-step.lit .rit-circ::before{ opacity: calc(.5 * var(--rit-glow)); }
.rit-step.lit .rit-vb{ color: var(--sc); }

/* ── свёрнутый (отмеченный) шаг. Разметка остаётся ПОЛНОЙ — прячет её класс, поэтому
      оптимистичное зажигание в forecast_ritual.js это одна строка classList.add,
      без пересборки узла и без скачка высоты блока. */
.rit-step.fold{ padding: 10px 11px 10px 15px; align-items: center; }
/* КАПС-ТАКТ ПЕРЕЖИВАЕТ СВОРАЧИВАНИЕ. Прятался и он — и три собранные строки читались
   одинаково: «Дай телу медленный старт» / «💬 Откровенные разговоры» / «📌 Новые
   обязательства». Каталог отдаёт заголовки-существительные, поэтому без слова «ОБОЙДИ»
   такт воздержания выглядит как ВЫПОЛНЕННАЯ рекомендация — совет дня переворачивается
   наизнанку. Остаётся только сам такт: повод (em) в свёрнутом виде не нужен. */
.rit-step.fold .rit-kick{ font-size: calc(9.5px * var(--font-scale)); letter-spacing: .12em; opacity: .92; }
.rit-step.fold .rit-kick em{ display: none; }
.rit-step.fold .rit-text,
.rit-step.fold .rit-note,
.rit-step.fold .rit-more,
.rit-step.fold .rit-more-lead,
.rit-step.fold .rit-more-lock{ display: none; }
.rit-step.fold .rit-title{ margin-top: 3px; font-size: calc(14.5px * var(--font-scale)); color: #d9d1f2; }
.rit-step.fold .rit-mark{ width: 44px; min-width: 44px; min-height: 36px; }
.rit-step.fold .rit-vb{ display: none; }
.rit-step.fold .rit-circ{ width: 26px; height: 26px; }

/* «Сегодня хватит одного огня»: обещание бейджа выполняется в ТОМ ЖЕ экране — такты 2–3
   идут без ✦-замка и без списка «тоже подойдёт», такт «Настройся» полный.
   ⟨РАУНД 3 ФИКС-ЦИКЛА⟩ ПРИЧИНУ ШАГА ЭТОТ РЕЖИМ БОЛЬШЕ НЕ ПРЯЧЕТ. Здесь стояло
   `display:none` для .rit-text — вместе с веткой «slim → сноска вместо текста» в app.js
   это оставляло дефолтный экран свежего пользователя с двумя карточками без единого
   «почему». Снятие нагрузки — это МЕНЬШЕ ДЕЛ (один огонь вместо трёх, никаких доп-позиций),
   а не меньше честности: вторая строка остаётся, просто звучит тише основного текста. */
.rit-step.slim .rit-text{ opacity: .86; }
.rit-step.dim{ opacity: .62; }
.rit-step.dim .rit-glow{ display: none; }

/* только чтение («вчера»): это НЕ кнопка — курсор не меняется, тапа нет, и
   dead_tap не отравляется мёртвым аффордансом.
   ФОРМА ОБЯЗАНА ОТЛИЧАТЬСЯ ОТ ЖИВОГО ОГНЯ. Раньше метка была тем же 32/26px кругом
   с цветным кольцом и заливкой, что и зажжённый огонь «сегодня»: на глаз разницы
   ноль, и самый заметный объект экрана «вчера» выглядел нажимаемым. Теперь это
   архивная отметка: меньший диаметр, ПУНКТИРНОЕ кольцо (у живого огня оно сплошное),
   ядро вполовину и общая приглушённость. Плюс тихий отклик на тап — ritRoTap(). */
.rit-ro{ flex: 0 0 auto; width: 44px; min-height: 36px; display: flex; align-items: center; justify-content: center;
  cursor: default; opacity: .74; }
/* .rit-step.fold .rit-circ выше по файлу задаёт 26px и весит 0,3,0 — архивной метке
   нужен вес не меньше, иначе она осталась бы того же размера, что живой огонь. */
.rit-ro .rit-circ,
.rit-step.fold .rit-ro .rit-circ{ width: 20px; height: 20px; border-color: var(--scc); border-style: dashed; box-shadow: none; background: transparent; }
.rit-ro .rit-circ::after{ opacity: .85; transform: scale(.52); }
.rit-ro.off{ opacity: .5; }
.rit-ro.off .rit-circ{ border-color: rgba(255,255,255,.16); }
.rit-ro.off .rit-circ::after{ display: none; }

/* ── сноски блока. Ни одна не наказывает за пропуск и не обещает исхода. */
.rit-note-low{
  margin: 11px 0 0; font-size: calc(12.5px * var(--font-scale)); line-height: 1.45; color: var(--hint);
  border-left: 2px solid rgba(255,209,102,.5); padding-left: 10px;
}
.rit-note-low.calm{ border-left-color: rgba(155,145,196,.4); }
/* ⟨ПРАВКА 6 ОСНОВАТЕЛЯ, раунд 4⟩ ИНВАРИАНТ ПОДВАЛА: карточка ритуала заканчивается НА
   СВОЁМ СОДЕРЖИМОМ. data-foot="none" — состояние «после трёх шагов не идёт ничего»
   (ноль огней, нет нити, нечего шерить, коллекция пуста): под последним объектом не
   остаётся ни зарезервированной высоты, ни висячего поля — только собственный отступ
   карточки, тот же самый, что сверху (16px). Правило намеренно НЕ добавляет в подвал
   декорацию: «заполнить чем-нибудь» правка запрещает прямым текстом, а два содержательных
   кандидата (фигура и нить) отпали по причинам, записанным у сборки блока в app.js.
   ЛЮБОЙ будущий объект подвала обязан появляться вместе со своим значением data-foot —
   иначе он вернёт сюда ровно ту пустую полосу, из-за которой правка и появилась. */
.rit[data-foot="none"] > .rit-steps{ margin-bottom: 0; }
.rit[data-foot="none"] > :last-child{ margin-bottom: 0; }
/* .rit-note-low.gold удалён вместе со своей единственной строкой («Сегодняшний ритуал —
   бесплатно и целиком»): золотая планка означает в приложении цену, а в блоке ритуала
   разговора про цену быть не должно — см. комментарий у plate в app.js. */

/* ── нить приезжает из forecast_ritual.js (.rt-* — его зона). Здесь только её
      место в стопке блока: отбивка и линия-разделитель. */
.rit-thread7{ margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--line); }

/* ── премиум ✦ в блоке: РОВНО ДВЕ поверхности, и обе честные — ✦-строка каталога
      внутри шага и замок нити на 30 дней внутри самой нити. Плашка «✦ Завтра» и её
      CTA удалены вместе со стилями: они продавали завтрашний день, который у
      бесплатного открывается одним тапом по рейлу дней, а премиуму не давали сверх
      этого ничего (кнопок отметки завтра нет ни у кого). Замок, обещающий сверх
      данных, доктриной «Астра» запрещён. */

/* «завтра»: кнопок-отметок нет ВОВСЕ — отмечать несделанное было бы игрой.
   МАРКЕР ЛУННЫЙ, А НЕ ЗОЛОТОЙ: строка объясняет устройство БЕСПЛАТНОЙ механики,
   и ✦ читалась бы как «а это уже в подписке» (та же логика, что у .rit-hint-ic). */
.rit-not-yet{
  display: flex; gap: 9px; align-items: flex-start; margin-top: 11px; padding: 12px 13px;
  background: var(--bg2); border: 1px solid var(--line); border-radius: 14px;
  font-size: calc(13px * var(--font-scale)); line-height: 1.45; color: #b9afdc;
}
.rit-not-yet .rit-ny-ic{
  flex: none; line-height: 1.45; color: #efe9ff;
  text-shadow: 0 0 8px rgba(207,196,238,.8), 0 0 18px rgba(179,136,255,.4);
}

/* ── ССЫЛКИ «ЧИТАТЬ ПРОГНОЗ ЦЕЛИКОМ» БОЛЬШЕ НЕТ ⟨FIX_RITUAL_5 п.1⟩: основатель открыл
   полный абзац по умолчанию, и .rit-tail/.rit-chev удалены вместе с ritToggleFull —
   мёртвых селекторов не держим. #fc-more остаётся живым контейнером абзаца. */
.rit #fc-more .fc-text{ margin: 2px 0 6px; }

/* ── чипы «два плюса / два минуса дня» ⟨FIX_RITUAL_5 п.2⟩: стоят сразу под полным
   абзацем, до карточек шагов. Плюсы — мятный акцент (--good), минусы — приглушённый
   красный (тон --bad, осаженный по насыщенности: это предостережение, а не тревога).
   На 320×568 ряды переносятся flex-wrap'ом — чипы никогда не обрезаются (без
   ellipsis, текст внутри чипа переносится). Никакой анимации — глушить в
   reduced-motion нечего. */
.rit-chips{ display: flex; flex-direction: column; gap: 7px; margin: 10px 0 2px; }
.rit-chips-row{ display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.rit-chips-k{
  font-size: calc(11px * var(--font-scale)); font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: var(--hint, #9b91c4); margin-right: 2px;
}
.rit-chip{
  display: inline-block; padding: 4px 11px; border-radius: 999px;
  font-size: calc(12.5px * var(--font-scale)); line-height: 1.35;
  white-space: normal; overflow-wrap: anywhere;
}
.rit-chips-row.plus .rit-chip{
  color: #a8ecce; border: 1px solid rgba(91,227,167,.32); background: rgba(91,227,167,.09);
}
.rit-chips-row.minus .rit-chip{
  color: #f0aab9; border: 1px solid rgba(255,107,138,.26); background: rgba(255,107,138,.07);
}

/* СВЁРНУТОЙ ПОЛОСЫ «ДЕНЬ СОБРАН» (.rit-peek) БОЛЬШЕ НЕТ — правка 3 основателя.
   Разметку сняли вместе с ritPeekHtml() в app.js; стили, keyframes дыхания её точки
   и её зеркало в prefers-reduced-motion удалены здесь, чтобы мёртвых селекторов в
   блоке не осталось. Вход в механику держат трек огней в шапке блока и подсказка
   первого раза над карточками. */

/* ── 360×640 (реальный дешёвый Android): фраза дня уступает кегль, потолок в три
      строки держит самый длинный перевод; слот кнопки сужается, но тач-таргет 44px
      остаётся неприкосновенным. */
@media (max-width: 380px){
  .rit-phrase{ font-size: calc(20px * var(--font-scale)); }
  .rit-mark{ min-width: 60px; max-width: 44%; }
  .rit-step{ padding-left: 13px; gap: 9px; }
}

/* ── REDUCED MOTION: все переходы 0 мс, конечные состояния мгновенные, дыхание
      выключено. Деградация в ФИНАЛЬНЫЙ кадр, а не в пустоту: каскад карточек не
      съедает их opacity, зажжённый огонь остаётся зажжённым. */
@media (prefers-reduced-motion: reduce){
  .rit::before,
  .rit-step{ animation: none; }
  .rit-step{ opacity: 1; transform: none; }
  .rit-step .rit-glow,
  .rit-circ, .rit-circ::after, .rit-circ::before,
  .rit-vb{ transition: none; }
}


/* ═══════════════════════════════════════════════════════════════════════════
   F3 · «РИТУАЛ ДНЯ» — CSS ИНЖЕНЕРА C · НАЧАЛО
   Зона: трек огней, отклик, строка «не сохранилось», вечерняя сноска,
   созвездие дня, нить из 7 дней, кнопки шеринга, пульс кольца.
   Разметку этих узлов генерирует web/forecast_ritual.js (window.FRIT) — здесь
   и только здесь их стили. Инженер B эти селекторы не переопределяет.

   ПРАВИЛА, КОТОРЫЕ НЕЛЬЗЯ ОСЛАБЛЯТЬ (F3_SPEC §0, CONCEPT §8):
     · никакого filter:blur(), никаких анимированных box-shadow, никакого
       color-mix() — дешёвые Android WebView < Chromium 111;
     · свечение = слой radial-gradient + переход opacity;
     · зациклена РОВНО одна анимация — 4-секундное дыхание собранного
       созвездия; дыхание пустой точки трека живёт до первого огня;
     · prefers-reduced-motion: reduce → всё в финальные кадры.
   ═══════════════════════════════════════════════════════════════════════════ */

/* Слои свечения (::after у точки трека и у сегодняшней точки нити) выходят за
   контент-бокс карточки на 6–7px и порождали горизонтальный скролл документа на
   360px. Карточка клипует по своему padding-box: свечение видно целиком (оно
   лежит внутри 16px паддинга), а страница больше не едет вбок. Тот же приём в
   прототипе — .ritual{overflow:hidden}. */
.card.rit{ overflow:hidden; }

/* ─────────── трек огней в шапке (он же обещание вечернего созвездия) ─────────── */
/* Точки соединены нитью ЕЩЁ ДО того, как их зажгли: обещание кадра стоит в
   шапке, а не только в награде. Заливка не ниже .34 + обводка — контраст ≈4.4:1
   (прежние 1.9:1 не доживали до тапа ни у кого). */
.rit-track{ display:flex; gap:7px; align-items:center; position:relative; flex:0 0 auto; }
.rit-track::before{
  content:""; position:absolute; left:2px; right:2px; top:50%; height:1px;
  background:linear-gradient(90deg,rgba(255,255,255,.06),rgba(255,255,255,.26),rgba(255,255,255,.06));
}
.rit-track i{
  width:9px; height:9px; border-radius:50%; display:block; position:relative;
  background:rgba(255,255,255,.34); border:1px solid rgba(255,255,255,.45);
  transition:background .4s ease;
}
/* 0 из 3 — первая точка ДЫШИТ (не мигает). Единственный бессловесный сигнал
   «здесь есть что делать»; гаснет навсегда с первым же огнём. Такта ТРИ, а не
   бесконечность: вербует момент прихода глаза, а вечный цикл в блоке разрешён
   ровно один — дыхание собранного созвездия (F3_SPEC §4.4 / CONCEPT §8).
   ТАКТЫ ОТСЧИТЫВАЮТСЯ ОТ ВСТРЕЧИ С ГЛАЗОМ, А НЕ ОТ ВКЛЕЙКИ БЛОКА. Замер: карточка
   ритуала появляется на 763–791 px ниже верха экрана (то есть целиком за первым
   экраном и на 360×640, и на 390×844), а 3 × 3.6 с ≈ 11 с истекают раньше, чем
   человек доскроллит (медиана времени на экране 8.8 с) — сигнал не доживал до
   глаза НИ РАЗУ. Класс .rit-seen ставит первое пересечение блока с вьюпортом
   (IntersectionObserver в forecast_ritual.js, тот же, что шлёт ritual_view). */
.rit.rit-seen .rit-track.empty i:first-child{ animation:ritDotBreath 3.6s ease-in-out 3; }
@keyframes ritDotBreath{
  0%,100%{ transform:scale(1);    background:rgba(255,255,255,.34); }
  50%    { transform:scale(1.28); background:rgba(255,255,255,.62); }
}
.rit-track i.lit{ background:var(--tc,#b388ff); border-color:transparent; }
.rit-track i.lit::after{
  content:""; position:absolute; inset:-7px; border-radius:50%;
  background:radial-gradient(circle, var(--tc,#b388ff) 0%, rgba(0,0,0,0) 68%);
  opacity:calc(.55 * var(--rit-glow,1));
}
/* капс шапки при собранном дне */
.rit-head h3.rit-cap-done{ color:var(--accent,#b388ff); }

/* ─────────── отклик: короткая реплика продукта, а не похвала ───────────
   ⟨ПРАВКА 8 ОСНОВАТЕЛЯ, раунд 4⟩ ОТКЛИК БОЛЬШЕ НЕ ЗАНИМАЕТ МЕСТА В ПОТОКЕ. Он был
   обычным блоком между карточками шагов: появлялся — блок ритуала вырастал на ~28 px
   и всё под ним уезжало вниз, через 2.2 с уезжало обратно. Основатель: «эти всплывашки
   интересные, но ломают экран… как облачко/пилюля, которое не в рамках этого блока».
   Теперь это фиксированный слой на <body> (#rit-echo-layer), position:fixed → ноль
   участия в потоке: соседи не сдвигаются ни на пиксель, что бы ни всплыло.
   pointer-events:none у слоя и у пилюли — палец продолжает попадать по карточкам под
   ней (второй огонь тапают сразу после первого). Уходит сама; JS снимает весь слой. */
.rit-echo-layer{
  position:fixed; left:0; right:0; z-index:55;      /* ниже шитов (60) и тостов (80), выше таббара (30) */
  display:flex; justify-content:center; padding:0 14px;
  pointer-events:none;
}
.rit-echo{
  max-width:min(340px, 100%); box-sizing:border-box;
  padding:9px 15px; border-radius:15px; text-align:center;
  font-size:calc(12.5px * var(--font-scale,1)); line-height:1.35; font-weight:600;
  color:var(--ec,var(--accent,#b388ff));
  background:rgba(28,22,52,.95); border:1px solid rgba(255,255,255,.10);
  box-shadow:0 12px 30px -14px rgba(0,0,0,.85), 0 0 0 1px rgba(0,0,0,.18);
  -webkit-backdrop-filter:blur(6px); backdrop-filter:blur(6px);
  pointer-events:none;
  opacity:0; transform:translateY(6px) scale(.97);
  /* только opacity и transform — перф-доктрина */
  transition:opacity .22s ease, transform .26s cubic-bezier(.2,.9,.3,1.1);
}
.rit-echo.in{ opacity:1; transform:none; }
/* отклик метки «вчера»: объяснение, а не похвала — тон служебный, без цвета сферы */
.rit-echo-ro{ color:var(--hint,#9b91c4); font-weight:500; }

/* ─────────── «не сохранилось»: тихая сноска, ни модалки, ни красного ─────────── */
.rit-sync{
  margin-top:9px; font-size:calc(13px * var(--font-scale,1)); line-height:1.4;
  color:var(--hint,#9b91c4);
}

/* ─────────── вечерняя строка про «обойди» ─────────── */
.rit-note-ev{
  margin-top:11px; font-size:calc(12.5px * var(--font-scale,1)); line-height:1.45;
  color:var(--hint,#9b91c4); border-left:2px solid rgba(155,145,196,.4); padding-left:10px;
}

/* ШЕРИНГА НА ШАГЕ НЕТ (правка 2 основателя): кнопка ↗ и её стили удалены целиком.
   Внутри карточки остаётся ровно одно действие — огонь. Делятся собранным ДНЁМ
   (.rit-done → ritShareDay), а не отдельным пунктом.
   Порядок в свёрнутом шаге держит сама кнопка-отметка. */
.rit-step.fold .rit-mark{ order:2; }

/* ─────────── ФИГУРА ДНЯ: НАСТОЯЩЕЕ СОЗВЕЗДИЕ ─────────── */
/* Координаты звёзд — гномоническая проекция настоящих RA/Dec (J2000), масштаб по
   обеим осям ОДИН: растянутый Ковш перестаёт быть Ковшом. Поэтому у панели нет ни
   фиксированной высоты, ни object-fit — высоту задаёт сам SVG через свой viewBox
   (пропорция фигуры), а неиспользованное поле кадра остаётся пустым небом.
   Никаких filter:blur() и анимированных box-shadow: свет — слой radial-gradient
   (дешёвые Android, CONCEPT §8). */
/* ⟨ДОБИВКА РАУНДА 2⟩ КАДР ВЫХОДИТ К КРАЯМ КАРТОЧКИ: поле по бокам отдано созвездию
   (margin −10px вместо −2px, padding 2px вместо 6px). Это +24 CSS-px ширины кадра на
   390-м экране, то есть +8% к величине КАЖДОЙ фигуры — самая дешёвая часть ответа на
   «звёзды мелкие, признак не разглядеть». Ничего не обрезается: SVG стоит по центру и
   держит max-width по своей собственной ширине (--fig-w). */
.rit-fig{
  position:relative; margin:12px -10px 10px; padding:10px 2px 2px;
}
/* Кадр срезан по самой фигуре (§1.7 после добивки), его ширина приезжает переменной
   --fig-w: вертикальные созвездия (Персей, Орион, Волопас) больше не тонут в пустом
   небе на всю ширину панели, а стоят по центру в своей ширине. Величина созвездия на
   экране от этого не меняется — исчезает только пустота. */
/* ⟨ДОБИВКА РАУНДА 3⟩ ПРЕДОХРАНИТЕЛЬ ПО ВЫСОТЕ. Потолок кадра в §1.7 считается от ШИРИНЫ
   (0.92w у вертикальных фигур) — на 390×844 это 36% экрана, а на коротком 360×640 те же
   329 px превращаются в половину экрана. Панель не имеет права занять пол-экрана ни на
   одном телефоне, поэтому здесь стоит второй потолок — от ВЫСОТЫ окна. Он ничего не
   обрезает и не ломает пропорций: viewBox и preserveAspectRatio="xMidYMid meet" сами
   вписывают рисунок в оставшуюся высоту и ставят его по центру. На 844 предохранитель
   не срабатывает вовсе (46vh = 388 px при самом высоком кадре 329). */
.rit-fig-svg{ display:block; width:100%; height:auto; max-width:var(--fig-w, none);
  max-height:46vh; margin:0 auto; position:relative; z-index:2; }

/* ═══════ ФОН ПАНЕЛИ СОЗВЕЗДИЯ (RITUAL_BG.md, правка 4 FIX_RITUAL_4) ═══════
   Основатель: «здесь пустовато выглядит созвездие, добавим фон — свечение,
   звёзды-точки». Язык взят у сцены «Общего неба» (детерминированная пыль + мягкая
   туманность, без единого фильтра) и переписан под другую сцену: там фон живёт за
   парой на фоне приложения, здесь — внутри карточки (--card #221a3d), которая
   заметно светлее, и предмет кадра один.
   ГЛАВНЫЙ ИНВАРИАНТ: светится только то, что принадлежит фигуре. У звёзд и огней есть
   ореол, у фона ореолов нет вовсе — пыль плоские круги, туманность градиент без
   границы. Обёртка стоит СНАРУЖИ svg (дыхание собранной фигуры анимирует opacity
   всего svg — награда обязана принадлежать фигуре; и перерисовка по месту трогает
   только содержимое svg, поэтому огонь физически не может задеть фон). */
.rit-fig-sky{ position:relative; }
/* СЛОЙ 1 «КОЛОДЕЦ» + СЛОЙ 2 «ТУМАННОСТИ» — один псевдоэлемент, ноль узлов DOM.
   На светлой карточке любая добавленная светимость делает панель мутной, поэтому
   глубину даёт ЗАТЕМНЕНИЕ к центру: панель становится окном, за которым темнее, чем
   в комнате (композит в центре rgb(19,14,37) — глубже фона приложения #0f0c1d).
   Контраст самой тихой звезды при этом РАСТЁТ: ΔL 0.212 на голой карточке → 0.229.
   Колодец не зависит от дня — он конструкция панели; от дня зависят только
   координаты и оттенок двух туманностей (инлайновые переменные, RITUAL_BG §3). */
.rit-fig-sky::before{
  content:""; position:absolute; inset:0; pointer-events:none; z-index:0;
  background:
    radial-gradient(58% 54% at var(--nb1x,62%) var(--nb1y,26%), var(--nb1c,rgba(207,196,238,.085)) 0%,
                    var(--nb1c0,rgba(207,196,238,0)) 72%),
    radial-gradient(46% 44% at var(--nb2x,36%) var(--nb2y,74%), var(--nb2c,rgba(155,145,196,.055)) 0%,
                    var(--nb2c0,rgba(155,145,196,0)) 74%),
    radial-gradient(64% 56% at 50% 44%, rgba(9,6,20,.58) 0%, rgba(9,6,20,.32) 44%, rgba(9,6,20,0) 94%);
  /* ШВА С КАРТОЧКОЙ НЕТ — И ЭТО НЕ ОБЕЩАНИЕ, А МАСКА ⟨приёмка правки 4⟩. Спека
     считала, что градиенты сами уходят в ноль к краям; замер по живому скриншоту
     показал обратное: у колодца на боковом краю оставалось .34 альфы, а туманность
     дня вообще может стоять центром в 18% от края — на карточке это читалось ПРЯМОЙ
     ЛИНИЕЙ по периметру панели (скачок до 10/255). Подгонять радиусы бессмысленно:
     положение туманности приходит из зерна дня и меняется. Поэтому весь слой гасится
     эллиптической маской, которая обнуляется РОВНО на серединах всех четырёх сторон
     (radius = inset(0) вписанный эллипс) и раньше того — в углах. Фон становится
     мягким «иллюминатором» без единой прямой линии, а числа §2–3 не тронуты: в центре
     маска = 1, композит тот же rgb(19,14,37).
     Маска — уже принятый в проекте инструмент (sky_parts/social.css); движки без
     mask-image просто получают чуть более заметный край, а не сломанную панель. */
  -webkit-mask-image: radial-gradient(50% 46% at 50% 46%, #000 0%, #000 40%, transparent 100%);
          mask-image: radial-gradient(50% 46% at 50% 46%, #000 0%, #000 40%, transparent 100%);
}
/* СЛОЙ 3 «ЗВЁЗДНАЯ ПЫЛЬ» — SVG-оверлей с ТЕМ ЖЕ viewBox и тем же боксом, что у фигуры:
   координаты пыли и координаты созвездия совпадают 1:1 на любой ширине и при
   срабатывании max-height:46vh, поэтому исключающие зоны считаются точно, а не на
   глазок. Пыль тише фигуры вдвое и без ореолов (RITUAL_BG §4.3). */
.rit-fig-dust{
  position:absolute; top:0; left:50%; transform:translateX(-50%);
  width:100%; max-width:var(--fig-w, none); height:100%;
  pointer-events:none; z-index:1;
}

/* ОДНО МЕСТО НА ДВА СОСТОЯНИЯ ⟨FIX_RITUAL_4 · ДОПОЛНЕНИЕ⟩. До третьего огня здесь стоит
   подводка, после — имя созвездия. Высота контейнера задана заранее (две строки подводки
   на узком экране), поэтому награда МЕНЯЕТ ТЕКСТ, а не двигает блок: тот же закон, по
   которому в этом раунде всплывающая пилюля ушла из потока. */
.rit-fig-title{
  margin-top:6px; min-height:calc(20px * var(--font-scale,1));
  display:flex; align-items:center; justify-content:center;
}
/* Имя стоит ОТДЕЛЬНОЙ строкой в именительном падеже — тем же приёмом, которым строка
   неба обошла «Луна в Телец»: склонений нет ни в одной из шести локалей. */
.rit-fig-name{
  text-align:center;
  font-size:calc(16px * var(--font-scale,1)); font-weight:600; line-height:1.25;
  letter-spacing:-.01em; color:#efe9ff;
}
/* ПОДВОДКА ВМЕСТО ИМЕНИ. Она тише имени на две ступени (кегль, вес, цвет подсказки) —
   это не подпись к картинке, а обещание механики, которая тут же и видна: три лунки.
   Курсива и кавычек нет: строка обязана пережить перевод +30% в две строки на 320px. */
.rit-fig-veil{
  text-align:center; max-width:26em;
  font-size:calc(12.5px * var(--font-scale,1)); font-weight:500; line-height:1.3;
  letter-spacing:.01em; color:var(--hint,#9b91c4);
}
/* НАГРАДА ТРЕТЬЕГО ОГНЯ. Имя не «включается», а проявляется — 0.42 с, из полутени,
   без сдвига соседей (движение только внутри собственной строки, transform + opacity).
   Класс вешается ровно в момент подмены текста (figTitleSync) и больше не повторяется. */
.rit-fig-name.reveal{ animation:ritNameIn .42s cubic-bezier(.22,.61,.36,1) both; }
@keyframes ritNameIn{
  from{ opacity:0; transform:translateY(4px) scale(.985); letter-spacing:.04em; }
  to{ opacity:1; transform:none; letter-spacing:-.01em; }
}
/* Причина, по которой фигура именно эта, называется ВСЕГДА: без неё картинка читается
   как декорация, с ней — как факт неба.

   ⟨РАУНД «ГЕЙТ НА ТРИ ОГНЯ» · раунд 2⟩ И ЗДЕСЬ ОДНО МЕСТО НА ДВА СОСТОЯНИЯ. Повод
   согласован с именем: пока имя закрыто — безличная форма («это созвездие высоко над
   тобой»), после третьего огня — родовая («он высоко над тобой»). Безличная длиннее и
   на 320px ложится в ДВЕ строки, родовая — в одну, поэтому ровно на кульминации
   ритуала панель укорачивалась на строку (ru 241→226, es 330→314) и всё под ней
   подпрыгивало. Тот же закон, что у .rit-fig-title парой правил выше: награда МЕНЯЕТ
   ТЕКСТ, а не двигает вёрстку.
   Резерв не задан числом: обе формы стоят в ОДНОЙ клетке грида — видимая узлом
   .rit-fig-why-t, безличная невидимым дублем из data-ghost. Высота клетки = максимум
   из двух, то есть высота безличной формы, и это верно на любой ширине, в каждой из
   шести локалей и при любом --font-scale; там, где обе формы в одну строку (360/390),
   резерв ровно в одну строку и никакой пустоты не даёт. Дубль не кликается, не
   выделяется и в текст экрана не попадает (содержимое псевдоэлемента), а прошлый день
   его вовсе не печатает: там состояние одно. */
.rit-fig-why{
  margin-top:3px; text-align:center;
  display:grid; grid-template-columns:minmax(0,1fr);
  font-size:calc(11.5px * var(--font-scale,1)); line-height:1.35; letter-spacing:.02em;
  color:var(--hint,#9b91c4);
}
.rit-fig-why > .rit-fig-why-t{ grid-area:1 / 1; min-width:0; }
.rit-fig-why[data-ghost]::before{
  content:attr(data-ghost); grid-area:1 / 1; min-width:0;
  visibility:hidden; pointer-events:none; -webkit-user-select:none; user-select:none;
}
/* ЗНАК ≠ СОЗВЕЗДИЕ — одна строка сноски и ровно в тот день, когда они разошлись (а это
   почти каждый день: ~24° прецессии). Стоит НИЖЕ причины и ещё тише её: причина — про
   сегодняшнее небо, эта строка — про устройство неба вообще, и перебивать первую она
   не имеет права. Ширина ограничена, чтобы две строки не растянулись на весь кадр. */
.rit-fig-prec{
  margin:4px auto 0; max-width:30em; text-align:center;
  font-size:calc(10.5px * var(--font-scale,1)); line-height:1.4; letter-spacing:.01em;
  color:var(--hint,#9b91c4); opacity:.72;
}

/* ЛУНКА — место ритуальной звезды в ЦЕЛОЙ фигуре ⟨FIX_RITUAL_3⟩. Деликатный пунктир,
   тот же язык, что в «Общем небе»: место названо, но ничего не обещано. Рёбра к лунке
   нарисованы обычным тихим контуром — силуэт целый с первого кадра, дыр в нём нет, и
   узнавать созвездие человеку приходится не по обломкам, а по самой фигуре.
   Прежнее правило «.rit-fig-edge.cut» (пунктирное ребро к вырезанной звезде) снято
   вместе с конструкцией выреза: вырезать больше нечего. */
.rit-fig-socket{ opacity:.9; }
/* ⟨ДОБИВКА РАУНДА 4⟩ РЕБРО ПРИЗНАКА — ГЛАВНЫЙ ГОЛОС РИСУНКА. Цвет и толщина стоят
   атрибутами в самом SVG (forecast_ritual.js: FIG_EDGE_SIGN .64/1.5 против фона
   .32/1.0) — так их видит и первая отрисовка, и дорисовка по месту, и шторка атласа,
   у которых один рисовальщик. Здесь только то, чего атрибутом не сказать: у линии
   признака чуть мягче торцы, чтобы утолщение не читалось «жирной палкой».
   Зачем вообще: приёмка раунда 4 не опознала вслепую десять фигур из двадцати, и во
   всех десяти глаз вёл длинное ребро, к признаку отношения не имеющее (рог Тельца в
   7 раз длиннее V Гиад). Звёзды при этом не тронуты ничем — их величины настоящие;
   линии же рисуем мы, и главной обязана быть та, по которой созвездие называют. */
.rit-fig-edge.sg{ stroke-linejoin:round; }
/* ДЫХАНИЕ СОБРАННОЙ ФИГУРЫ — единственная бесконечная анимация блока (F3_SPEC §4.4).
   Дыхание, а не мигание: 6 с, ход опаковости всего .93 → 1, без масштабов и теней.
   Появляется РОВНО тогда, когда горят все три звезды выреза, — это единственное
   место, где движение в блоке заслужено. */
.rit-fig.done .rit-fig-svg{ animation:ritFigBreath 6s ease-in-out infinite; }
@keyframes ritFigBreath{ 0%,100%{ opacity:.93; } 50%{ opacity:1; } }
/* Зажжённая звезда и пришедшее с ней ребро ВХОДЯТ, а не появляются рывком: 400 мс на
   звезду, 350 мс на линию — та же длительность, что у огня в карточке шага. */
.rit-fig-star.new{ animation:ritStarIn .4s ease forwards; }
@keyframes ritStarIn{ from{ opacity:0; transform:scale(.6); } to{ opacity:1; transform:none; } }
.rit-fig-star{ transform-box:fill-box; transform-origin:center; }
/* ⟨FIX_RITUAL_3⟩ РЕБРО НЕ РИСУЕТСЯ ЗАНОВО — ОНО РАЗГОРАЕТСЯ. Прежняя анимация
   сматывала линию в ноль (stroke-dashoffset 420) и прочерчивала её заново: под старой
   конструкцией это было честно — ребра к вырезанной звезде на экране действительно не
   было. Теперь фигура нарисована ЦЕЛИКОМ и всегда, и та же анимация на 350 мс
   ПРОДЕЛЫВАЛА БЫ В СИЛУЭТЕ ДЫРУ ровно там, где мы её только что закрыли. Поэтому
   зажигание ведёт ребро по свету: линия стоит на месте и разгорается из тихой в
   цветную. Ни один кадр перехода не оставляет силуэт неполным. */
.rit-fig-edge.new{ animation:ritEdgeIn .35s ease .06s both; }
@keyframes ritEdgeIn{ from{ opacity:.5; } to{ opacity:1; } }
/* ТРЕТЬЯ ЗАМЫКАЕТ (§3.2). Рёбра ПОСЛЕДНЕГО огня дорисовываются вдвое медленнее
   остальных — 700 мс против 350. Это единственный акцент, которым «третий огонь
   замыкает рисунок» читается глазом: до него все три такта выглядели одинаково. */
.rit-fig-edge.new.last{ animation-duration:.7s; }
/* УХОД — ТОТ ЖЕ ПУТЬ НАЗАД, И ТОЛЬКО У УХОДЯЩЕЙ ЗВЕЗДЫ. Гашение огня анимирует
   ровно ту звезду, которую погасили; всё остальное на экране не шевелится (раньше
   перерисовывался весь SVG, и оставшиеся звёзды проигрывали анимацию ЗАЖИГАНИЯ в
   момент погасания).
   ⟨FIX_RITUAL_3⟩ Уходит ТОЛЬКО звезда: её рёбра остаются нарисованными и просто
   теряют цвет тем же тактом. Смотать линию с экрана значило бы проделать в силуэте
   дыру — ровно то, ради чего конструкция и менялась. */
.rit-fig-star.out{ animation:ritStarOut .3s ease forwards; }
@keyframes ritStarOut{ from{ opacity:1; transform:none; } to{ opacity:0; transform:scale(.6); } }

/* ─────────── «Поделиться»: всегда бесплатно, ни в одной ветке нет премиума ─────────── */
.rit-done{ display:flex; gap:9px; margin-top:12px; }
.rit-done .btn{ flex:1; margin:0; }

/* ─────────── НИТЬ: тихая история, а не серия ─────────── */
/* Ни цифр «подряд», ни предупреждений, ни красного слома. Пропущенный день —
   просто тусклая точка, и никакой реакции продукта на это нет. */
.rit-thread-host{ margin-top:14px; }
.rit-thread7{ cursor:pointer; }
.rt-k{ display:flex; justify-content:space-between; align-items:baseline; gap:10px; }
.rt-cap{
  font-size:10px; font-weight:700; letter-spacing:.16em; text-transform:uppercase;
  color:var(--hint,#9b91c4);
}
.rt-n{ font-size:calc(11.5px * var(--font-scale,1)); color:var(--hint,#9b91c4); }
/* сетка-колонки вместо фиксированных 9px: подписи дней в es/pt/fr шире точки,
   и на фиксированной ширине они наезжали бы друг на друга */
.rt-dots,.rt-days{ display:grid; grid-auto-flow:column; grid-auto-columns:1fr; align-items:center; }
.rt-dots{ margin-top:10px; }
.rt-dots i{
  width:9px; height:9px; border-radius:50%; display:block; position:relative; margin:0 auto;
  background:var(--accent,#b388ff);
}
/* ТОЧКА СЕГОДНЯШНЕГО ДНЯ НАЛИВАЕТСЯ, А НЕ ПЕРЕЩЁЛКИВАЕТСЯ (CONCEPT §8: «наливается
   яркостью, 500 мс»). Переход висит только на сегодняшней точке: у прошедших дней
   яркость не меняется никогда, и анимировать там нечего. */
.rt-dots i.today{ transition: opacity .5s ease; }
@media (prefers-reduced-motion: reduce){ .rt-dots i.today{ transition:none; } }
.rt-dots i.today::after{
  content:""; position:absolute; inset:-6px; border-radius:50%;
  background:radial-gradient(circle, var(--accent,#b388ff) 0%, rgba(0,0,0,0) 68%);
  opacity:calc(.6 * var(--rit-glow,1));
}
.rt-days{ margin-top:7px; }
.rt-days span{ font-size:calc(10.5px * var(--font-scale,1)); color:var(--hint,#9b91c4); text-align:center; }
/* РАЗВЁРНУТАЯ НИТЬ (премиум, до 30 дней). Та же нить, а не другой экран: колонок больше,
   точка мельче, а вместо тридцати букв недели — подпись-диапазон «первый день … сегодня»
   (тридцать подписей на 360px физически не помещаются). Цифр «подряд» и серий тут
   по-прежнему нет: пропущенный день — просто тусклая точка. */
.rit-thread7.long .rt-dots i{ width:6px; height:6px; }
.rit-thread7.long .rt-dots i.today::after{ inset:-5px; }
.rit-thread7.long .rt-days{ display:flex; justify-content:space-between; }
.rit-thread7.long .rt-days span{ text-align:left; }
.rit-thread7.long .rt-days span:last-child{ text-align:right; }
/* ✦-замок нити живёт ВНУТРИ нити, а не отдельной строкой в стопке */
.rt-lock{
  display:inline-flex; align-items:center; gap:6px; margin-top:11px; padding:0;
  background:none; border:0; font-family:inherit; cursor:pointer;
  font-size:calc(11.5px * var(--font-scale,1)); font-weight:600; color:var(--gold,#ffcf70);
}
.rit-astra{ color:var(--gold,#ffcf70); }

/* ─────────── пульс кольца сферы в ответ на тап по шагу ─────────── */
/* Дешёвая деталь, физически связывающая ритуал с кольцами этажом выше (CONCEPT §6.3).
   Только transform — ни box-shadow, ни filter.
   ДВА ИМЕНИ КЛАССА НАМЕРЕННО: .rit-pulse вешает ritRingPulse() из app.js (сторона B),
   .rit-ring-pulse — резервная реализация в forecast_ritual.js, которая включается,
   только если функции B на странице нет. Правило одно, чтобы пульс не зависел от
   того, чья ветка отработала. */
.rings .ring-item.rit-pulse .ring-wrap,
.rings .ring-item.rit-ring-pulse .ring-wrap{ animation:ritRingPulse .4s ease; }
@keyframes ritRingPulse{ 0%{ transform:scale(1); } 45%{ transform:scale(1.06); } 100%{ transform:scale(1); } }

/* ─────────── 360×640: самый узкий обязательный экран ─────────── */
@media (max-width:370px){
  /* Кадр фигуры НЕ ужимается по высоте руками: она следует из пропорций настоящей
     фигуры (viewBox), и «подрежем 20px» здесь означало бы сплющить созвездие.
     Ужимаются только поля и подписи. */
  .rit-fig{ padding:8px 2px 0; margin:10px -2px 2px; }
  .rit-fig-name{ font-size:calc(15px * var(--font-scale,1)); }
  /* Подводка на 360 живёт в две строки — контейнер её и держит, чтобы приход имени
     не поднимал карточки шагов на десяток пикселей. */
  .rit-fig-veil{ font-size:calc(12px * var(--font-scale,1)); }
  .rit-fig-title{ min-height:calc(19px * var(--font-scale,1)); }
  .rit-track{ gap:6px; }
  .rt-dots{ margin-top:9px; }
}

/* ─────────── REDUCED MOTION: всё в финальные кадры, ничего не пропадает ─────────── */
@media (prefers-reduced-motion: reduce){
  /* специфичность зеркалит живое правило (.rit.rit-seen …): гейт «блок увидели»
     не имеет права перебить выключение движения */
  .rit.rit-seen .rit-track.empty i:first-child,
  .rit-track.empty i:first-child,
  .rit-echo,
  .rings .ring-item.rit-pulse .ring-wrap,
  .rings .ring-item.rit-ring-pulse .ring-wrap{ animation:none; }
  /* ⟨ПРАВКА 8⟩ Пилюля отклика ПОЯВЛЯЕТСЯ, но не движется: ни всплытия, ни масштаба —
     сразу конечный кадр. Ничего не пропадает, авто-уход остаётся (его ведёт таймер JS,
     а не анимация). */
  .rit-echo{ transition:none; transform:none; }
  .rit-track i{ transition:none; }
  /* Зажжённые звёзды и их рёбра — СРАЗУ В КОНЕЧНОМ СОСТОЯНИИ. Ничего не пропадает:
     собранная фигура остаётся собранной, просто без входа. Дыхание выключено. */
  .rit-fig-star.new{ opacity:1; transform:none; animation:none; }
  .rit-fig-edge.new{ animation:none; opacity:1; }
  /* Уход — тоже без движения: звезда не «уползает», она просто уступает место лунке
     (сама подмена происходит по таймеру и от анимации не зависит). */
  .rit-fig-star.out{ animation:none; opacity:1; transform:none; }
  /* Дыхание собранной фигуры выключено (§3.2) — фигура остаётся собранной и целиком
     видимой, просто перестаёт дышать. */
  .rit-fig.done .rit-fig-svg{ animation:none; opacity:1; }
  /* Имя ПОЯВЛЯЕТСЯ, но не движется: награда никуда не девается, уходит только вход. */
  .rit-fig-name.reveal{ animation:none; opacity:1; transform:none; letter-spacing:-.01em; }
  /* ФОН ПАНЕЛИ (RITUAL_BG §8). Выключать нечего — у него нет ни анимаций, ни
     переходов, — но замок ставится тем же законом, что в scene.css: любое будущее
     движение в фоне заводится ТЕМ ЖЕ коммитом, что и эта строка. getAnimations() на
     .rit-fig-sky и .rit-fig-dust обязан быть пуст ВСЕГДА, в обоих режимах motion. */
  .rit-fig-sky, .rit-fig-sky::before,
  .rit-fig-dust, .rit-fig-dust circle{ animation:none; transition:none; }
}
/* ═══════════════ F3 · «РИТУАЛ ДНЯ» — CSS ИНЖЕНЕРА C · КОНЕЦ ═══════════════ */

/* ═══════════ F3 · КОЛЛЕКЦИЯ СОЗВЕЗДИЙ «Твоё небо» (инженер A · §4.4–4.5) ═══════════
   Тихая строка под нитью и шторка-дневник. Ни прогресс-бара, ни знаменателя, ни
   пустых слотов: в разметке физически нечему показывать то, чего у человека нет. */
.rit-atlas{
  display:flex; align-items:center; gap:8px;
  margin:10px 0 2px; padding:9px 12px;
  border-radius:12px; cursor:pointer;
  background:rgba(255,255,255,.028);
  border:1px solid rgba(255,255,255,.055);
  -webkit-tap-highlight-color:transparent;
  transition:background .18s ease, border-color .18s ease;
}
.rit-atlas:active{ background:rgba(255,255,255,.05); }
.rit-atlas:focus-visible{ outline:2px solid rgba(207,196,238,.55); outline-offset:2px; }
.rit-atlas .ra-ic{ font-size:12px; color:#cfc4ee; opacity:.85; line-height:1; }
.rit-atlas .ra-k{ font-size:13px; font-weight:600; letter-spacing:.01em; color:var(--fg,#e8e6f2); }
/* Число — это КОЛИЧЕСТВО СОБРАННОГО, а не «сколько из скольких»: знаменателя нет нигде. */
.rit-atlas .ra-n{ margin-left:auto; font-size:13px; font-weight:600; color:#cfc4ee; opacity:.9; font-variant-numeric:tabular-nums; }

.ra-grid{ display:flex; flex-direction:column; gap:2px; margin:6px 0 14px; }
.ra-card{ display:flex; align-items:center; gap:12px; padding:8px 2px; }
.ra-card + .ra-card{ border-top:1px solid rgba(255,255,255,.05); }
/* ⟨раунд 2 фикс-цикла⟩ КЛЕТКА РИСУНКА 96×96, КАК И ОБЪЯВЛЕНО В §4.4 (было 76). На 76 px
   тихий контур собранной фигуры (opacity .30–.62, радиусы 2.1–2.7 ед. кадра — меньше
   пикселя на экране) исчезал под ореолами трёх зажжённых звёзд: карточка собранного дня
   читалась как «три яркие точки и две искры», а не как целый силуэт. По новой конструкции
   силуэт обязан читаться и в дневнике коллекции тоже. */
.ra-fig{ flex:0 0 96px; width:96px; height:96px; opacity:.75; }
.ra-card.done .ra-fig{ opacity:1; }
.ra-fig svg{ display:block; width:100%; height:100%; }
/* Строка без картинки: день встречен, а нарисовать его нечем (вырез того дня ссылается
   на звезду, снятую из каталога; прошлое не переписывается — §3.4). Пустой рамки не
   рисуем вовсе, текст встаёт на её место — обещания без содержания не остаётся. */
.ra-card.nofig{ padding-left:4px; }
.ra-meta{ min-width:0; }
.ra-nm{ font-size:14.5px; font-weight:600; line-height:1.25; color:var(--fg,#e8e6f2); }
.ra-card:not(.done) .ra-nm{ opacity:.72; }
.ra-dt{ margin-top:2px; font-size:11.5px; line-height:1.3; opacity:.5; }
.ra-part{ opacity:.85; }               /* «осталось неполным» — память, а не долг */
.ra-empty{ padding:14px 2px; font-size:13px; line-height:1.5; opacity:.6; }
.ra-note{ padding-top:10px; border-top:1px solid rgba(255,255,255,.06);
          font-size:11.5px; line-height:1.5; opacity:.45; }
@media (prefers-reduced-motion: reduce){
  .rit-atlas{ transition:none; }
}
/* ═══════════ F3 · КОЛЛЕКЦИЯ СОЗВЕЗДИЙ · КОНЕЦ ═══════════ */

/* ═══════════ iOS-НАТИВ · T2 «Web-мост» · НАЧАЛО ═══════════
   Все селекторы ниже принадлежат узлам, которые РОЖДАЮТСЯ ТОЛЬКО в iOS-режиме
   (за гейтом IOSH.on() в ios.js/app.js). В Telegram и вебе таких узлов в DOM нет
   ни одного, поэтому блок физически не может изменить ни один существующий экран —
   это и есть его вклад в железное правило «вне iOS ничего не меняется». */

/* Плашка офлайна над лентой Прогноза. Не тревога, а факт: приглушённый янтарь,
   без иконки-восклицания — данные честные, просто вчерашние. */
.ios-offline-bar{
  margin:0 0 10px; padding:9px 12px; border-radius:12px;
  background:rgba(244,200,105,.10); border:1px solid rgba(244,200,105,.24);
  color:#F4C869; font-size:12.5px; line-height:1.4; text-align:center;
}
/* «Восстановить покупки» под печатью-CTA пейвола: тише CTA на порядок — это
   служебный путь, а не второе предложение купить. */
.pw-restore{ margin-top:10px; font-size:13.5px; opacity:.75; }
/* Просвет под последней кнопкой экрана — РЕАЛЬНЫМ узлом, а не margin-bottom: у
   последнего ребёнка нижний margin схлопывается наружу через .pw2, и «Восстановить
   покупки» на полном скролле оставалась под fixed таб-баром (замерено: bottom 821 при
   верхе бара 800). Высота — та же мера, что у липкой печати-CTA: реальная высота бара
   живёт в --pw-tabbar-h (её ставит renderPaywall), фолбэк покрывает кадр до замера. */
.pw-restore-pad{ height:calc(var(--pw-tabbar-h, 54px) + 16px); }
/* В приложении #screen уже отступает на высоту таббара + safe-area (calc(90px + --sab)) —
   этот запас и нижний паддинг .pw2 складывались с ним в ~230pt пустоты под «Terms · Privacy»
   при полной прокрутке (основатель 2026-10-12). Оставляем один отступ — у #screen. */
html.native-app .pw-restore-pad{ height:0; }
html.native-app .pw2, html.native-app .pw2-screen{ padding-bottom:8px; }
/* Состояние «цены недоступны»: тот же вертикальный ритм, что у лестницы планов. */
.pw-iap-fail{ margin-top:14px; text-align:center; }
.pw-iap-fail .btn{ margin-top:12px; }
.ios-restore-card .btn{ margin-top:10px; }
/* Шторка пре-промпта пушей переиспользует геометрию .ios-soon (тот же шит,
   тот же ритм печати) — своя только вторая, «тихая» кнопка. */
.ios-push .btn + .btn{ margin-top:8px; }
/* ═══════════ iOS-НАТИВ · T2 «Web-мост» · КОНЕЦ ═══════════ */

/* ═══════════ «СФЕРЫ ДНЯ 2.0» · шторка глубины (openSphereDetail) ═══════════
   Живёт в штатной .sheet (тёмный космос, скролл внутри, крестик/фон закрывают).
   Палитра --sph/--sph-hi приезжает с корня .sph-sheet[data-sphere] (см. блок
   .aspect-row выше — источник один). Специфичность держим на одиночных .sph-*
   классах, чтобы не бороться с .sheet h2 и .hint. */
.sph-sheet{ padding-top:2px; }
.sph-head{ display:flex; align-items:baseline; justify-content:space-between; gap:12px; margin:2px 0 6px;
  padding-right:44px; /* крестик шторки (.sheet-x, 36px @ right:10px) — процент не должен под него подлезать */ }
/* заголовок слева, не по центру: рядом стоит процент (перебиваем .sheet h2 text-align) */
.sph-sheet .sph-head h2{ margin:0; text-align:left; font-size:20px; }
.sph-pct{ font-weight:800; font-size:20px; color:var(--sph-hi,#efe6ff); flex:none;
  text-shadow:0 0 14px var(--sph-lit, rgba(179,136,255,.14)); }
.sph-pct i{ font-style:normal; font-size:13px; opacity:.7; margin-left:1px; }
.sph-bar{ margin-bottom:12px; }
.sph-p{ margin:10px 0; font-size: calc(14.5px * var(--font-scale, 1)); line-height:1.5; }
/* «стоит сделать»: карточка в тоне приложения, маркер ✦ */
.sph-do{ margin:14px 0 0; padding:12px 14px; background:var(--card); border:1px solid var(--line);
  border-radius:14px; }
.sph-do-h{ font-size:12.5px; text-transform:uppercase; letter-spacing:.06em; opacity:.9; }
.sph-do-list{ list-style:none; margin:8px 0 0; padding:0; }
.sph-do-list li{ position:relative; padding-left:22px; margin:8px 0;
  font-size: calc(14px * var(--font-scale, 1)); line-height:1.45; }
.sph-do-list li::before{ content:"✦"; position:absolute; left:2px; top:0;
  color:var(--sph,var(--accent)); font-size:12px; }
/* матричный этаж: отбит линейкой, титул-«бровь», самоцвет с числом аркана */
/* Матричная СНОСКА (не этаж): продолжение разбора в акценте сферы (--sph задаёт
   .sph-sheet[data-sphere]); капс/курсив/рамка сняты 16.08 по решению основателя. */
.sph-mx2{ margin:14px 0 0; padding-top:12px; border-top:1px solid var(--line);
  font-size:calc(13.5px * var(--font-scale,1)); line-height:1.55; color:var(--tx-soft,#c9c2dd); }
.sph-mx2-mark{ color:var(--sph); margin-right:2px; }
.sph-mx2-arc{ color:var(--sph-hi); font-weight:650; }
.sph-mx2 .sph-mx-open{ display:inline; cursor:pointer; white-space:nowrap; margin-left:6px; }

/* ── Тизер шторки сферы для бесплатного (гейт глубины, решение основателя 2026-08-16) ──
   Язык — превью запертых глав транзитов (.tf-teaser, 1c-3): НАСТОЯЩЕЕ начало первого
   абзаца тает в вуаль mask-image (фон шторки — градиент, поэтому solid-fade-див как у
   .tf-teaser-fade не годится: маска честно пропускает любой фон). Ниже — премиум-якорь
   «Астры»: печать pg--seal (дыхание pg-breathe штатное, reduced-motion гасит его в
   общем правиле .pg — styles.css, «деградация К ПОЛНОЙ ЯРКОСТИ») + common.premium_locked
   и золотой CTA (.tf-teaser-cta переиспользован). Точек-заглушек тут НЕТ сознательно —
   redacted-язык остаётся замкам строк family/finance. */
.sph-veil{ position:relative; margin-top:2px; }
.sph-veil-body{ margin:10px 0 0; max-height:3.1em; overflow:hidden; opacity:.92;
  -webkit-mask-image:linear-gradient(180deg,#000 0%,rgba(0,0,0,.7) 42%,transparent 94%);
  mask-image:linear-gradient(180deg,#000 0%,rgba(0,0,0,.7) 42%,transparent 94%); }
.sph-prem{ display:flex; flex-direction:column; align-items:center; gap:7px;
  margin:4px 0 14px; text-align:center; }
.sph-prem-lbl{ font-size:13px; font-weight:650; letter-spacing:.02em; color:var(--gold,#ffd98a); }
.sph-teaser .sph-teaser-cta{ margin-top:0; }

/* ═══════════ Справка «Натальная карта» (openWheelHelp) ═══════════
   Шторка по тапу в пустую зону натального колеса (docs/forecast_spheres/WHEEL_HELP.md).
   Живёт в штатной .sheet (тёмный космос, крестик/фон закрывают); декоративный акцент —
   мини-«орбита» с ✦ и двумя планетами-точками, чистый CSS без ассетов. */
.whlp{ padding-top:4px; }
.whlp-orb{ position:relative; width:58px; height:58px; margin:2px auto 12px; border-radius:50%;
  border:1px solid var(--line); display:grid; place-items:center;
  color:var(--gold,#ffd98a); font-size:18px; line-height:1;
  background:radial-gradient(70% 70% at 50% 35%, rgba(179,136,255,.16), rgba(15,12,29,0) 72%);
  box-shadow:0 0 22px -8px rgba(179,136,255,.45), inset 0 0 12px rgba(179,136,255,.10);
  text-shadow:0 0 12px rgba(255,217,138,.55); }
.whlp-dot{ position:absolute; width:5px; height:5px; border-radius:50%;
  background:var(--accent,#b388ff); box-shadow:0 0 8px rgba(179,136,255,.85); }
.whlp-dot.d1{ top:3px; left:11px; }
.whlp-dot.d2{ bottom:6px; right:2px; width:4px; height:4px; opacity:.8; }
.whlp .whlp-p{ margin:10px 0; font-size:calc(14.5px * var(--font-scale,1)); line-height:1.55; }
.whlp-cta{ margin-top:16px; }

/* ═══ «Избранное» на Прогнозе (основатель 2026-08-19): чипы-прыжки к закреплённым
   разделам (до 3). Пусто/флаг выключен → fcFavsHtml вернул "" и блока нет. Цвет
   чипа — токен линии через data-line (те же значения, что у [data-line]). ═══ */
.fc-favs-row{ display:flex; gap:8px; flex-wrap:wrap; margin:2px 0 10px; }
.fc-fav{ display:inline-flex; align-items:center; gap:6px; border:0; cursor:pointer;
  font-size:12.5px; font-weight:700; color:var(--text); padding:7px 12px; border-radius:16px;
  background:var(--bg2); border:1px solid var(--line); font-family:inherit; }
.fc-fav .fc-fav-star{ color:var(--gold); font-size:12px; }
.fc-fav .fc-fav-line{ color:var(--dim); font-weight:600; }
.fc-fav[data-line="romance"]{ box-shadow:inset 0 0 0 1px rgba(255,126,182,.28); }
.fc-fav[data-line="friendship"]{ box-shadow:inset 0 0 0 1px rgba(91,227,167,.26); }
.fc-fav[data-line="family"]{ box-shadow:inset 0 0 0 1px rgba(255,209,102,.26); }
/* заглушка избранного: та же форма пилюли, пунктир «здесь может быть кто-то» */
.fc-fav-ghost{ border:1px dashed rgba(255,255,255,.22); background:rgba(255,255,255,.03);
  color:var(--dim); font-weight:600; }
.fc-fav-ghost .fc-fav-star{ color:rgba(255,217,138,.5); }
.fc-favs-row{ margin:10px 0; }
/* избранное: горизонтальный слайдер (основатель 19.08 — «когда пар много, листать»),
   значок линии в её цвете, имя — обычным текстом; скроллбар спрятан */
.fc-favs-row{ flex-wrap:nowrap; overflow-x:auto; -webkit-overflow-scrolling:touch;
  scrollbar-width:none; padding-bottom:2px; }
.fc-favs-row::-webkit-scrollbar{ display:none; }
.fc-fav{ flex:0 0 auto; }
.fc-fav .fc-fav-ic{ font-size:12px; }
.fc-fav[data-line="romance"] .fc-fav-ic{ color:#ff7eb6; }
.fc-fav[data-line="friendship"] .fc-fav-ic{ color:#5be3a7; }
.fc-fav[data-line="family"] .fc-fav-ic{ color:#ffd166; }
/* рубрика блока избранного: «Совместимость дня» (выбор основателя 19.08) */
.fc-favs-blk{ margin:12px 0 10px; }
.fc-favs-h{ font-size:11px; letter-spacing:2px; font-weight:800; text-transform:uppercase;
  color:var(--dim); margin:0 2px 8px; }
.fc-favs-blk .fc-favs-row{ margin:0; }
/* заглушка — НЕ чип слайдера: занимает всю ширину и переносится на несколько строк,
   чтобы стартовая фраза была видна целиком (основатель 19.08) */
.fc-fav-ghost{ flex:1 1 100%; white-space:normal; text-align:left;
  line-height:1.45; padding:10px 14px; align-items:flex-start; }
.fc-fav-ghost .fc-fav-star{ margin-top:1px; }
/* значки линий — SVG: выравнивание по тексту чипа */
.fc-fav .fc-fav-ic{ display:inline-flex; align-items:center; }
.fc-fav .fc-fav-ic svg{ display:block; }

/* ═══ Публичный лендинг (браузер без Telegram; его видит и ревью App Store) ═══ */
.landing{ max-width:520px; margin:0 auto; padding:8vh 22px 40px; }
.ld-logo{ font-size:13px; letter-spacing:3px; color:var(--gold); font-weight:800; text-transform:uppercase; margin-bottom:18px; }
.ld-hero h1{ font-size:26px; font-weight:800; line-height:1.25; margin-bottom:12px; }
.ld-sub{ font-size:14.5px; line-height:1.55; color:var(--dim); margin-bottom:20px; }
.ld-cta{ width:100%; }
.ld-feats{ margin:26px 0 8px; display:flex; flex-direction:column; gap:10px; }
.ld-feat{ font-size:14px; line-height:1.45; color:#d9d2ec; }
.ld-price{ margin-top:26px; background:var(--bg2); border:1px solid var(--line); border-radius:18px; padding:16px; }
.ld-price h2{ font-size:16px; font-weight:800; margin-bottom:6px; }
.ld-free{ font-size:12.5px; color:var(--dim); margin-bottom:12px; line-height:1.5; }
.ld-row{ display:flex; justify-content:space-between; align-items:baseline; gap:10px; padding:9px 0; border-top:1px solid var(--line); font-size:13.5px; }
.ld-row .ld-n{ font-weight:700; }
.ld-row .ld-p{ color:#d9d2ec; text-align:right; }
.ld-row .ld-p i{ display:block; font-style:normal; font-size:11px; color:var(--dim); }
.ld-note{ margin-top:12px; font-size:11.5px; color:var(--dim); line-height:1.5; }
.ld-foot{ margin-top:24px; font-size:12.5px; color:var(--dim); display:flex; gap:8px; flex-wrap:wrap; align-items:center; }
.ld-foot a{ color:var(--accent); text-decoration:none; }
.ld-mail{ margin-left:auto; }
/* A1 (план аналитики 2026-09-10): экран возврата после карточной оплаты — тот же лендинг-каркас,
   но по центру и без прайса. Прайс после оплаты — ровно то, что мы чиним. */
.pay-return{ padding:14vh 22px 40px; text-align:center; }
.pay-return .ld-hero .sign-emoji{ font-size:42px; line-height:1; margin:6px 0 14px; }
.pay-return .ld-cta{ margin-top:6px; }
.pay-return .pr-note{ margin-top:14px; }
.pay-return .ld-foot{ justify-content:center; }
.pay-return .ld-mail{ margin-left:0; width:100%; }

/* Аккаунт: обязательные пункты в одной раскрывашке (основатель 2026-10-12) */
.acc-priv{ margin:14px 0 6px; border:1px solid rgba(255,255,255,.08); border-radius:16px; background:rgba(255,255,255,.025); }
.acc-priv > summary{ list-style:none; cursor:pointer; padding:14px 16px; font-size:14.5px; font-weight:600;
  color:var(--muted, #a99fc7); display:flex; align-items:center; justify-content:space-between; gap:10px; }
.acc-priv > summary::-webkit-details-marker{ display:none; }
.acc-priv > summary::after{ content:"⌄"; font-size:18px; line-height:1; transition:transform .2s ease; }
.acc-priv[open] > summary::after{ transform:rotate(180deg); }
.acc-priv > summary:focus-visible{ outline:2px solid var(--accent, #b88cff); outline-offset:2px; border-radius:16px; }
.acc-priv-body{ padding:0 10px 10px; }
.acc-priv-body > .card{ margin:8px 0 0; }
.acc-priv-body a{ color:#c9b3ff; text-decoration:underline; text-underline-offset:2px; }
