/* Part of Survival Language — see index.html for load order.
   All colors live in tokens.css; this and the other files below only use
   var(--...) references, never raw hex, so a purchased theme (js/store.js
   applyThemeSkin) or dark mode recolors everything without touching CSS. */

  /* ---- Hero / month grid ---- */
  /* Spacing between hero/alphabet-card/month-grid/facts-card used to come from a mix
     of this element's own bottom padding and the NEXT element's top margin, and the
     two didn't add up to the same total on every transition — the gap around the
     Alphabet card in particular ended up noticeably bigger above it than below it.
     Now every block below the hero owns its OWN top margin only (16px, see
     .facts-entry-card and .month-grid below) and .hero contributes nothing on its
     own bottom edge, so the gap is the same 16px whichever block happens to follow. */
  /* A parent's note to their child, on the child's own home screen (js/store.js
     fetchFamilyInfo, screens.home.js loadParentNoteBanner) — gold like .trick-note
     (lesson.css) since both are "someone left you a helpful aside" callouts, but a
     real box rather than a quiet left-rule: unlike .teach-meaning's translation,
     this is new information the learner hasn't seen yet, worth a beat of attention. */
  .parent-note-card{
    border:1.5px solid var(--gold); border-radius:var(--radius-md);
    background:var(--gold-soft); padding:var(--space-4); margin-top:var(--space-4);
  }
  .parent-note-eyebrow{ display:block; font-size:11px; font-weight:800; text-transform:uppercase; letter-spacing:.04em; color:var(--gold-text); margin-bottom:4px; }
  .parent-note-text{ margin:0; font-size:14.5px; font-weight:600; color:var(--ink); line-height:1.4; }

  .hero{ padding:var(--space-6) 0 0; }
  .hero-card{
    position:relative; overflow:hidden; border-radius:var(--radius-lg); padding:var(--space-6);
    background:linear-gradient(135deg, var(--hero-a), var(--hero-b));
    box-shadow:0 16px 34px -14px color-mix(in srgb, var(--hero-a) 65%, transparent);
  }
  .hero-card::before{
    content:""; position:absolute; width:230px; height:230px; border-radius:50%;
    background:rgba(255,255,255,.10); top:-100px; right:-70px; pointer-events:none;
  }
  /* A very quiet Georgian-character motif — "ა", the first letter of the alphabet
     Sonya is learning, not a flag or ornament — reused on every "hero" surface
     (this card, .trainer-tile-big) as one shared brand mark instead of a different
     graphic per screen. Kept to a whisper (14% opacity) so it reads as texture,
     never as a competing headline next to the real Georgian word on the card. */
  /* Bottom-LEFT, not right — .hero-illust (the mountain graphic, rendered by JS)
     already owns the bottom-right corner; this sits behind the text on the other
     side instead of competing with it. */
  .hero-card::after{
    content:"ა"; position:absolute; left:-24px; bottom:-58px; font-family:'Noto Sans Georgian','Manrope',sans-serif;
    font-size:220px; font-weight:700; line-height:1; color:rgba(255,255,255,.14); pointer-events:none;
  }
  .hero-card .eyebrow{ position:relative; z-index:1; font-size:12.5px; font-weight:700; letter-spacing:.08em; text-transform:uppercase; color:rgba(255,255,255,.85); margin-bottom:var(--space-3); }
  /* max-width:11em (~350px) used to cap this at the mobile card's own natural
     width anyway, so it did nothing there — but on a tablet/desktop-width card,
     where there's actual room to spare, the exact same cap forced the title
     onto 2-3 short lines instead of using the space it had (Sofia). Removed —
     it now wraps only when the card genuinely isn't wide enough for it. */
  .hero-card h1{ position:relative; z-index:1; font-size:32px; font-weight:800; line-height:1.15; letter-spacing:-.01em; color:#fff; }
  /* p.lede is no longer rendered (screens.home.js, Sofia's 10.2 — the hero read
     as a banner ad with a long description and no single action). Rule kept
     harmlessly unused rather than touching the i18n string it pulled from. */
  .hero-card p.lede{ position:relative; z-index:1; margin-top:var(--space-3); font-size:15.5px; line-height:1.55; color:rgba(255,255,255,.85); max-width:26em; }
  /* The replacement: one big number as the actual key metric, with the
     month/day-count context set small beside it instead of spelled out in a
     full sentence below the bar. */
  /* "Today's mission" (Sofia's Home-rhythm pass, ROADMAP.md) — replaces the old
     percent-led .hero-stat-row/.overall-bar pair below, kept harmlessly unused
     rather than deleted since nothing currently renders that markup. */
  .hero-card .hero-mission-sub{ position:relative; z-index:1; margin-top:6px; font-size:13px; font-weight:600; color:rgba(255,255,255,.82); }
  .hero-card .hero-stat-row{ position:relative; z-index:1; margin-top:var(--space-4); display:flex; align-items:center; gap:var(--space-3); }
  .hero-card .hero-stat-num{ font-size:40px; font-weight:800; line-height:1; color:#fff; }
  .hero-card .hero-stat-label{ font-size:12.5px; line-height:1.4; color:rgba(255,255,255,.8); }
  .hero-card .hero-stat-label b{ display:block; font-weight:700; font-size:13.5px; color:#fff; }
  .hero-card .overall-bar{ position:relative; z-index:1; margin-top:var(--space-4); max-width:230px; height:10px; border-radius:5px; background:rgba(255,255,255,.22); border:1.5px solid rgba(255,255,255,.3); overflow:hidden; }
  .hero-card .overall-bar > i{ display:block; height:100%; background:#fff; }
  /* One explicit call to action instead of ending on a caption line — routes
     to the same place tapping the active month card does (screens.home.js). */
  .hero-card .hero-cta{
    position:relative; z-index:1; margin-top:var(--space-4); display:inline-flex; align-items:center; gap:6px;
    background:#fff; color:var(--hero-a); font-family:inherit; font-weight:800; font-size:14px;
    border:none; border-radius:999px; padding:11px 20px; cursor:pointer;
    box-shadow:0 8px 18px -10px rgba(0,0,0,.4); transition:background-color .15s ease;
  }
  .hero-card .hero-cta:hover{ background:rgba(255,255,255,.9); }
  .hero-illust{ position:absolute; right:2px; bottom:0; width:128px; height:auto; z-index:0; opacity:.9; pointer-events:none; }
  @media (max-width:420px){ .hero-illust{ width:96px; } }
  /* Junior's mission gets the hero-illust corner too, but a companion instead of
     the abstract mountain graphic — the two are mutually exclusive (screens.home.js
     picks one), never layered. Full opacity/no filter unlike the mountain's washed-
     out tint: the companion is a real character, not a quiet background texture. */
  .hero-illust.hero-companion-illust{
    display:flex; align-items:flex-end; justify-content:flex-end;
    font-size:84px; line-height:1; opacity:1; filter:drop-shadow(0 10px 16px rgba(0,0,0,.28));
  }
  @media (max-width:420px){ .hero-illust.hero-companion-illust{ font-size:64px; } }

  /* Compact single-line stat row (zone 2) — everything the old hero-stat-row's
     big percent used to carry, moved out of the hero and down to one plain line:
     lessons this month, streak, words learned overall (learnedWords().length,
     the same count Settings' "Слов выучено" tile already shows). */
  .stat-line{
    display:flex; align-items:center; flex-wrap:wrap; gap:5px; margin-top:var(--space-3); padding:0 2px;
    font-size:13px; font-weight:600; color:var(--ink-soft);
  }
  .stat-line .num{ font-weight:700; color:var(--ink); font-family:'Unbounded',sans-serif; font-variant-numeric:tabular-nums; }
  .stat-line-icon{ display:inline-flex; width:14px; height:14px; color:var(--accent-2); flex:none; }
  .stat-line-icon svg{ width:100%; height:100%; }
  .stat-line .dot{ color:var(--border); font-weight:400; margin:0 1px; }

  .month-grid{ display:flex; flex-direction:column; gap:var(--space-3); margin-top:var(--space-4); }
  /* п.39 (тени, раунд 2): убрала box-shadow — эта же пара
     .month-card/.practice-row/.profile-row/.region-card и т.п. и так уже
     держит границу перепадом --surface/--bg, transparent-border остаётся
     только как цель для hover/active-состояний ниже. */
  .month-card{
    display:flex; align-items:center; gap:var(--space-4); padding:var(--space-4);
    background:var(--surface); border-radius:var(--radius-md); text-align:left;
    border:1.5px solid transparent; transition:border-color .15s ease, background .15s ease;
  }
  .month-card:hover:not(.locked){ border-color:var(--accent-2); }
  /* Sofia (10.5): locked cards keep title + lock + progress only — the
     Georgian subtitle (.m-ka, below) is the detail that goes.
     Sofia (л. locked-card contrast): .5 read as disabled-UI-grey rather than
     "next up, not yet unlocked" — raised to .62 so a locked card still reads
     as real content waiting its turn, not a switched-off control. */
  .month-card.locked{ opacity:.62; }
  .month-card.locked .m-ka{ display:none; }
  /* v38: the one month card that's actually "today's lesson" (see screens.home.js's
     numState === "active") gets a visibly stronger treatment — a tinted background
     and a real border instead of the same plain surface every other month card
     uses — so it's obvious at a glance which card to tap next, without touching
     which month is unlocked or how that's decided. Sofia (10.3): a plain border
     read as "just another card" — the left edge is now noticeably thicker than
     the rest of the border, so the accent registers before you even read the
     badge. */
  .month-card.month-card-active{
    background:linear-gradient(135deg, color-mix(in srgb, var(--hero-a) 10%, var(--surface)), color-mix(in srgb, var(--hero-b) 10%, var(--surface)));
    border-color:color-mix(in srgb, var(--hero-b) 45%, transparent); border-left-width:4px; padding:var(--space-6) var(--space-4);
  }
  /* Replaces the old plain-uppercase .month-card-eyebrow — a small filled pill
     with a dot reads as a live status chip, not just another text label. */
  .month-badge{
    display:inline-flex; align-items:center; gap:5px; align-self:flex-start;
    font-size:11px; font-weight:800; letter-spacing:.03em; text-transform:uppercase;
    color:var(--hero-b-text); background:color-mix(in srgb, var(--hero-b) 16%, var(--surface));
    border-radius:999px; padding:3px 10px 3px 8px; margin-bottom:4px;
  }
  .month-badge::before{ content:""; width:6px; height:6px; border-radius:50%; background:var(--hero-b); flex:none; }
  .month-num{
    width:52px; height:52px; border-radius:50%; flex:none; display:flex; align-items:center; justify-content:center;
    font-family:'Unbounded',sans-serif; font-weight:700; font-size:18px;
    background:var(--surface-2); color:var(--ink-faint); border:2px dashed var(--border);
  }
  .month-num.active{ background:var(--accent); color:var(--accent-ink); border:none; box-shadow:0 4px 0 0 var(--accent-hover); }
  .month-num.done{ background:var(--gold); color:var(--accent-ink); border:none; box-shadow:0 4px 0 0 color-mix(in srgb, var(--gold) 70%, black); }
  .month-num svg{ width:22px; height:22px; }
  .month-body{ flex:1; min-width:0; display:flex; flex-direction:column; gap:2px; }
  .month-body .m-title{ font-size:16px; font-weight:700; }
  .month-body .m-ka{ font-size:13px; color:var(--ink-soft); margin-top:1px; }
  /* Same fix as .region-bar/.side-nav-progress-bar (see nav.css) — most visible on
     a .locked month card, where opacity:.55 (below) crushes an already-subtle
     surface/surface-2 step the same way .region-card.empty did. */
  .month-progress{ margin-top:var(--space-2); height:6px; border-radius:4px; background:var(--surface-2); border:1px solid var(--border); overflow:hidden; }
  .month-progress > i{ display:block; height:100%; background:var(--success); }
  /* .month-card-active swaps the card's own background for a pastel hero-color
     gradient (see above) — --surface-2/--border are tuned for the plain --surface
     every other card uses, and read as almost the same tone as that gradient, so
     the track disappeared into the card instead of just the (already-fixed)
     locked-card opacity case. A track derived from --ink instead — near-black in
     light mode, near-white in dark — stays visible against any background color,
     since it's the same token already relied on for text contrast on that surface. */
  .month-card-active .month-progress{
    background:color-mix(in srgb, var(--ink) 10%, transparent);
    border-color:color-mix(in srgb, var(--ink) 22%, transparent);
  }
  .month-count{ font-family:'Unbounded',sans-serif; font-size:11.5px; color:var(--ink-faint); margin-top:var(--space-1); }

  /* ---- Numbers trainer's stage list (js/screens.numbers.js) ----
     Reuses .month-grid/.month-card wholesale (same locked/active/done
     language as the Home month picker above) but with two scoped overrides,
     both from Sofia's review of the redesign:
     1) A locked Home month card hides its Georgian subtitle on purpose —
        that's real spoiler-y content (the day's actual words). A locked
        Numbers stage's subtitle is just "which numbers live here" (20, 40,
        60…), which is exactly the context Sofia wants visible even before
        the block unlocks — so undo the inherited .locked .m-ka{display:none}
        for this list specifically, without touching the Home grid it also
        governs.
     2) Slightly more breathing room between cards (space-4 instead of the
        shared space-3) — with every card's subtitle now always showing (see
        above) plus the new .stage-type-tag line below, rows got visually
        denser than the plain 2-line Home month cards this component was
        built for. */
  .numbers-stage-grid{ gap:var(--space-4); }
  .numbers-stage-grid .month-card.locked .m-ka{ display:block; }
  .stage-type-tag{
    display:inline-flex; align-self:flex-start; margin-top:5px;
    font-size:10.5px; font-weight:700; color:var(--ink-faint);
    background:var(--surface-2); border-radius:999px; padding:2px 8px;
  }
  .month-card-active .stage-type-tag{
    background:color-mix(in srgb, var(--ink) 8%, transparent); color:var(--ink-soft);
  }

  /* ---- Numbers trainer — four semantic "families" (round 2/3 review) ----
     units+teens=basics, rule20+tensMajor+tensAll=twenties, anyRule=pattern,
     hundreds+thousands=big. No new palette — each reuses a color the app
     already has for something adjacent in meaning:
       basics   — teal,  the app's own "Georgian/knowledge" identity (--hero-b)
       twenties — purple, the app's own "learning/progression" identity (--hero-a)
       pattern  — pink,   the app's primary accent (--accent)
       big      — gold,   the app's existing reward/achievement color (--gold)
     Deliberately no text legend spelling these names out anywhere (Sofia,
     round 3: "нобody needs 'Базовые'/'Двадцатки' spelled out separately, the
     block titles already say it") — the color is a quiet, unlabelled cue,
     except on the adult divider below, which does carry a one-line label
     because that label's the whole point of the divider (round 3, second
     note) — not the family name, the *content* ("how 20/30/40 are built"). */
  :root{
    --fam-basics:var(--hero-b); --fam-twenties:var(--hero-a); --fam-pattern:var(--accent); --fam-big:var(--gold);
  }
  /* Locked cards keep a colored left edge (their family) instead of a flat
     grey border — the one thing that made every locked row read as "the same
     row repeated 6 times". */
  .numbers-stage-grid .month-card.locked{ border-left-color:var(--fam-color, var(--border)); border-left-width:4px; }
  .month-card.fam-basics{ --fam-color:var(--fam-basics); } .month-card.fam-twenties{ --fam-color:var(--fam-twenties); }
  .month-card.fam-pattern{ --fam-color:var(--fam-pattern); } .month-card.fam-big{ --fam-color:var(--fam-big); }

  /* Section dividers ahead of each family's first stage (round 3, second
     note — Sofia: "можно вернуть информацию о том, как формируются 20, 30,
     40" — that explanation used to sit right on the old single-page screen;
     the block redesign moved it inside the rule20 lesson only, so it
     disappeared from the overview). One line, in the family's color, zero
     taps to read. No border-top rule above it (Sofia: "не делай черту перед
     правилом, она лишняя") — the colored dot plus the bold heading already
     separates it from the card above without needing a literal line too. */
  .stage-divider{ display:flex; align-items:flex-start; gap:9px; margin:18px 0 2px; }
  .stage-divider:first-child{ margin-top:0; }
  .stage-divider i{ width:8px; height:8px; border-radius:50%; background:var(--fam-color); margin-top:4px; flex:none; }
  .stage-divider b{ display:block; font-size:13px; font-weight:800; color:var(--ink); }
  .stage-divider span{ display:block; font-size:12px; color:var(--ink-soft); margin-top:2px; line-height:1.4; }
  .stage-divider.fam-basics{ --fam-color:var(--fam-basics); } .stage-divider.fam-twenties{ --fam-color:var(--fam-twenties); }
  .stage-divider.fam-pattern{ --fam-color:var(--fam-pattern); } .stage-divider.fam-big{ --fam-color:var(--fam-big); }

  /* ---- Numbers trainer, kid profile (round 3) ----
     Header is the app's own real .hero/.hero-card (css above, js/screens.home.js)
     — not a bespoke component — carrying progress + a "what's next" line +
     the child's own companion in the corner (same companionEmoji()/
     hero-illust markup Home uses). Replaces round 2's eyebrow+progress-dots
     stack, which Sofia found "перегружен" once paired with the legend below it.

     Below it: one tile per stage, family-colored (see --fam-* above) with
     state layered on top as a second, independent axis — locked = flat
     neutral grey (state hasn't started, no color yet), active = that
     family's color at full strength (the one thing to look at), done = a
     soft pastel tint of the same family color with a star for its icon
     (Sofia, round 1: "звезда вместо галочки"). Nothing is ever at full
     saturation except the single active tile, so "all 8 open" stays calm by
     construction rather than by accident (Sofia, round 2: worried a fully-
     open kid screen would look "слишком ярко"). Generous gap between tiles
     (--space-6, 24px — Sofia, round 3: still "склеено" at the previous 16px). */
  .kid-grid{ display:flex; flex-direction:column; gap:var(--space-6); margin-top:var(--space-4); }
  .kid-tile{
    display:flex; align-items:center; gap:14px; padding:var(--space-4); width:100%;
    border-radius:var(--radius-lg); border:none; text-align:left; font-family:inherit; cursor:pointer;
    position:relative; overflow:hidden; isolation:isolate; background:var(--surface-2); color:var(--ink-faint);
  }
  .kid-tile.locked{ border-left:4px solid var(--fam-color, var(--border)); padding-left:calc(var(--space-4) - 4px); }
  .kid-tile.locked .kid-tile-title{ color:var(--ink-soft); }
  .kid-tile.done{
    background:color-mix(in srgb, var(--fam-color) 14%, var(--surface)); color:var(--ink);
    box-shadow:inset 0 0 0 1.5px color-mix(in srgb, var(--fam-color) 30%, transparent);
  }
  .kid-tile.active{
    color:#fff; background:linear-gradient(135deg, var(--fam-color) 0%, color-mix(in srgb, var(--fam-color) 65%, black) 100%);
    box-shadow:0 10px 22px -12px color-mix(in srgb, var(--fam-color) 70%, transparent);
  }
  .kid-tile.active::after{
    content:""; position:absolute; inset:0; border-radius:inherit;
    background:radial-gradient(140% 160% at 100% -20%, rgba(255,255,255,.3), transparent 55%);
    pointer-events:none;
  }
  .kid-tile-icon{
    position:relative; z-index:1; flex:none; width:48px; height:48px; border-radius:var(--radius-sm);
    display:flex; align-items:center; justify-content:center;
    font-family:'Unbounded',sans-serif; font-weight:800; font-size:16px;
    background:var(--surface); color:var(--ink-faint);
  }
  .kid-tile.active .kid-tile-icon{ background:rgba(255,255,255,.24); color:#fff; }
  .kid-tile.done .kid-tile-icon{ background:var(--surface); color:var(--gold); }
  .kid-tile-icon svg{ width:24px; height:24px; }
  .kid-tile-body{ position:relative; z-index:1; min-width:0; flex:1; }
  .kid-tile-title{ font-family:'Unbounded',sans-serif; font-weight:700; font-size:14.5px; line-height:1.25; }
  .kid-tile-sub{ display:block; font-size:11.5px; margin-top:3px; line-height:1.35; opacity:.85; }
  .kid-tile-type{
    display:inline-flex; margin-top:5px; font-size:10px; font-weight:800; letter-spacing:.01em;
    background:rgba(255,255,255,.22); border-radius:999px; padding:2px 8px;
  }
  .kid-tile:not(.active) .kid-tile-type{ background:color-mix(in srgb, var(--ink) 7%, transparent); }
  .kid-tile-cta{
    position:relative; z-index:1; flex:none; background:rgba(255,255,255,.94); color:var(--fam-color, var(--accent-hover));
    font-family:'Unbounded',sans-serif; font-weight:700; font-size:11px; border-radius:999px; padding:7px 12px;
  }
  .kid-tile.fam-basics{ --fam-color:var(--fam-basics); } .kid-tile.fam-twenties{ --fam-color:var(--fam-twenties); }
  .kid-tile.fam-pattern{ --fam-color:var(--fam-pattern); } .kid-tile.fam-big{ --fam-color:var(--fam-big); }

  /* ---- Numbers trainer, desktop split view (round 5) ----
     Sofia: opening the Numbers screen on a laptop just showed the same phone
     list stretched wide, with nothing using the extra room. This is the
     master-detail layout she picked over a simple wider grid: the stage list
     stays exactly where it already is (numbers-stage-grid / kid-grid,
     unchanged), a fixed column on the left; a stage's content opens beside
     it instead of replacing it, in a card-styled pane on the right — mirrors
     .wrap-crystals' own desktop-only widening below, same idea applied to a
     two-column split instead of a wider single grid. Only mounted at
     .numbers-split's own 1024px breakpoint (js/screens.numbers.js decides
     via matchMedia, not CSS alone, since the *markup* itself differs — a
     detail pane instead of a second screen — not just its layout). */
  .numbers-split{ display:flex; gap:var(--space-6); align-items:flex-start; margin-top:var(--space-2); }
  .numbers-split-list{ flex:0 0 336px; min-width:0; }
  .numbers-split-detail{
    flex:1; min-width:0; position:sticky; top:var(--space-6);
    background:var(--surface); border:1.5px solid var(--border); border-radius:var(--radius-lg);
    padding:var(--space-6);
  }
  .numbers-detail-head{ display:flex; align-items:center; gap:10px; margin-bottom:var(--space-4); }
  .numbers-detail-head h3{ font-size:19px; font-weight:800; margin:0; color:var(--ink); }
  /* The open card/tile gets the same accent ring already used for an already-
     picked companion or cover (see .shop-card.active, above) — a familiar
     "this one's selected" signal reused, not a new one invented for here. */
  .month-card.selected{ box-shadow:0 0 0 2.5px var(--accent); }
  .kid-tile.selected{ box-shadow:0 0 0 2.5px var(--accent), 0 10px 22px -12px color-mix(in srgb, var(--accent) 40%, transparent); }

  /* ---- Facts-about-the-country entry card (home) + alphabet entry card ---- */
  /* Alphabet and Facts side by side, each at half width — see screens.home.js's
     entryRow comment. No wrap: this stays one row at every width, phone included
     (a wrap breakpoint would fight with "half width, one row" on exactly the
     narrow screens this is for). flex (not grid) so a single card, when only one
     of the two is present, naturally fills the row instead of leaving an empty
     half. */
  .home-entry-row{ display:flex; gap:var(--space-3); margin-top:var(--space-4); }
  /* Half width is too tight for the full-size horizontal icon+title+subtitle
     layout the standalone (full-width) card uses below, so the layout switches
     to icon-above-text — but font sizes, icon size and padding all stay the
     exact same values as the full-width card (Sofia: half-width cards read as
     visibly smaller/cramped when those shrink too — text wraps to a second
     line more often here, and that's fine, it's the tradeoff for keeping type
     consistent instead of shrinking it to fit). */
  .home-entry-row .facts-entry-card{
    flex:1; min-width:0; margin-top:0;
    flex-direction:column; align-items:flex-start; gap:var(--space-3); padding:var(--space-4);
  }
  .facts-entry-card{
    display:flex; align-items:center; gap:var(--space-4); padding:var(--space-4); margin-top:var(--space-4);
    background:var(--surface);
    border:1.5px solid var(--border); border-radius:var(--radius-md); text-align:left; width:100%;
  }
  .facts-entry-card:hover{ border-color:var(--hero-b); }
  .facts-entry-icon{
    width:52px; height:52px; border-radius:50%; flex:none; display:flex; align-items:center; justify-content:center;
    background:color-mix(in srgb, var(--hero-b) 20%, var(--surface)); color:var(--hero-b);
    border:1.5px solid color-mix(in srgb, var(--hero-b) 45%, transparent);
  }
  .facts-entry-icon svg{ width:24px; height:24px; }
  /* Sofia: Alphabet and Facts used to share one purple->teal gradient treatment —
     read as two copies of the same card, not two different sections. Each now
     gets its own color + surface instead, matching the color system's own
     "purple = learning/progression, teal = Georgian/knowledge" split (see the
     v2 color system comment in tokens.css) — Alphabet stays a plain neutral
     surface with a big purple glyph (no badge circle needed, the glyph itself
     carries the color), Facts keeps its icon badge but on a light teal wash
     instead of the old gradient. #alpha-entry / #facts-entry are the actual
     card ids (js/screens.home.js, screens/home.php) — styling them directly
     needs no extra class, since both render paths already share these ids. */
  #alpha-entry:hover{ border-color:var(--category-a); }
  #alpha-entry .facts-entry-icon{
    background:none; border:none; color:var(--category-a);
  }
  #facts-entry{ background:var(--teal-100); border-color:transparent; }
  #facts-entry:hover{ border-color:var(--category-b); }
  .facts-entry-body{ flex:1; min-width:0; display:flex; flex-direction:column; gap:2px; }
  .facts-entry-body .f-title{ font-size:16px; font-weight:700; }
  .facts-entry-body .f-sub{ font-size:13px; color:var(--ink-soft); margin-top:2px; }
  /* The fact-of-the-day preview (screens.home.js factOfTheDay()) is real fact
     text, not the short static subtitle — clamp it to two lines so a long fact
     never blows out the card's height. */
  .facts-entry-body .f-sub.fact-of-day{
    display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden;
  }

  /* ---- Facts-about-the-country list screen ---- */
  .facts-list{ display:flex; flex-direction:column; gap:var(--space-3); padding-top:var(--space-2); padding-bottom:var(--space-6); }
  .fact-card{
    background:color-mix(in srgb, var(--cat-color, var(--surface)) 6%, var(--surface));
    border:1.5px solid var(--border); border-left:4px solid var(--cat-color, var(--border));
    border-radius:var(--radius-md); padding:var(--space-4);
  }
  /* Sofia (16): every 4th card in the main collection list (see the realCardIdx
     counter in renderFacts()) renders bigger — a small/small/big/small/small/big
     rhythm instead of one flat repeating card shape down a long scroll. More
     padding, a bigger headline, and a stronger tint/left-border make it read as
     "worth pausing on" without turning into a whole different component. */
  .fact-card.featured{
    /* Was var(--space-5), a token that doesn't exist in tokens.css — an invalid
       var() makes the whole shorthand invalid, so this padding was silently
       collapsing to 0 on every featured card (Sofia's "some cards have no left
       inset" report). var(--space-4) is the token actually defined. */
    padding:var(--space-6) var(--space-4);
    border-left-width:6px;
    background:color-mix(in srgb, var(--cat-color, var(--surface)) 11%, var(--surface));
  }
  .fact-card.featured .fact-card-text{ font-size:19.5px; line-height:1.4; }
  .fact-card.featured .fact-tag{ font-size:11px; }
  /* Sofia (17): six different category colors was one color too many to read
     at a glance — collapsed to the same three-color language already used
     elsewhere in the app (tokens.css's color system + the Home/Trainers
     screens): purple for history & culture (learning/knowledge-about), teal
     for nature & daily life (the same "Georgian/everyday" family as the
     Alphabet/Facts split on Home), pink for humor & food (the lighter, "fun"
     categories). Gold is reserved for genuinely reward-like things (XP badges,
     crystals) elsewhere in the app, not spent here on just another category. */
  .fact-card[data-cat="history"]{ --cat-color:var(--category-a); }
  .fact-card[data-cat="culture"]{ --cat-color:var(--category-a); }
  .fact-card[data-cat="humor"]{ --cat-color:var(--accent); }
  .fact-card[data-cat="food"]{ --cat-color:var(--accent); }
  .fact-card[data-cat="nature"]{ --cat-color:var(--category-b); }
  .fact-card[data-cat="daily"]{ --cat-color:var(--category-b); }
  /* Editorial layout (Sofia, п.24) — small category tag, the fact set large as the
     card's own headline (there's no separate title text; the sentence is the
     content), a region link as its own row at the bottom. Replaces the old
     icon-circle + two-chip-row layout, which read as a form field summary rather
     than something meant to be read.
     Sofia (18): the tag used to compete with the fact text for attention —
     shrunk a touch further (10.5px) and, more importantly, the label itself
     is now blended toward --ink-soft instead of the full-strength category
     color, so it still reads as "this category" at a glance without out-
     shouting the actual fact underneath it. */
  .fact-tag{
    display:inline-flex; align-items:center; gap:5px; font-size:10.5px; font-weight:700; text-transform:uppercase; letter-spacing:.04em;
    color:color-mix(in srgb, var(--cat-color, var(--hero-b)) 65%, var(--ink-soft));
    background:color-mix(in srgb, var(--cat-color, var(--hero-b)) 11%, var(--surface));
    border-radius:999px; padding:4px 10px 4px 8px; margin-bottom:var(--space-3);
  }
  .fact-tag-icon{ display:flex; }
  .fact-tag-icon svg{ width:13px; height:13px; }
  .fact-card-text{ font-size:16.5px; line-height:1.45; font-weight:600; color:var(--ink); }
  .fact-card-link{
    display:inline-flex; align-items:center; gap:4px; margin-top:var(--space-3); font-family:inherit;
    font-size:13px; font-weight:700; color:var(--accent); background:none; border:none; padding:0;
  }
  .fact-card-link-arrow{ transition:transform .15s ease; }
  .fact-card-link:hover .fact-card-link-arrow{ transform:translateX(2px); }

  /* ---- Facts: tabs (collection / regions) + locked-slot placeholders ---- */
  .facts-tabs{ display:flex; gap:var(--space-2); margin:4px 0 var(--space-4); }
  .facts-tab{
    background:var(--surface); border:1.5px solid var(--border); border-radius:999px;
    padding:var(--space-2) var(--space-4); font-family:inherit; font-size:13px; font-weight:700; color:var(--ink-soft);
    line-height:1.2; white-space:nowrap;
  }
  .facts-tab.active{ background:var(--accent); border-color:var(--accent); color:var(--accent-ink); }
  .fact-locked{
    background:var(--surface-2); border:1.5px dashed var(--border); border-radius:var(--radius-md);
    padding:var(--space-4); display:flex; align-items:center; gap:var(--space-3); color:var(--ink-faint); font-size:13px;
  }
  .fact-locked svg{ width:18px; height:18px; flex:none; }

  /* ---- Facts: regions map + grid + region detail ---- */
  /* The map's own fill colors (per-path style="fill:...", set in georgiaMapHtml())
     already encode unlock progress, so this wrapper only needs to frame it — same
     card look as everything else on this screen, not a special "map" treatment. */
  /* Sofia (19): the map read a little small against the surrounding UI, with a
     lot of the card's own padding just sitting empty on the map's left/right
     (the country's shape is wide and short, so side padding cost more visible
     "emptiness" than top/bottom did). Full-bleed to the card's left/right edges
     — the rounded corners (border-radius + overflow:hidden) still frame it —
     reclaims that space as map instead of margin, growing the rendered map
     itself by roughly the padding that used to sit beside it, without touching
     the SVG's own viewBox/shapes at all. */
  .georgia-map{
    background:var(--surface); border:1.5px solid var(--border); border-radius:var(--radius-md);
    padding:var(--space-3) 0; margin-top:var(--space-2); display:flex; position:relative; overflow:hidden;
  }
  .georgia-map svg{ width:100%; height:auto; display:block; }
  .georgia-map path[id]{ cursor:pointer; transition:filter .15s ease, stroke .15s ease, stroke-width .15s ease; }
  .georgia-map path[id]:hover, .georgia-map path[id]:focus-visible{ filter:brightness(1.1); outline:none; }
  /* Sofia, п.26 — the hover/tap target gets a real outline, not just a subtle
     brightness bump, so it's unmistakable which shape the tooltip is naming. */
  .georgia-map path[id].map-region-active{ stroke:var(--ink); stroke-width:2.5px; }
  /* v36: city dots + labels drawn on top of the region shapes (pointer-events:none
     set inline per-marker in georgiaMapHtml() so they never block the hover/tap
     target beneath them), and the floating name tooltip shown on hover/tap. */
  .map-city circle{ fill:var(--ink); stroke:var(--surface); stroke-width:1.4px; }
  .map-city text{
    font-family:inherit; font-size:11px; font-weight:700; fill:var(--ink);
    paint-order:stroke; stroke:var(--surface); stroke-width:3px; stroke-linejoin:round;
  }
  .map-tooltip{
    position:absolute; left:0; top:0; transform:translate(-50%, -130%);
    background:var(--ink); color:var(--surface); font-size:13px; font-weight:700;
    padding:var(--space-1) var(--space-3); border-radius:var(--radius-sm); white-space:nowrap; pointer-events:none;
    box-shadow:0 4px 14px rgba(0,0,0,.2); z-index:3;
  }
  .map-tooltip::after{
    content:""; position:absolute; left:50%; top:100%; transform:translateX(-50%);
    border:5px solid transparent; border-top-color:var(--ink);
  }
  /* Sofia (21): "Вся Грузия 0/15" used to render as just another region-card —
     same shape, same bar — reading as one more region rather than what it
     actually was (a leftover "uncategorized facts" bucket). It's now a
     distinct summary strip instead: how many of the real regions are fully
     explored, out of the total — an overview *above* the grid of individual
     regions, not one more entry inside it. Teal, matching .region-card.complete
     — this is specifically a "how much is DONE" number. */
  .georgia-summary{
    display:flex; align-items:center; gap:var(--space-3); margin-top:var(--space-3);
    padding:var(--space-3) var(--space-4); background:var(--surface); border:1.5px solid var(--border); border-radius:var(--radius-md);
  }
  .georgia-summary-label{ font-size:11px; font-weight:800; letter-spacing:.06em; text-transform:uppercase; color:var(--ink-faint); flex:none; }
  .georgia-summary-count{ font-family:'Unbounded',sans-serif; font-size:13px; font-weight:700; color:var(--ink); flex:none; }
  .georgia-summary-bar{ flex:1; height:6px; border-radius:999px; background:var(--surface-2); border:1px solid var(--border); overflow:hidden; }
  .georgia-summary-bar i{ display:block; height:100%; background:var(--hero-b); }
  .region-grid{ display:grid; grid-template-columns:repeat(auto-fill,minmax(150px,1fr)); gap:var(--space-3); margin-top:var(--space-3); padding-bottom:var(--space-6); }
  .region-card{
    background:var(--surface); border-radius:var(--radius-md); border:1.5px solid transparent;
    padding:var(--space-4); display:flex; flex-direction:column; gap:4px; text-align:left; color:var(--ink);
  }
  /* Sofia (20): not-started shouldn't share a look with "in progress" — same
     "muted content, not a disabled control" reasoning as the locked month-cards
     on Home (opacity .62 there too, not .5), so a not-yet-opened region still
     reads as the next thing to explore rather than an inert element. */
  .region-card.empty{ opacity:.62; }
  /* Sofia, п.26 / (20): three distinct states, same color language as the map
     right above these cards (georgiaMapHtml() — pink while in progress, teal
     once fully read, neutral otherwise): a fully-read region gets the teal
     "done" treatment (matches .region-bar's fill below and the map's own 100%
     fill); a region with SOME facts seen but not all gets a matching pink tint
     instead of looking identical to a not-started one but for its bar. */
  .region-card.complete{
    background:color-mix(in srgb, var(--hero-b) 9%, var(--surface));
    border-color:color-mix(in srgb, var(--hero-b) 40%, transparent);
  }
  .region-card.current{
    background:color-mix(in srgb, var(--accent) 8%, var(--surface));
    border-color:color-mix(in srgb, var(--accent) 35%, transparent);
  }
  .region-name{ font-size:14px; font-weight:700; }
  .region-count{ font-family:'Unbounded',sans-serif; font-size:12px; color:var(--ink-soft); }
  /* A plain surface-2-on-surface trough (no border) turned out to disappear
     entirely on a "not started yet" region card — .empty's opacity:.5 crushes an
     already-subtle surface/surface-2 step down toward the page background, so
     there was nothing left to distinguish the bar's own shape from its card. A
     thin --border outline (the same fix .segment already uses for the lesson
     progress bar) survives that dimming because --border is a more distinct tone
     to begin with. */
  .region-bar{ height:6px; border-radius:999px; background:var(--surface-2); border:1px solid var(--border); overflow:hidden; margin-top:6px; }
  .region-bar i{ display:block; height:100%; background:var(--accent); }
  .region-card.complete .region-bar i{ background:var(--hero-b); }

  /* ---- Achievements / badges screen (Sofia: "коллекция наград, а не таблица
     прогресса") — three fixed color tiers instead of one pale gold wash, and
     a locked state with its own honest cool-neutral look instead of the same
     card at opacity:.55. Shared by three call sites via badgeTilesHtml()
     (js/screens.practice.js): this dedicated screen, the Crystals tab
     (screens.crystals.js) and the inline Settings block — one component,
     restyle once. */
  .achievements-sub{ color:var(--ink-soft); font-size:14px; margin-top:var(--space-1); }
  .badges-grid{ display:grid; grid-template-columns:repeat(3, 1fr); gap:var(--space-3); margin-top:var(--space-4); padding-bottom:var(--space-6); }
  .badge-tile{
    display:flex; flex-direction:column; align-items:center; gap:6px; padding:var(--space-4) var(--space-2);
    border-radius:var(--radius-md); border:1.5px solid transparent; background:var(--badge-locked-fill);
    position:relative;
  }
  .badge-tile-icon{ width:28px; height:28px; color:var(--badge-locked-icon); }
  .badge-tile-icon svg{ width:100%; height:100%; display:block; }
  .badge-tile-amount{ font-family:'Unbounded',sans-serif; font-weight:800; font-size:15px; color:var(--badge-locked-ink); }
  .badge-tile-label{ font-size:11px; color:var(--badge-locked-ink); text-transform:uppercase; letter-spacing:.04em; opacity:.8; }
  .badge-tile.locked{ border-color:var(--badge-locked-border); }

  /* Тир A (100/1000/5000 XP) — тёплое золото, настоящая яркая заливка вместо
     бледной. Тир B (250/2000/7500) — голубой, чтобы карточки различались.
     Тир C (500/3500/10000) — "веха": свечение вокруг карточки + иконка
     чуть крупнее + настоящий венок (ICONS.medal) вместо звезды. */
  .badge-tile.earned.tier-a{ background:var(--badge-a-fill); }
  .badge-tile.earned.tier-a .badge-tile-icon{ color:var(--badge-a-icon); }
  .badge-tile.earned.tier-a .badge-tile-amount, .badge-tile.earned.tier-a .badge-tile-label{ color:var(--badge-a-ink); }
  .badge-tile.earned.tier-b{ background:var(--badge-b-fill); }
  .badge-tile.earned.tier-b .badge-tile-icon{ color:var(--badge-b-icon); }
  .badge-tile.earned.tier-b .badge-tile-amount, .badge-tile.earned.tier-b .badge-tile-label{ color:var(--badge-b-ink); }
  .badge-tile.earned.tier-c{ background:var(--badge-c-fill); box-shadow:0 0 0 2px var(--badge-c-icon) inset, 0 6px 18px -8px var(--badge-c-icon); }
  .badge-tile.earned.tier-c .badge-tile-icon{ width:32px; height:32px; color:var(--badge-c-icon); }
  .badge-tile.earned.tier-c .badge-tile-amount, .badge-tile.earned.tier-c .badge-tile-label{ color:var(--badge-c-ink); }

  /* ---- Crystals (XP) screen: shop, spend instructions, history ---- */
  /* Sofia, п.28: the balance used to be a small number inside a plain card — now
     a real hero block, big number first, with its own call to action beside it.
     Stays a plain --surface card rather than a gradient fill (п.34 — the pink/
     purple gradient is already reused for the Home hero, Alphabet hero and the
     Practice dashboard; a fourth reuse here starts to read as "gradient on every
     card", the exact zoomer-ish pattern she asked to avoid) and --gold-text is
     already the AA-contrast-safe variant for sitting on --surface, so no new
     color risk across the purchasable theme skins. */
  .crystals-hero{
    display:flex; align-items:center; justify-content:space-between; gap:var(--space-4); flex-wrap:wrap;
    background:var(--surface); border-radius:var(--radius-lg);
    padding:var(--space-6) var(--space-4); margin-top:var(--space-1);
  }
  .crystals-hero-info{ display:flex; align-items:center; gap:var(--space-3); }
  /* Sofia: the number was so heavy (46px/800) it out-weighed the diamond icon
     next to it, which got lost. Gave the icon its own tinted circle badge — it's
     no longer competing bare against a huge dark number — and brought the number
     down to a size/weight where the two actually balance as one unit. */
  .crystals-hero-icon{
    width:50px; height:50px; border-radius:50%; flex:none; display:flex; align-items:center; justify-content:center;
    background:color-mix(in srgb, var(--gold) 16%, var(--surface)); color:var(--gold);
  }
  .crystals-hero-icon svg{ width:25px; height:25px; }
  .crystals-hero-amount{ font-family:'Unbounded',sans-serif; font-variant-numeric:tabular-nums; font-weight:700; font-size:36px; line-height:1; color:var(--gold-text); }
  .crystals-hero-label{ font-size:12px; font-weight:800; letter-spacing:.05em; text-transform:uppercase; color:var(--ink-faint); margin-top:3px; }
  /* Sofia, п.30: chunky — real height, bold, an icon, a strong fill — scoped to
     just this screen's buy buttons rather than the app-wide .btn, so the rest of
     the app's buttons aren't nudged as a side effect of this one ask. */
  .crystals-hero-cta{
    flex:none; display:inline-flex; align-items:center; gap:6px; min-height:48px; padding:0 20px;
    background:var(--accent); color:var(--accent-ink); font-family:inherit; font-weight:800; font-size:14.5px;
    border:none; border-radius:14px; box-shadow:0 4px 0 0 var(--accent-hover); cursor:pointer;
  }
  .crystals-hero-cta:active{ transform:translateY(3px); box-shadow:none; }
  /* п.37: было капсом — Sofia называла именно этот класс как пример
     ("РАМКИ ДЛЯ АВАТАРА", он же .shop-group-label). Это настоящий заголовок
     секции (группирует карточки под собой), а не мелкий meta-лейбл — обычный
     регистр, letter-spacing убран (он был нужен только для читаемости капса). */
  .crystals-section-title{ font-size:12.5px; font-weight:700; color:var(--ink-faint); margin:var(--space-6) 0 var(--space-3); }

  /* ---- Crystals showcase redesign (п.27): tabs instead of one long vertical
     scroll, a filterable product-card grid instead of horizontal-scroll rows.
     Sofia: "предлагаю внедрять" after approving the standalone concept mockup —
     this ports that mockup's markup/CSS 1:1 into the real screen. ---- */
  .crystals-tabs{ display:flex; gap:4px; background:var(--surface-2); padding:4px; border-radius:14px; margin:var(--space-4) 0 var(--space-4); }
  .crystals-tab{ flex:1; text-align:center; padding:10px 4px; border-radius:11px; font-weight:800; font-size:13px; color:var(--ink-faint); border:none; background:none; font-family:inherit; cursor:pointer; }
  .crystals-tab.active{ background:var(--surface); color:var(--ink); box-shadow:var(--shadow-soft); }
  .tab-panel{ display:none; }
  .tab-panel.active{ display:block; }

  /* Category filter chips (Shop tab only). v1 was a solid accent-pink fill on
     the active chip — right next to the pink "Выбрано" tags and pink active-card
     borders below, it turned into a wall of the same pink and stopped reading as
     "a filter" specifically (Sofia: "фильтр плохо смотрится"). An outline style
     — quiet border by default, a thin accent border + tinted background when
     active, no solid fill — stays legible as UI chrome instead of competing
     with the products themselves. */
  .filter-chips{ display:flex; gap:8px; overflow-x:auto; padding-bottom:var(--space-3); scrollbar-width:none; }
  .filter-chips::-webkit-scrollbar{ display:none; }
  .filter-chip{
    flex:none; padding:7px 15px; border-radius:999px; background:var(--surface);
    font-size:12.5px; font-weight:700; color:var(--ink-soft); font-family:inherit; cursor:pointer;
    border:1.5px solid var(--border);
  }
  .filter-chip.active{ border-color:var(--accent); background:color-mix(in srgb, var(--accent) 10%, var(--surface)); color:var(--accent); }

  /* Category divider, shown only in the "Всё" filter between groups so mixed
     frame/theme/boost cards don't read as one undifferentiated pile (Sofia: "в
     магазине все вместе плохо смотрится, нужны разделители"). Reuses the app's
     own section-title styling; spans however many grid columns the current
     breakpoint has. */
  .shop-group-label{ grid-column:1 / -1; margin:var(--space-2) 0 0; }
  .shop-group-label:first-child{ margin-top:0; }

  /* Product grid replacing the old horizontal-scroll .shop-row/.shop-item rows —
     a showcase card per item instead of a small swatch chip. */
  .shop-grid{ display:grid; grid-template-columns:1fr 1fr; gap:var(--space-3); padding-bottom:var(--space-6); }
  .shop-card{
    position:relative; background:var(--surface); border-radius:var(--radius-md);
    padding:var(--space-4) var(--space-3) var(--space-3); display:flex; flex-direction:column; align-items:center; gap:8px;
    border:1.5px solid transparent; font-family:inherit; cursor:pointer; text-align:center; width:100%;
  }
  .shop-card.active{ border-color:transparent; box-shadow:0 0 0 2.5px var(--accent); }
  .shop-card:disabled{ opacity:.5; cursor:default; }
  /* "ХИТ" ribbon: a fixed gold + near-black text pair, not the theme's --gold
     token (a muted, AA-for-small-text shade in light mode but a bright saturated
     one in dark mode — one hardcoded text color read fine against one and murky
     against the other, Sofia: "читабельность не очень хорошая"). Foil-gold +
     dark ink, like a physical sticker, stays ~11:1 contrast in both themes. */
  .shop-card-featured{
    position:absolute; top:-9px; left:50%; transform:translateX(-50%); white-space:nowrap;
    background:#F2B705; color:#2B1D00; font-size:10px; font-weight:800; text-transform:uppercase;
    letter-spacing:.04em; padding:3px 9px; border-radius:8px; box-shadow:var(--shadow-soft);
  }
  .shop-card-swatch-box{ width:72px; height:72px; display:flex; align-items:center; justify-content:center; }
  /* Sofia: a frame is worn on a round avatar, so its preview should be the real
     circular ring (.avatar-frame, reused from the header/Settings — see
     avatarWithFrameHtml() in screens.crystals.js), not a rounded-square gradient
     chip. .avatar-frame's real 2.5px ring (shell.css) reads fine at header size
     but got lost at this smaller preview scale, where telling frames apart at a
     glance is the whole point — thicker padding here only. */
  .shop-card-swatch-box .who-avatar{ width:52px; height:52px; font-size:19px; }
  .shop-card-swatch-box .avatar-frame{ padding:3.5px; }
  .shop-card-icon{ width:56px; height:56px; border-radius:16px; display:flex; align-items:center; justify-content:center; background:color-mix(in srgb, var(--accent) 14%, var(--surface)); color:var(--accent); }
  .shop-card-icon svg{ width:28px; height:28px; }
  .shop-card-name{ font-weight:700; font-size:13.5px; }
  .shop-card-sub{ font-size:11px; color:var(--ink-faint); margin-top:-4px; }
  .shop-card-tag{ display:inline-flex; align-items:center; gap:4px; font-weight:800; font-size:12.5px; padding:5px 12px; border-radius:999px; }
  .shop-card-tag.price{ background:var(--gold-soft); color:var(--gold-text); }
  .shop-card-tag.price svg{ width:11px; height:11px; }
  .shop-card-tag.owned{ background:var(--success-soft); color:var(--success); }
  .shop-card-tag.active-tag{ background:var(--accent); color:var(--accent-ink); }
  .shop-card-tag.info{ background:var(--surface-2); color:var(--ink-faint); }
  /* Sofia: themes need an actual preview of the interface, not a flat 2-color
     gradient swatch (she pointed at macOS's Light/Dark picker as the reference) —
     a tiny mockup card built from the theme's own palette instead. --tm-hero-a /
     --tm-hero-b / --tm-accent are set inline per theme (screens.crystals.js); the
     "no theme" swatch sets none of them, so these fall back to the *live* tokens —
     an accurate small preview of "your current theme" rather than a placeholder. */
  .theme-swatch{
    width:56px; height:52px; border-radius:var(--radius-sm); overflow:hidden; flex:none;
    display:flex; flex-direction:column; background:var(--surface); border:1px solid var(--border);
  }
  .theme-swatch-hero{ height:56%; flex:none; background:linear-gradient(135deg, var(--tm-hero-a, var(--hero-a)), var(--tm-hero-b, var(--hero-b))); }
  .theme-swatch-body{ flex:1; display:flex; align-items:center; gap:4px; padding:0 6px; }
  .theme-swatch-dot{ width:9px; height:9px; border-radius:50%; flex:none; background:var(--tm-accent, var(--accent)); }
  .theme-swatch-line{ flex:1; height:4px; border-radius:2px; background:var(--border); }

  /* Sofia: "я не хочу делать приложение ТОЛЬКО для телефона" — wider grid at
     laptop widths instead of the mobile columns just stretching with empty
     margins. Scoped to .wrap-crystals (not the shared .wrap every screen uses)
     so this doesn't change any other screen's width; the tab bar gets its own
     cap at the same breakpoint so 3 tabs don't stretch into sparse thirds of a
     ~700-920px bar. */
  @media (min-width:700px){
    .wrap-crystals{ max-width:680px; }
    .shop-grid{ grid-template-columns:repeat(3, 1fr); }
    .crystals-tabs{ max-width:360px; margin-left:auto; margin-right:auto; }
  }
  @media (min-width:1000px){
    .wrap-crystals{ max-width:920px; }
    .shop-grid{ grid-template-columns:repeat(4, 1fr); }
  }

  /* Companion picker (js/screens.companion.js) — Step 1 of "the one loop":
     reuses .shop-grid/.shop-card (same tap-to-select card, same .active ring)
     instead of a new grid system, since a hero choice and a cosmetic choice
     are the same interaction shape. Emoji placeholders sit where a frame's
     SVG icon normally would — .companion-emoji only bumps the font-size up
     to fill that same 56px box. */
  /* Reached two ways now — first-time onboarding (js/screens.companion.js's own
     header comment) and later, deliberately, from Junior Profile's "Герой"
     section — so it needs a way out that isn't just "finish the picker".
     .back-btn is the exact same round icon button .month-header uses; this
     is a plain one-button row above the (still centered) title block, not a
     second .month-header — that layout reads as "navigating a list", this
     screen still wants the onboarding-style centered moment. */
  .companion-picker-topbar{ padding-top:var(--space-4); }
  .companion-picker-head{ padding:var(--space-2) 0 var(--space-2); text-align:center; }
  .companion-picker-head h2{ font-size:22px; margin-bottom:6px; }
  .companion-picker-head .lede{ color:var(--ink-soft); font-size:14.5px; line-height:1.45; max-width:340px; margin:0 auto; }
  .companion-grid{ grid-template-columns:repeat(2, 1fr); margin-top:var(--space-5); }
  @media (min-width:420px){ .companion-grid{ grid-template-columns:repeat(3, 1fr); } }
  .companion-emoji{ font-size:30px; background:none; }
  /* "Без героя" — Sofia: the picker used to force a pick (Next stayed
     disabled until one of five was tapped); this card is the sixth, honest
     option — same tap-to-select shape as a real companion, just dashed and
     empty, so a kid isn't cornered into a hero they don't want. */
  .companion-card.none .companion-emoji{
    width:34px; height:34px; margin:0 auto; border-radius:50%; border:2px dashed var(--ink-faint);
    display:flex; align-items:center; justify-content:center; font-size:15px; color:var(--ink-faint);
  }
  .companion-card.none.active{ border-color:var(--accent); }
  .companion-picker-cta{ display:block; width:100%; margin:var(--space-6) 0 var(--space-4); }

  /* Spend-instructions used to be N separate bordered boxes stacked in a column —
     now a plain divided list (own row, bottom rule, no box) under its section
     title, the same "text block with dividers" treatment history-list already
     used below it — one less kind of container on a screen that already has
     several. */
  .instructions-list{ display:flex; flex-direction:column; }
  .instruction-row{ display:flex; align-items:center; gap:var(--space-3); padding:var(--space-3) var(--space-1); border-bottom:1px solid var(--border); }
  .instruction-row:last-child{ border-bottom:none; }
  .instruction-icon{ width:24px; height:24px; color:var(--ink-faint); flex:none; }
  .instruction-body{ flex:1; min-width:0; }
  .instruction-title{ font-weight:700; font-size:14px; }
  .instruction-sub{ font-size:12.5px; color:var(--ink-faint); margin-top:2px; }
  .instruction-cost{ font-size:12.5px; color:var(--gold-text); font-weight:800; white-space:nowrap; flex:none; display:flex; align-items:center; gap:2px; }
  .instruction-cost svg{ width:11px; height:11px; flex:none; }
  .history-list{ display:flex; flex-direction:column; }
  .history-row{ display:flex; align-items:center; justify-content:space-between; padding:var(--space-3) var(--space-1); border-bottom:1px solid var(--border); }
  .history-row:last-child{ border-bottom:none; }
  /* [hidden] and .history-row{display:flex} above are the same specificity, and
     author CSS beats the browser's own [hidden]{display:none} rule on a tie —
     so without this, the "collapsed" rows rendered anyway. This wins outright. */
  .history-row[hidden]{ display:none; }
  .history-label{ font-size:13.5px; font-weight:600; }
  .history-date{ font-size:11.5px; color:var(--ink-faint); margin-top:1px; }
  .history-amount{ font-weight:800; font-size:14px; }
  .history-amount.pos{ color:var(--success); }
  .history-amount.neg{ color:var(--ink-faint); }
  .history-empty{ color:var(--ink-faint); font-size:13.5px; padding:16px 0 24px; text-align:center; }
  /* Sofia: last 10 crystal-history rows show open, the rest sit "под кат" in the
     DOM ([hidden]) until this button reveals them — a low-stakes block gets a
     one-tap expand instead of numbered pagination controls. */
  .history-more-btn{
    display:block; width:100%; margin-top:var(--space-1); padding:var(--space-3);
    background:none; border:none; border-radius:var(--radius-sm);
    color:var(--accent); font-family:inherit; font-weight:700; font-size:13.5px; text-align:center; cursor:pointer;
  }
  .history-more-btn:active{ background:var(--surface-2); }
  .btn-icon-inline{ display:inline-flex; vertical-align:-3px; }
  .btn-icon-inline svg{ width:15px; height:15px; }

  /* ---- Month day-grid view ---- */
  .month-header{ display:flex; align-items:center; gap:var(--space-3); padding:var(--space-6) 0 var(--space-2); }
  .back-btn{
    background:var(--surface-2); border:none; color:var(--ink-soft); flex:none;
    width:38px; height:38px; border-radius:50%; display:flex; align-items:center; justify-content:center;
  }
  .back-btn:hover{ background:var(--border); color:var(--ink); }
  .back-btn svg{ width:19px; height:19px; display:block; }
  .month-header h2{ font-size:22px; }
  .month-header .ka{ font-size:14px; color:var(--ink-soft); display:block; margin-top:2px; }
  /* Tile radius is unified at --radius-md across every grid-of-tiles screen
     (day-grid, alpha-grid, number-grid, mult-grid below) — one shape language
     for "a tile you tap", same reasoning as the 3-level radius scale generally. */
  .day-grid{ display:grid; grid-template-columns:repeat(7, 1fr); gap:var(--space-3); padding:var(--space-4) 0 var(--space-8); }
  .day-node{
    aspect-ratio:1; border-radius:var(--radius-md); display:flex; align-items:center; justify-content:center;
    font-family:'Unbounded',sans-serif; font-weight:700; font-size:14px; border:none; position:relative;
  }
  .day-node.locked{ background:var(--surface-2); color:var(--ink-faint); border:1.5px dashed var(--border); }
  .day-node.available{ background:var(--accent); color:var(--accent-ink); box-shadow:0 3px 0 0 var(--accent-hover); }
  .day-node.available::after{ content:""; position:absolute; inset:-4px; border-radius:18px; border:2px solid var(--ring); animation:pulse 2.4s ease-out infinite; }
  @keyframes pulse{ 0%{ transform:scale(.96); opacity:.9;} 70%{ transform:scale(1.08); opacity:0;} 100%{opacity:0;} }
  .day-node.done{ background:var(--gold); color:var(--accent-ink); box-shadow:0 3px 0 0 color-mix(in srgb, var(--gold) 70%, black); }
  .day-node svg{ width:16px; height:16px; }
  .day-legend{ display:flex; gap:var(--space-4); flex-wrap:wrap; font-size:12.5px; color:var(--ink-faint); padding-bottom:var(--space-3); }
  .day-legend span{ display:inline-flex; align-items:center; gap:6px; }
  .legend-dot{ width:10px; height:10px; border-radius:50%; display:inline-block; }

  /* ---- Alphabet screen: current-letter header (Sofia 15) ---- */
  .alpha-hero{
    display:flex; align-items:center; gap:var(--space-4); margin-top:var(--space-4);
    padding:var(--space-4); border-radius:var(--radius-lg);
    background:linear-gradient(135deg, var(--category-a), var(--category-b));
    box-shadow:0 14px 28px -14px color-mix(in srgb, var(--category-a) 65%, transparent);
  }
  .alpha-hero-glyph{ font-size:56px; font-weight:700; line-height:1; color:#fff; flex:none; }
  .alpha-hero-info{ display:flex; flex-direction:column; gap:1px; min-width:0; }
  .alpha-hero-name{ font-size:15px; font-weight:700; color:#fff; }
  .alpha-hero-translit{ font-size:13px; color:rgba(255,255,255,.85); }
  .alpha-hero-pos{ font-size:12px; color:rgba(255,255,255,.75); margin-top:3px; }

  /* ---- Alphabet screen: letter tiles (glyph + reading, no popup) ---- */
  /* Deliberately its own class, not .day-grid/.day-node (shared with the month
     calendar) — these tiles need to fit two lines (glyph + reading) instead of
     one, so the sizing can't be shared with that grid. */
  .alpha-grid{ display:grid; grid-template-columns:repeat(5, 1fr); gap:var(--space-2); padding:var(--space-4) 0 var(--space-6); }
  .alpha-tile{
    display:flex; flex-direction:column; align-items:center; justify-content:center; gap:2px;
    border-radius:var(--radius-md); padding:var(--space-2) 4px; text-align:center;
  }
  .alpha-tile-ka{ font-size:20px; font-weight:600; line-height:1; }
  .alpha-tile-translit{ font-size:11px; font-weight:600; color:var(--ink-faint); }
  .alpha-tile.locked{ background:var(--surface-2); border:1.5px dashed var(--border); }
  .alpha-tile.locked .alpha-tile-ka{ color:var(--ink-faint); }
  /* Sofia (16): "learned" used gold before — gold is this app's reward/prize
     color (crystals, medals), which made every learned letter read a little
     like a trophy. Teal is this app's own "Georgian/knowledge" color instead,
     a better semantic fit for "you've learned this one". */
  .alpha-tile.done{ background:color-mix(in srgb, var(--category-b) 14%, var(--surface)); border:1.5px solid color-mix(in srgb, var(--category-b) 45%, transparent); }
  .alpha-tile.done .alpha-tile-ka{ color:var(--category-b-text); }
  /* The one letter you're actually on right now — same accent/pink as every
     other "do this next" cue in the app (day-node.available above uses the
     same color for the same reason), so it reads as "tap here" at a glance. */
  .alpha-tile.current{ background:var(--accent); border:1.5px solid var(--accent); box-shadow:0 3px 0 0 var(--accent-hover); }
  .alpha-tile.current .alpha-tile-ka{ color:var(--accent-ink); }
  .alpha-tile.current .alpha-tile-translit{ color:var(--accent-ink); opacity:.85; }
  .alpha-tile.done .alpha-tile-translit{ color:var(--ink-soft); }

  /* ---- Alphabet screen: numbers reference (digit + Georgian word + reading) ----
     Tiles, 5 to a row — like a flowing list, a column of longer Georgian number
     words ran together with too little to tell one row from the next. Fixed at
     5 columns even on narrow phones (unlike .alpha-grid, which drops to 4) —
     the numbers section was asked for specifically at 5, so the font shrinks
     to fit instead of the column count changing. */
  .section-subhead{ font-size:19px; margin:var(--space-6) 0 var(--space-3); }
  .number-grid{ display:grid; grid-template-columns:repeat(5, 1fr); gap:7px; padding-bottom:var(--space-2); }
  .number-tile{
    display:flex; flex-direction:column; align-items:center; justify-content:center; gap:3px;
    background:var(--surface); border:1.5px solid var(--border); border-radius:var(--radius-sm); padding:var(--space-2) 3px; text-align:center;
  }
  .number-tile-digit{
    font-family:'Unbounded',sans-serif; font-weight:800; font-size:10.5px; color:var(--accent);
    background:color-mix(in srgb, var(--accent) 12%, var(--surface));
    width:19px; height:19px; border-radius:50%; display:flex; align-items:center; justify-content:center;
  }
  .number-tile-ka{ font-size:12.5px; font-weight:600; line-height:1.15; }
  .number-tile-translit{ font-size:9.5px; color:var(--ink-faint); line-height:1.1; }

  /* ---- Alphabet screen: "how numbers are built" worked examples ---- */
  .number-rule-title{ font-size:15.5px; font-weight:700; margin-bottom:var(--space-1); }
  .number-rule-body{ font-size:13px; color:var(--ink-soft); line-height:1.5; margin:0 0 var(--space-3); }
  .number-formula{
    display:flex; flex-wrap:wrap; align-items:center; gap:var(--space-2); background:var(--surface);
    border:1.5px solid var(--border); border-radius:var(--radius-md); padding:var(--space-3) var(--space-4); margin-bottom:var(--space-3);
  }
  .nf-part{ display:flex; flex-direction:column; align-items:center; gap:1px; min-width:46px; }
  .nf-part b{ font-family:'Unbounded',sans-serif; font-size:11.5px; font-weight:700; color:var(--ink-faint); }
  .nf-part .ka{ font-size:15px; font-weight:600; }
  .nf-part .translit{ font-size:10.5px; color:var(--ink-faint); }
  .nf-part.nf-result .ka{ color:var(--accent); }
  .nf-op{ flex:none; font-family:'Unbounded',sans-serif; font-weight:800; font-size:15px; color:var(--ink-faint); }

  /* ---- Trainers hub ---- */
  /* v27 bento layout: 2 columns (big:small ≈ 2:1, matching Sofia's reference
     image) × 2 rows. The big tile is placed explicitly (col 1, spanning both
     rows); the two small tiles then auto-place into col 2's two rows in DOM
     order — no explicit placement needed for them. Grid items default to
     align-self:stretch, so the big tile's height becomes exactly "2 small
     tiles + the gap between them" for free, with no fixed pixel heights
     anywhere — it stays correct however tall the small tiles' content makes them. */
  .trainers-grid{
    display:grid; grid-template-columns:2fr 1fr; grid-template-rows:1fr 1fr;
    gap:var(--space-3); padding-top:var(--space-2);
  }
  .trainer-tile{
    display:flex; flex-direction:column; justify-content:flex-end; text-align:left;
    border-radius:var(--radius-md); border:1.5px solid var(--border); padding:var(--space-4);
    background:var(--surface);
    position:relative; overflow:hidden;
  }
  .trainer-tile:hover{ border-color:var(--hero-b); }
  .trainer-tile-small{ min-height:104px; }
  /* Sofia (14, 15): three visually independent "worlds" instead of one bento
     grid of near-identical cards — drop the shared icon-circle + gradient-tint
     background (every tile used to look like a copy of the same template with
     a different tiny glyph inside it) and let the subject itself carry the
     tile: a huge ა / 123 / × IS the icon now, not a decorative watermark
     bleeding off the edge behind one. Less copy too, per her note — each small
     tile is just its name plus that glyph, no subtitle line. Colors reuse the
     same purple/teal split already established on the Home screen's Alphabet/
     Facts cards (tokens.css's "learning" vs "Georgian/knowledge" split):
     Numbers stays teal (a course-knowledge drill, same family as Facts),
     Multiplication stays purple (a progression drill, same family as
     Alphabet) — a plain neutral surface behind each, like Home's cards. */
  .trainer-tile-glyph{
    position:relative; z-index:1; display:block; line-height:1;
    font-family:'Unbounded',sans-serif; font-weight:800; margin-bottom:var(--space-2);
  }
  .trainer-tile-glyph.ka{ font-family:'Noto Sans Georgian','Manrope',sans-serif; font-weight:700; }
  .trainer-tile .t-title{ position:relative; z-index:1; font-size:14.5px; font-weight:700; line-height:1.25; }
  .trainer-tile[data-entry="numbers"] .trainer-tile-glyph{ font-size:38px; color:var(--category-b); }
  /* "×" is a thin, mostly-whitespace glyph — needs a noticeably bigger
     font-size than "123" to read as the same visual weight/"hugeness". */
  .trainer-tile[data-entry="multiplication"] .trainer-tile-glyph{ font-size:68px; color:var(--category-a); }
  /* The big tile (always Алфавит — the section with the most content behind
     it) gets the same bright hero-gradient treatment as the home screen's
     "Изучаем грузинский" card, so it reads as the dominant, lead item rather
     than just a bigger version of the same neutral card — same gradient,
     same soft decorative circle, white text over it. The huge "ა" is now the
     one and only glyph on the tile (no separate icon-circle, no second faint
     watermark copy of the same letter competing with it). */
  .trainer-tile-big{
    grid-column:1; grid-row:1 / span 2; padding:var(--space-6); border-radius:var(--radius-lg);
    position:relative; overflow:hidden; border:none;
    background:linear-gradient(135deg, var(--category-a), var(--category-b));
    box-shadow:0 14px 28px -14px color-mix(in srgb, var(--category-a) 65%, transparent);
  }
  .trainer-tile-big::before{
    content:""; position:absolute; width:150px; height:150px; border-radius:50%;
    background:rgba(255,255,255,.10); top:-60px; right:-45px; pointer-events:none;
  }
  .trainer-tile-big .trainer-tile-glyph{
    font-size:88px; color:#fff; margin-bottom:0;
  }
  .trainer-tile-big .t-title{ position:relative; z-index:1; font-size:19px; color:#fff; margin-top:var(--space-1); }

  /* ---- Multiplication table picker ---- */
  /* Same "5 to a row" tile idea as .number-grid, but 13 tiles (×0-×12) don't
     divide evenly into 5 — 4 per row keeps the last row from looking sparse
     and matches .alpha-grid's narrow-screen column count instead. */
  .mult-grid{ display:grid; grid-template-columns:repeat(4, 1fr); gap:var(--space-2); padding:var(--space-3) 0 var(--space-6); }
  .mult-tile{
    display:flex; flex-direction:column; align-items:center; justify-content:center; gap:2px;
    padding:var(--space-3) 4px; border-radius:var(--radius-md); background:var(--surface); border:1.5px solid var(--border);
  }
  .mult-tile:hover{ border-color:var(--accent-2); }
  .mult-tile-op{ font-family:'Unbounded',sans-serif; font-size:13px; color:var(--ink-faint); }
  .mult-tile-n{ font-family:'Unbounded',sans-serif; font-size:22px; font-weight:700; }
  .mult-tile.done{ background:var(--gold-soft); border:1.5px solid var(--gold); }
  .mult-tile.done .mult-tile-op{ color:var(--ink-soft); }

  @media (max-width:420px){
    .alpha-grid{ grid-template-columns:repeat(4, 1fr); }
    .number-grid{ gap:5px; }
    .number-tile{ padding:7px 2px; }
    .number-tile-ka{ font-size:11px; }
    .number-tile-translit{ font-size:8.5px; }
    .mult-grid{ grid-template-columns:repeat(4, 1fr); gap:6px; }
    .mult-tile{ padding:11px 3px; }
    .mult-tile-n{ font-size:19px; }
  }

