/* Health Check - all styles. Split from index.html in v4.22.0; loaded as styles.css?v=APP_VERSION (the ?v= literal in index.html must match APP_VERSION in app.js - deploy.ps1 verifies). */
  :root {
    /* ===================================================================
       FOG THEME — light is primary, dark is a supported alternate.
       Spec tokens (--fog/--vellum/--ink/--ink-soft/--sage/--dusk/--amber/
       --hair) are the source of truth; the legacy names (--bg/--card/…)
       are aliased onto them so every existing component follows the theme
       without being rewritten. Dawn fog over water: calm, low-contrast,
       no pure white, no pure black, no gradient text, no colored shadows.
       =================================================================== */
    --fog:      #E9EEEC;   /* app background */
    --vellum:   #F6F9F8;   /* raised surfaces, rows, sheets */
    --ink:      #2A3634;   /* primary text */
    --ink-soft: #5E726C;   /* secondary text/labels — darkened from spec #6C807B to clear 4.5:1 on --fog */
    --sage:     #6E8E7F;   /* primary accent — completion, progress, active (darkened slightly from #7C9C8D for contrast on vellum) */
    --dusk:     #54657A;   /* secondary accent — charts, second series */
    --amber:    #B08A57;   /* warnings only, nothing decorative */
    --hair:     rgba(42,54,52,0.10);

    /* legacy aliases → mapped onto the fog system */
    --bg:      var(--fog);
    --surface: var(--vellum);
    --card:    var(--vellum);
    --accent:  var(--sage);         /* brand — progress, success, primary actions */
    --accent2: var(--ink-soft);     /* quiet secondary — labels, secondary emphasis */
    --gold:    var(--amber);        /* celebration reuses the amber tone in the light theme */
    --danger:  #B0554D;             /* muted coral, calm on a light ground */
    --text:    var(--ink);
    --muted:   var(--ink-soft);
    --border:  var(--hair);
    --done-bg:     rgba(110,142,127,0.10);   /* 10% sage wash on completed rows */
    --done-border: rgba(110,142,127,0.42);
    --warn:    var(--amber);
    --on-accent: var(--vellum);     /* text/glyph sitting on a --sage fill (e.g. the checkmark) */
    --gold-bg:     rgba(176,138,87,0.10);
    --gold-border: rgba(176,138,87,0.40);
    --frost:       #6E93A6;                 /* freeze days — a cool, calm iceberg blue */
    --frost-bg:    rgba(110,147,166,0.12);
    --frost-border:rgba(110,147,166,0.45);
    --shadow-1: 0 1px 2px rgba(42,54,52,0.04);
    --shadow-2: 0 1px 2px rgba(42,54,52,0.04);
    /* -- animation system: one calm easing, two duration buckets -- */
    --dur-1: 180ms;   /* tap feedback */
    --dur-2: 260ms;   /* micro — toggle, tab */
    --dur-3: 400ms;   /* panel — sheet, expand, flip */
    --ease-out: cubic-bezier(0.22, 0.61, 0.36, 1);
    --ease-spring: cubic-bezier(0.22, 0.61, 0.36, 1);  /* spring retired — a calm app never overshoots; alias kept so existing references stay calm */
  }
  /* legacy alias — accent3 was the old pink; map to danger */
  :root { --accent3: var(--danger); }

  /* ===================================================================
     THEMES — the user picks one in Settings (stored on their profile).
     :root is Fog (the clean light default). Dark and Sage override the
     tokens. If nothing is chosen yet, we follow the OS for dark.
     =================================================================== */
  :root[data-theme="dark"] {
    --fog:      #151B1A;
    --vellum:   #1D2523;
    --ink:      #DEE6E3;
    --ink-soft: #8FA29D;
    --sage:     #8FB0A0;
    --dusk:     #7C90A6;
    --amber:    #C79E68;
    --hair:     rgba(222,230,227,0.10);
    --danger:   #E0857C;
    --done-bg:     rgba(143,176,160,0.12);
    --done-border: rgba(143,176,160,0.42);
    --on-accent: #151B1A;
    --gold-bg:     rgba(199,158,104,0.12);
    --gold-border: rgba(199,158,104,0.40);
    --frost:       #9DC0D2;
    --frost-bg:    rgba(157,192,210,0.14);
    --frost-border:rgba(157,192,210,0.42);
    --shadow-1: 0 1px 2px rgba(0,0,0,0.28);
    --shadow-2: 0 1px 2px rgba(0,0,0,0.28);
  }
  /* Sage — a warmer, greener nature theme: soft green paper, moss + ochre */
  :root[data-theme="sage"] {
    --fog:      #E6EDE0;
    --vellum:   #F3F7EE;
    --ink:      #2B3A2C;
    --ink-soft: #566A50;
    --sage:     #5C8460;
    --dusk:     #7C8A56;   /* moss — the second series */
    --amber:    #AE8442;
    --hair:     rgba(43,58,44,0.11);
    --danger:   #A9564A;
    --done-bg:     rgba(92,132,96,0.12);
    --done-border: rgba(92,132,96,0.45);
    --on-accent: #F3F7EE;
    --gold-bg:     rgba(174,132,66,0.12);
    --gold-border: rgba(174,132,66,0.42);
    --frost:       #5E93A0;
    --frost-bg:    rgba(94,147,160,0.13);
    --frost-border:rgba(94,147,160,0.45);
    --shadow-1: 0 1px 2px rgba(43,58,44,0.05);
    --shadow-2: 0 1px 2px rgba(43,58,44,0.05);
  }
  /* no explicit choice yet → follow the OS for dark */
  @media (prefers-color-scheme: dark) {
    :root:not([data-theme]) {
      --fog: #151B1A; --vellum: #1D2523; --ink: #DEE6E3; --ink-soft: #8FA29D;
      --sage: #8FB0A0; --dusk: #7C90A6; --amber: #C79E68; --hair: rgba(222,230,227,0.10);
      --danger: #E0857C; --done-bg: rgba(143,176,160,0.12); --done-border: rgba(143,176,160,0.42);
      --on-accent: #151B1A; --gold-bg: rgba(199,158,104,0.12); --gold-border: rgba(199,158,104,0.40);
      --frost: #9DC0D2; --frost-bg: rgba(157,192,210,0.14); --frost-border: rgba(157,192,210,0.42);
      --shadow-1: 0 1px 2px rgba(0,0,0,0.28); --shadow-2: 0 1px 2px rgba(0,0,0,0.28);
    }
  }

  @media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
      animation-duration: 0.01ms !important;
      animation-iteration-count: 1 !important;
      transition-duration: 0.01ms !important;
    }
  }

  * { box-sizing: border-box; margin: 0; padding: 0; }

  /* keyboard focus: a visible ring for keyboard users only (not on mouse/touch) */
  :focus-visible {
    outline: 2px solid color-mix(in srgb, var(--dusk) 55%, transparent);
    outline-offset: 2px;
    border-radius: 6px;
  }

  /* phones: the page never scrolls sideways, whatever a child does */
  html, body { overflow-x: hidden; max-width: 100%; }
  svg { max-width: 100%; }

  body {
    font-family: 'Karla', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
    font-feature-settings: 'tnum' 1;   /* tabular numerals hold the stat tiles in line */
    background: var(--bg);
    color: var(--text);
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: calc(20px + env(safe-area-inset-top)) 16px calc(84px + env(safe-area-inset-bottom));
  }

  header { text-align: center; margin-bottom: 18px; position: relative; width: 100%; max-width: 520px; }
  .gear-btn {
    position: absolute; right: 0; top: 2px;
    width: 44px; height: 44px; border-radius: 14px;
    background: transparent; border: 1px solid var(--border); color: var(--muted);
    cursor: pointer; display: flex; align-items: center; justify-content: center;
    transition: color var(--dur-1), border-color var(--dur-1), transform var(--dur-1) var(--ease-out);
    -webkit-tap-highlight-color: transparent;
  }
  .gear-btn:active { transform: scale(0.92); }
  .gear-btn svg { width: 20px; height: 20px; }

  .date-badge {
    font-size: 13px; color: var(--muted);
    text-transform: uppercase; letter-spacing: 0.12em; margin-bottom: 8px;
  }

  /* one flat accent, high weight — gradient headings are gone for good */
  h1 {
    font-size: 26px; font-weight: 800; letter-spacing: -0.02em;
    color: var(--accent);
    margin-bottom: 4px;
  }

  /* the tagline reads once, then it's noise — and a healthy sync state is
     the expectation, not news. Status shows only when something's off;
     the full readout lives in Settings. */
  .subtitle { display: none; }
  .sync-pill.online { display: none; }

  .sync-pill {
    display: inline-flex; align-items: center; gap: 6px;
    margin-top: 10px; font-size: 11px; color: var(--muted);
    border: 1px solid var(--border); border-radius: 999px; padding: 4px 12px;
    text-transform: uppercase; letter-spacing: 0.08em;
  }
  .sync-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--muted); transition: background 0.3s; }
  .sync-pill.online .sync-dot { background: var(--accent); }
  .sync-pill.offline .sync-dot { background: var(--warn); }
  .sync-pill.demo .sync-dot { background: var(--accent3); }

  /* Progress ring (segments are drawn in JS as .ring-seg; angles already start
     at the top, so the SVG itself is not rotated) */
  .progress-wrap { position: relative; width: 120px; height: 120px; margin: 14px auto 22px; }
  .progress-label { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; pointer-events: none; }
  .progress-pct { font-size: 28px; font-weight: 700; color: var(--text); line-height: 1; }
  .progress-sub { font-size: 11px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.1em; margin-top: 2px; }

  /* Sections & items */
  .section { width: 100%; max-width: 520px; margin-bottom: 18px; }
  .section-label {
    font-size: 11px; text-transform: uppercase; letter-spacing: 0.12em;
    color: var(--muted); margin-bottom: 8px; padding-left: 4px;
    display: flex; justify-content: space-between; align-items: baseline;
  }
  .section-label .mini { font-size: 10px; letter-spacing: 0.06em; }

  .item {
    background: var(--card); border: 1px solid var(--border); border-radius: 16px;
    padding: 14px 16px; display: flex; align-items: center; gap: 12px; margin-bottom: 8px;
    cursor: pointer; user-select: none;
    /* a little lift so an untapped row reads as an interactive control, not text */
    box-shadow: 0 1px 3px color-mix(in srgb, var(--ink) 7%, transparent);
    transition: background var(--dur-3) var(--ease-out), border-color var(--dur-3) var(--ease-out), opacity var(--dur-3) var(--ease-out), transform var(--dur-1) var(--ease-out), box-shadow var(--dur-1) var(--ease-out);
    -webkit-tap-highlight-color: transparent;
    position: relative; touch-action: pan-y; overflow: hidden;
  }
  .item:not(.done):hover { box-shadow: 0 3px 10px color-mix(in srgb, var(--ink) 11%, transparent); }
  .item:active { transform: scale(0.98); }
  /* completion: the row background lifts to a 6% sage tint and the row settles
     to 55% opacity. No strikethrough — striking out a habit someone just did is
     punitive typography. The reward is the row going quiet. */
  .item.done { background: var(--done-bg); border-color: var(--done-border); opacity: 0.55; }
  /* radial wash from the touch point, settling once — the only flourish on check-off */
  .item.just-done::before {
    content: ''; position: absolute; inset: 0; pointer-events: none;
    background: radial-gradient(circle at var(--wx, 50%) var(--wy, 50%),
                color-mix(in srgb, var(--sage) 24%, transparent),
                color-mix(in srgb, var(--sage) 0%, transparent) 72%);
    transform-origin: var(--wx, 50%) var(--wy, 50%);
    animation: washIn var(--dur-2) var(--ease-out) forwards;
  }
  @keyframes washIn {
    0% { transform: scale(0.55); opacity: 0; }
    100% { transform: scale(1); opacity: 1; }
  }
  .item.swiping { transition: none; }
  /* parked rows: visibly resting, not interactive as a check-off */
  .item.parked-row { cursor: default; opacity: 0.75; background: var(--surface); border-style: dashed; }
  .item.parked-row:active { transform: none; }

  /* swipe affordances under the row */
  .swipe-track { position: relative; }
  .swipe-under {
    position: absolute; inset: 0 2px 8px; border-radius: 16px;
    display: flex; align-items: center; justify-content: space-between;
    padding: 0 20px; font-size: 13px; font-weight: 700; pointer-events: none;
    opacity: 0; transition: opacity var(--dur-1);
  }
  .swipe-under .su-done { color: var(--accent); }
  .swipe-under .su-note { color: var(--accent2); margin-left: auto; }
  .swipe-track.swipe-r .swipe-under { opacity: 1; background: var(--done-bg); }
  .swipe-track.swipe-r .su-note { visibility: hidden; }
  .swipe-track.swipe-l .swipe-under { opacity: 1; background: var(--surface); }
  .swipe-track.swipe-l .su-done { visibility: hidden; }

  .checkbox {
    width: 28px; height: 28px; border-radius: 8px;
    /* a clearly-visible ring (not a hairline) so it reads as "tap me" */
    border: 2px solid color-mix(in srgb, var(--ink-soft) 45%, transparent);
    background: color-mix(in srgb, var(--ink-soft) 5%, transparent);
    flex-shrink: 0; display: flex; align-items: center; justify-content: center;
    transition: background var(--dur-2), border-color var(--dur-2); font-size: 14px;
    position: relative;
  }
  /* the SVG checkmark inside any box — sizes to the box, colour follows text */
  .checkbox .ck, .pick-box .ck, .su-done .ck { width: 62%; height: 62%; display: block; }
  .su-done .ck { width: 16px; height: 16px; display: inline-block; vertical-align: -3px; }
  .item.done .checkbox { background: var(--accent); border-color: var(--accent); color: var(--on-accent); opacity: 1; }
  /* the check-off — the single most important interaction. It fills calmly and
     settles; it never overshoots, pulses, or throws a bloom ring. */
  .item.just-done .checkbox { animation: checkfill var(--dur-2) var(--ease-out); }
  @keyframes checkfill {
    0% { transform: scale(0.88); }
    100% { transform: scale(1); }
  }
  /* no settle bounce, no ring pulse — a calm app never overshoots. The ring
     value tweens in place via its stroke transition. */
  /* quiet breathing hint on the flip card */
  .flip-kicker .hint { animation: hintBreathe 2.8s ease-in-out infinite; }
  @keyframes hintBreathe {
    0%, 100% { opacity: 0.45; }
    50% { opacity: 0.9; }
  }
  .tab-svg { transition: transform var(--dur-2) var(--ease-spring); }
  .tabbar button.active .tab-svg { transform: scale(1.12) translateY(-1px); }
  .badge-tile { transition: transform var(--dur-1) var(--ease-out); }
  .badge-tile:active { transform: scale(0.95); }
  .hday { transition: transform var(--dur-1) var(--ease-out); }
  .hday:active { transform: scale(0.94); }

  .emoji { font-size: 22px; flex-shrink: 0; width: 32px; text-align: center; }
  .item-text { flex: 1; min-width: 0; }
  /* type hierarchy: name up in weight, down in size; desc a muted caption */
  .item-name { font-size: 14px; font-weight: 700; color: var(--text); }
  .item-desc { font-size: 11px; color: var(--muted); margin-top: 2px; }
  .tag {
    font-size: 9px; text-transform: uppercase; letter-spacing: 0.08em;
    border: 1px solid var(--border); color: var(--muted);
    border-radius: 999px; padding: 2px 7px; flex-shrink: 0;
  }
  .tag.custom { border-color: var(--border); color: var(--accent3); }

  /* Stats */
  .streak-row { width: 100%; max-width: 520px; display: flex; gap: 10px; margin-bottom: 18px; }
  .streak-card { flex: 1; background: var(--card); border: 1px solid var(--border); border-radius: 14px; padding: 14px 8px; text-align: center; }
  .streak-val { font-size: 22px; font-weight: 700; color: var(--accent); }
  .streak-lbl { font-size: 10px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.08em; margin-top: 2px; }

  /* History strip */
  .history-strip { width: 100%; max-width: 520px; display: flex; gap: 6px; margin-bottom: 20px; }
  /* inside the hero the strip is part of the orientation card, not a floater */
  .today-hero .history-strip { margin: 12px 0 0; }
  .today-hero .hday { background: color-mix(in srgb, var(--card) 72%, transparent); }
  .hday { flex: 1; background: var(--card); border: 1px solid var(--border); border-radius: 10px; padding: 8px 2px; text-align: center; cursor: pointer; min-height: 44px; -webkit-tap-highlight-color: transparent; }
  .hday .d { font-size: 10px; color: var(--muted); text-transform: uppercase; }
  .hday .s { font-size: 13px; font-weight: 700; margin-top: 2px; color: var(--text); }
  .hday.good { border-color: var(--done-border); background: var(--done-bg); }
  .hday.good .s { color: var(--accent); }
  .hday.frozen { border-color: var(--border); }
  .hday.frozen .s { color: var(--accent2); }
  .hday.today { border-color: var(--accent); }
  /* 7 tiles must fit a narrow phone without clipping */
  @media (max-width: 420px) {
    .history-strip { gap: 4px; }
    .hday { padding: 8px 1px; min-height: 40px; }
    .hday .d { font-size: 9px; }
    .hday .s { font-size: 11px; }
  }

  /* ---------- flip card — one card, front/back, milestone takes the slot ---------- */
  .flip-wrap {
    width: 100%; margin-bottom: 16px;
    perspective: 900px; -webkit-tap-highlight-color: transparent;
    transition: transform var(--dur-1) var(--ease-out);
  }
  /* only an unrevealed card invites a tap — pointer + press-down live on
     .tappable so a revealed card stops pretending to be a button */
  .flip-wrap.tappable { cursor: pointer; }
  .flip-wrap.tappable:active { transform: scale(0.985); }
  .flip-inner {
    position: relative; width: 100%;
    transform-style: preserve-3d;
    transition: transform var(--dur-3) var(--ease-out);
  }
  .flip-wrap.flipped .flip-inner { transform: rotateY(180deg); }
  .flip-face {
    width: 100%; backface-visibility: hidden; -webkit-backface-visibility: hidden;
    background: linear-gradient(135deg, var(--vellum), var(--vellum));
    border: 1px solid var(--border); border-radius: 16px; padding: 16px;
    box-shadow: var(--shadow-1);
  }
  .flip-back { position: absolute; inset: 0; transform: rotateY(180deg); overflow: hidden; }
  .flip-kicker { font-size: 10px; text-transform: uppercase; letter-spacing: 0.14em; color: var(--accent2); margin-bottom: 8px; display: flex; justify-content: space-between; }
  .flip-kicker .hint { letter-spacing: 0.04em; opacity: 0.7; }
  .flip-line { font-size: 14px; line-height: 1.6; color: var(--text); }
  .flip-line b { color: var(--accent); }
  .week-dots { display: flex; gap: 8px; margin: 8px 0 8px; }
  .wdot { width: 26px; height: 26px; border-radius: 50%; border: 1.5px solid var(--border);
    display: flex; align-items: center; justify-content: center; font-size: 9px; color: var(--muted); }
  .wdot.hit { background: var(--done-bg); border-color: var(--accent); color: var(--accent); font-weight: 700; }
  .wdot.miss { border-color: var(--border); }
  .wdot.frozen { border-color: var(--border); color: var(--accent2); }
  .wdot.today { border-color: var(--accent); border-style: dashed; }

  .flip-face.milestone { border-color: var(--gold-border); background: linear-gradient(135deg, var(--gold-bg), var(--vellum)); }
  .flip-face.milestone .flip-kicker { color: var(--gold); }
  .flip-face.milestone .flip-line b { color: var(--gold); }

  /* momentum win card: arrives face-down with a shimmer, reveals on tap */
  .flip-face.windown {
    border-color: var(--gold-border); background: linear-gradient(150deg, var(--gold-bg), var(--vellum));
    text-align: center; padding: 22px 16px; position: relative; overflow: hidden;
  }
  .flip-face.windown::after {
    content: ''; position: absolute; top: -60%; left: -30%; width: 40%; height: 220%;
    background: linear-gradient(100deg, transparent, rgba(245,198,107,0.14), transparent);
    transform: rotate(12deg); animation: winShimmer 2.6s ease-in-out infinite;
  }
  @keyframes winShimmer {
    0% { left: -45%; } 60%, 100% { left: 115%; }
  }
  .win-tap { font-size: 15px; color: var(--gold); font-weight: 800; letter-spacing: 0.03em; }
  .win-sub { font-size: 11px; color: var(--muted); margin-top: 6px; }
  .flip-face.winface { border-color: var(--gold-border); background: linear-gradient(135deg, var(--gold-bg), var(--vellum)); position: relative; overflow: hidden; }
  .flip-face.winface .flip-kicker { color: var(--gold); }
  .win-title { font-size: 17px; font-weight: 800; color: var(--gold); margin-bottom: 4px; }
  .flip-wrap.win-reveal .flip-inner { animation: winFlip 560ms var(--ease-spring); }
  @keyframes winFlip {
    0% { transform: rotateY(180deg) scale(0.94); }
    100% { transform: rotateY(0deg) scale(1); }
  }
  /* legacy card faces (kept for safety) */
  .flip-face.windown.daily { border-color: var(--border); background: linear-gradient(150deg, var(--vellum), var(--vellum)); }
  .flip-face.windown.daily .win-tap { color: var(--accent); }
  .flip-face.dayface { border-color: var(--border); background: linear-gradient(135deg, var(--vellum), var(--vellum)); }
  .day-title { font-size: 17px; font-weight: 800; color: var(--accent); margin-bottom: 4px; }

  /* ---------- card materials: bronze / silver / gold / platinum ----------
     rarity decides the metal; every card keeps the full reveal treatment
     (face-down shimmer, spring flip, confetti, haptic) — the metal and its
     colors are what escalate */
  .flip-face.cardface { position: relative; overflow: hidden; }
  .card-title { font-size: 17px; font-weight: 800; margin-bottom: 4px; }
  .flip-kicker .tierlbl { letter-spacing: 0.1em; font-weight: 700; }
  /* sheen sweep rides across every revealed card */
  .flip-face.cardface:not(.windown)::before {
    content: ''; position: absolute; top: -60%; left: -30%; width: 40%; height: 220%;
    transform: rotate(12deg); animation: winShimmer 3s ease-in-out infinite;
    pointer-events: none;
  }
  .flip-face.m-bronze { border-color: var(--gold-border); background: linear-gradient(135deg, var(--gold-bg), var(--vellum)); }
  .flip-face.m-bronze .card-title, .flip-face.m-bronze .tierlbl, .flip-face.m-bronze .win-tap { color: #d8a47a; }
  .flip-face.m-bronze::before, .flip-face.m-bronze::after { background: linear-gradient(100deg, transparent, rgba(216,164,122,0.12), transparent); }
  .flip-face.m-silver { border-color: var(--border); background: linear-gradient(135deg, var(--vellum), var(--vellum)); }
  .flip-face.m-silver .card-title, .flip-face.m-silver .tierlbl, .flip-face.m-silver .win-tap { color: var(--text); }
  .flip-face.m-silver::before, .flip-face.m-silver::after { background: linear-gradient(100deg, transparent, rgba(201,212,228,0.13), transparent); }
  .flip-face.m-gold { border-color: var(--gold-border); background: linear-gradient(135deg, var(--gold-bg), var(--vellum)); }
  .flip-face.m-gold .card-title, .flip-face.m-gold .tierlbl, .flip-face.m-gold .win-tap { color: var(--gold); }
  .flip-face.m-gold::before, .flip-face.m-gold::after { background: linear-gradient(100deg, transparent, rgba(245,198,107,0.14), transparent); }
  .flip-face.m-platinum { border-color: var(--border); background: linear-gradient(135deg, var(--vellum), var(--vellum)); }
  .flip-face.m-platinum .card-title, .flip-face.m-platinum .tierlbl, .flip-face.m-platinum .win-tap {
    background: linear-gradient(100deg, #7dd3fc, #c4b5fd, #f0a3c0, #f5c66b);
    -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent;
  }
  .flip-face.m-platinum::before, .flip-face.m-platinum::after { background: linear-gradient(100deg, transparent, rgba(196,181,253,0.16), transparent); }

  /* celebration motes — see the shared system below (.motes) */

  /* ---------- badges ---------- */
  .badge-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
  .badge-tile {
    background: var(--bg); border: 1px solid var(--border); border-radius: 12px;
    padding: 12px 8px; text-align: center; position: relative; min-height: 44px;
    -webkit-tap-highlight-color: transparent;
  }
  .badge-tile .bmult {
    position: absolute; top: 6px; right: 8px; font-size: 11px; font-weight: 800;
    color: var(--gold);
  }
  .badge-tile .bicon { font-size: 26px; }
  .badge-tile .bname { font-size: 11px; font-weight: 700; margin-top: 6px; line-height: 1.3; }
  .badge-tile .bsub { font-size: 9px; color: var(--muted); margin-top: 2px; line-height: 1.35; }
  /* material tiers — the material itself carries information.
     steel: brushed neutral · gold: warm · prismatic: iridescent sweep */
  .badge-tile.earned { border-color: var(--border); background: linear-gradient(160deg, var(--vellum), var(--vellum)); box-shadow: inset 0 1px 0 rgba(255,255,255,0.06); }
  .badge-tile.earned .bname { color: var(--text); }
  .badge-tile.earned.t-gold { border-color: var(--gold-border); background: linear-gradient(160deg, var(--gold-bg), var(--gold-bg)); }
  .badge-tile.earned.t-gold .bname { color: var(--gold); }
  .badge-tile.earned.t-prismatic {
    border-color: var(--border); position: relative; overflow: hidden;
    background: linear-gradient(160deg, var(--vellum), var(--vellum));
  }
  .badge-tile.earned.t-prismatic .bname {
    background: linear-gradient(100deg, #7dd3fc, #c4b5fd, #f0a3c0, #f5c66b);
    -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent;
  }
  .badge-tile.earned.t-prismatic::after {
    content: ''; position: absolute; top: -60%; left: -40%; width: 45%; height: 220%;
    background: linear-gradient(100deg, transparent, rgba(196,181,253,0.14), transparent);
    transform: rotate(14deg); animation: winShimmer 3.2s ease-in-out infinite;
  }
  .badge-tile.locked { opacity: 0.55; }
  .badge-tile.locked .bicon { filter: grayscale(1); opacity: 0.5; }

  .badge-reveal {
    position: fixed; inset: 0; z-index: 90; display: flex; align-items: center; justify-content: center;
    background: rgba(20, 26, 25, 0.48); backdrop-filter: blur(4px); -webkit-backdrop-filter: blur(4px);
    opacity: 0; pointer-events: none; transition: opacity var(--dur-2);
  }
  .badge-reveal.show { opacity: 1; pointer-events: auto; }
  .badge-reveal-card {
    background: linear-gradient(160deg, var(--gold-bg), var(--vellum)); border: 1px solid var(--gold-border);
    border-radius: 20px; padding: 32px 28px; text-align: center; max-width: 320px; width: calc(100% - 48px);
    box-shadow: var(--shadow-2);
    transform: scale(0.8); transition: transform var(--dur-3) var(--ease-spring);
  }
  .badge-reveal.show .badge-reveal-card { transform: scale(1); }
  /* earn moment: brief radial light sweep behind the badge, once */
  .badge-reveal-card { position: relative; overflow: hidden; }
  .badge-reveal.show .badge-reveal-card::before {
    content: ''; position: absolute; inset: -40%; pointer-events: none;
    background: radial-gradient(circle at 50% 35%, rgba(245,198,107,0.28), transparent 55%);
    animation: sweepIn 900ms var(--ease-out) forwards;
  }
  @keyframes sweepIn {
    0% { opacity: 0; transform: scale(0.6); }
    45% { opacity: 1; }
    100% { opacity: 0; transform: scale(1.35); }
  }
  .badge-reveal-card.t-prismatic { border-color: var(--border); background: linear-gradient(160deg, var(--vellum), var(--vellum)); }
  .badge-reveal-card.t-prismatic .bkicker {
    background: linear-gradient(100deg, #7dd3fc, #c4b5fd, #f0a3c0, #f5c66b);
    -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent;
  }
  .badge-reveal-card.t-steel { border-color: var(--border); background: linear-gradient(160deg, var(--vellum), var(--vellum)); }
  .badge-reveal-card.t-steel .bkicker { color: var(--text); }
  .badge-reveal-card .bicon { font-size: 56px; display: block; animation: checkpop 500ms var(--ease-spring); }
  .badge-reveal-card .bkicker { font-size: 10px; text-transform: uppercase; letter-spacing: 0.16em; color: var(--gold); margin: 16px 0 4px; }
  .badge-reveal-card .bname { font-size: 20px; font-weight: 800; }
  .badge-reveal-card .bdesc { font-size: 13px; color: var(--text); line-height: 1.6; margin-top: 8px; }
  .badge-reveal-card .actions { display: flex; gap: 8px; justify-content: center; margin-top: 20px; }

  /* ---------- celebration: fog catching light (replaces confetti) ----------
     Earned moments — badge reveals, win/milestone cards — get a calm bloom of
     drifting motes in the theme palette instead of a spinning confetti fall.
     Same atmospheric language as the app: soft forms that rise and fade like
     breath or mist catching the dawn, never a party. Three drifting shapes so
     the bloom isn't uniform. Reduced-motion is honored globally.
     Motes animate only when the moment is live: .motes.play (win cards, injected
     at reveal) or under .badge-reveal.show (the badge modal). */
  .motes { position: absolute; inset: 0; overflow: hidden; pointer-events: none; border-radius: inherit; }
  .motes span {
    position: absolute; bottom: 14%; opacity: 0;
    border-radius: 50%; filter: blur(0.4px); will-change: transform, opacity;
  }
  /* three forms: round light-mote, soft petal, fine speck */
  .motes.play span:nth-child(3n),
  .badge-reveal.show .motes span:nth-child(3n) {
    width: 7px; height: 7px; animation: mote-rise 2200ms var(--ease-out) forwards;
  }
  .motes.play span:nth-child(3n+1),
  .badge-reveal.show .motes span:nth-child(3n+1) {
    width: 5px; height: 9px; border-radius: 60% 60% 55% 55% / 70% 70% 42% 42%;
    animation: mote-drift 2600ms var(--ease-out) forwards;
  }
  .motes.play span:nth-child(3n+2),
  .badge-reveal.show .motes span:nth-child(3n+2) {
    width: 3px; height: 3px; animation: mote-rise 1900ms var(--ease-out) forwards;
  }
  @keyframes mote-rise {
    0%   { opacity: 0; transform: translateY(12px) scale(0.55); }
    22%  { opacity: 0.9; }
    100% { opacity: 0; transform: translateY(-130px) scale(1); }
  }
  @keyframes mote-drift {
    0%   { opacity: 0; transform: translate(0, 10px) rotate(-8deg) scale(0.55); }
    22%  { opacity: 0.82; }
    100% { opacity: 0; transform: translate(16px, -110px) rotate(20deg) scale(1); }
  }
  /* a single soft bloom of light behind the reveal — the room quietly brightening */
  .reveal-bloom {
    position: absolute; left: 50%; top: 42%; width: 190px; height: 190px;
    transform: translate(-50%, -50%) scale(0.4); pointer-events: none; opacity: 0;
    background: radial-gradient(circle, color-mix(in srgb, var(--sage) 20%, transparent), transparent 68%);
  }
  .motes.play .reveal-bloom,
  .badge-reveal.show .reveal-bloom { animation: bloom-soft 1500ms var(--ease-out) forwards; }
  @keyframes bloom-soft {
    0%   { opacity: 0; transform: translate(-50%, -50%) scale(0.4); }
    32%  { opacity: 1; }
    100% { opacity: 0; transform: translate(-50%, -50%) scale(1.32); }
  }

  /* ---------- item detail sheet ---------- */
  .sheet {
    position: fixed; inset: 0; z-index: 85; display: flex; align-items: flex-end; justify-content: center;
    background: rgba(20, 26, 25, 0.40); backdrop-filter: blur(3px); -webkit-backdrop-filter: blur(3px);
    opacity: 0; pointer-events: none; transition: opacity var(--dur-2);
  }
  .sheet.show { opacity: 1; pointer-events: auto; }
  .sheet-card {
    background: var(--surface); border: 1px solid var(--border); border-bottom: none;
    border-radius: 20px 20px 0 0; padding: 20px; width: 100%; max-width: 520px;
    max-height: 82vh; overflow-y: auto; overscroll-behavior: contain;
    transform: translateY(40px); transition: transform 320ms var(--ease-spring);
  }
  .sheet.show .sheet-card { transform: translateY(0); }
  /* grab handle: drag down anywhere on it to dismiss the sheet */
  .sheet-grab { padding: 2px 0 12px; touch-action: none; cursor: grab; }
  .sheet-grab::before {
    content: ''; display: block; width: 44px; height: 5px; border-radius: 999px;
    background: var(--border); margin: 0 auto;
  }
  .idet-head { display: flex; align-items: center; gap: 12px; margin-bottom: 16px; }
  .idet-head .emoji { font-size: 28px; }
  .idet-head .iname { font-size: 18px; font-weight: 800; flex: 1; }
  .idet-stats { display: flex; gap: 8px; margin-bottom: 16px; }
  .idet-stat { flex: 1; background: var(--bg); border: 1px solid var(--border); border-radius: 12px; padding: 10px 4px; text-align: center; }
  .idet-stat .v { font-size: 18px; font-weight: 700; color: var(--accent); }
  .idet-stat .l { font-size: 9px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.06em; margin-top: 2px; }
  .idet-heat { display: grid; grid-template-columns: repeat(10, 1fr); gap: 5px; margin-bottom: 8px; }
  .idet-cell { aspect-ratio: 1; border-radius: 6px; background: transparent; border: 1px dashed var(--border); cursor: pointer; -webkit-tap-highlight-color: transparent; }
  .idet-cell.hit { background: var(--accent); border: 1px solid var(--accent); }
  .idet-cell.miss { background: var(--vellum); border: 1px solid var(--border); }
  .idet-legend { font-size: 11px; color: var(--muted); margin-bottom: 16px; line-height: 1.6; }
  .idet-legend .box { width: 11px; height: 11px; border-radius: 4px; display: inline-block; vertical-align: -1px; margin-right: 2px; }
  .idet-note { background: var(--bg); border: 1px solid var(--border); border-radius: 12px; padding: 12px 14px; font-size: 13px; color: var(--text); line-height: 1.6; white-space: pre-wrap; margin-bottom: 16px; }

  /* ---------- avatar & greeting ---------- */
  /* slots are children of a centered flex column — without an explicit
     width they shrink to content and cards render at odd widths */
  #greetSlot, #flipSlot, #coachSlot { width: 100%; max-width: 520px; }
  .greet-card {
    width: 100%; display: flex; align-items: center; gap: 14px;
    background: var(--card); border: 1px solid var(--border); border-radius: 16px;
    padding: 12px 16px; margin-bottom: 16px; box-shadow: var(--shadow-1);
  }
  .greet-text { flex: 1; min-width: 0; }
  .greet-hi { font-size: 16px; font-weight: 700; }
  .greet-sub { font-size: 12px; color: var(--muted); margin-top: 2px; line-height: 1.5; }
  .avatar-svg { display: block; flex-shrink: 0; }

  .me-head { width: 100%; max-width: 520px; display: flex; align-items: center; gap: 14px; margin-bottom: 16px; }

  /* tappable avatar: no button chrome, generous target */
  .avatar-tap {
    background: none; border: none; padding: 0; cursor: pointer;
    min-width: 44px; min-height: 44px; display: flex; align-items: center; justify-content: center;
    -webkit-tap-highlight-color: transparent; flex-shrink: 0;
  }
  .avatar-tap:active .avatar-svg { transform: scale(0.92); }

  /* idle life: a gentle bob everywhere the avatar lives, and an
     occasional wave on the greeting card (reduced-motion kills both) */
  .greet-card .avatar-svg, .me-head .avatar-svg, .coach-card .avatar-svg {
    animation: avBob 3.6s cubic-bezier(0.37, 0, 0.63, 1) infinite;
    will-change: transform; transform: translateZ(0);
  }
  @keyframes avBob {
    0%, 100% { transform: translateY(0) rotate(0deg); }
    25% { transform: translateY(-1.6px) rotate(-0.4deg); }
    50% { transform: translateY(-2.6px) rotate(0deg); }
    75% { transform: translateY(-1.6px) rotate(0.4deg); }
  }
  .av-armR { transform-box: fill-box; transform-origin: top center; }
  .greet-card .av-armR { animation: avWave 7s ease-in-out infinite; }
  @keyframes avWave {
    0%, 74%, 96%, 100% { transform: rotate(0deg); }
    80% { transform: rotate(-52deg); }
    84% { transform: rotate(-24deg); }
    88% { transform: rotate(-52deg); }
    92% { transform: rotate(-24deg); }
  }
  .me-head .mh-name { font-size: 18px; font-weight: 800; flex: 1; }

  .trait-row { display: flex; gap: 6px; flex-wrap: wrap; margin: 6px 0 12px; }
  .trait-chip {
    min-width: 44px; min-height: 44px; border-radius: 12px; border: 1px solid var(--border);
    background: var(--card); cursor: pointer; font-family: inherit; color: var(--text);
    font-size: 12px; font-weight: 600; padding: 0 12px;
    display: inline-flex; align-items: center; justify-content: center;
    -webkit-tap-highlight-color: transparent;
  }
  .trait-chip.on { border-color: var(--accent); background: var(--done-bg); color: var(--accent); }
  .trait-chip .swatch { width: 22px; height: 22px; border-radius: 50%; display: block; }
  .trait-label { font-size: 10px; text-transform: uppercase; letter-spacing: 0.1em; color: var(--muted); }

  /* ---------- coach card — foundation-card anatomy: avatar column left,
     kicker → message → actions on the right ---------- */
  .coach-card {
    width: 100%; background: linear-gradient(135deg, var(--vellum), var(--vellum));
    border: 1px solid var(--border); border-radius: 16px; padding: 16px; margin-bottom: 16px;
    box-shadow: var(--shadow-1);
    display: flex; gap: 14px; align-items: flex-start;
  }
  .coach-card .cc-avatar { flex-shrink: 0; margin-top: 2px; }
  .coach-card .cc-body { flex: 1; min-width: 0; display: flex; flex-direction: column; }
  .cc-kicker {
    font-size: 11px; color: var(--accent2); font-weight: 700; letter-spacing: 0.01em;
    margin-bottom: 6px;
  }

  /* today's pulse — the day bar (ring, flattened) + the permanent week strip */
  .today-pulse { width: 100%; max-width: 520px; margin: 0 auto 12px; }
  .seg-bar-row { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; padding: 0 2px; }
  .seg-bar { flex: 1; display: flex; gap: 3px; height: 10px; }
  .seg-bar .seg { flex: 1; border-radius: 999px; background: var(--card); border: 1px solid var(--border); }
  .seg-bar .seg.on { background: var(--accent); border-color: var(--accent); }
  .seg-bar .seg.lit { animation: segFill 480ms var(--ease-out); transform-origin: center; }
  @keyframes segFill { 0% { transform: scaleY(0.35); opacity: 0.4; } 100% { transform: scaleY(1); opacity: 1; } }
  .seg-count { font-size: 11px; color: var(--muted); font-weight: 700; letter-spacing: 0.05em; white-space: nowrap; }

  /* the greeting as the rail's first card: title row */
  .coach-card.greet-rail { flex-direction: column; }
  .greet-rail .ccrow { display: flex; gap: 14px; align-items: flex-start; width: 100%; }
  .greet-rail .cc-kicker { font-size: 15px; color: var(--ink); letter-spacing: -0.01em; margin-bottom: 4px; }
  .greet-rail .avatar-tap { background: none; border: 0; padding: 0; cursor: pointer; -webkit-tap-highlight-color: transparent; }
  .coach-card .history-strip { margin: 12px 0 0; max-width: none; }
  .coach-card .hday { min-height: 38px; padding: 6px 1px; background: color-mix(in srgb, var(--card) 72%, transparent); }
  .coach-card .hday .d { font-size: 9px; }
  .coach-card .hday .s { font-size: 11px; }
  .coach-line { font-size: 14px; line-height: 1.6; color: var(--text); }
  .coach-line b { color: var(--accent); }
  .coach-actions { display: flex; gap: 8px; margin-top: 12px; flex-wrap: wrap; }

  /* in-app notification stack: horizontal snap-scroll + dot indicator */
  .coach-rail {
    display: flex; gap: 10px; overflow-x: auto;
    scroll-snap-type: x mandatory; -webkit-overflow-scrolling: touch;
    scrollbar-width: none; margin-bottom: 4px;
  }
  .coach-rail::-webkit-scrollbar { display: none; }
  .coach-rail .coach-card { flex: 0 0 100%; scroll-snap-align: center; margin-bottom: 0; }
  .coach-dots { display: flex; align-items: center; justify-content: center; gap: 3px; margin: 6px 0 14px; }
  /* each dot is a button: generous padded hit area, negative margin keeps the
     row visually as slim as plain dots */
  .coach-dots .cdot-btn { background: none; border: 0; padding: 16px 9px; margin: -12px 0;
    cursor: pointer; display: flex; align-items: center; -webkit-tap-highlight-color: transparent; }
  .coach-dots .cdot { width: 6px; height: 6px; border-radius: 999px; background: var(--border);
    transition: width var(--dur-2) var(--ease-out), background var(--dur-1); }
  .coach-dots .cdot.on { background: var(--accent); width: 18px; }
  .coach-dots .ccount { font-size: 10px; color: var(--muted); margin-left: 6px; letter-spacing: 0.06em; }

  /* ---------- the card rail — one home for everything the app has to say ----------
     The day's journey/celebration card rides first, then any coaching or
     park-return prompts. Several cards become a swipeable snap rail; each
     card leaves a sliver of the next showing so the rail reads as swipeable
     without instruction. Cells stretch so short cards match tall ones. */
  .story-rail {
    display: flex; gap: 10px; overflow-x: auto; align-items: stretch;
    scroll-snap-type: x mandatory; -webkit-overflow-scrolling: touch;
    scrollbar-width: none; margin-bottom: 4px;
  }
  .story-rail::-webkit-scrollbar { display: none; }
  /* min-height keeps the rail from jumping when a short teaser reveals into
     a taller card or a coach card resolves away */
  .story-cell { flex: 0 0 100%; min-width: 0; scroll-snap-align: start; display: flex; min-height: 150px; }
  .story-rail.peek .story-cell { flex-basis: calc(100% - 26px); }
  .story-cell > * { width: 100%; }
  .story-cell .flip-wrap { margin-bottom: 0; display: flex; }
  .story-cell .flip-inner { width: 100%; display: flex; }
  /* a short teaser centres itself in the rail's fixed-height cell */
  .story-cell .flip-face.windown { display: flex; flex-direction: column; justify-content: center; }
  .story-cell .coach-card { margin-bottom: 0; }
  .story-cell .cc-body { height: 100%; }
  .story-cell .coach-actions { margin-top: auto; padding-top: 12px; }
  .story-cell .foundation-card { margin-bottom: 0; }

  /* ---------- journey ---------- */
  /* the chart-card's full-width svg rule must not inflate the little avatar */
  #journeyLine .avatar-svg { width: 34px; height: 42px; flex: 0 0 auto; }
  .journey-row { display: flex; gap: 12px; padding: 8px 0; border-bottom: 1px solid var(--border); font-size: 13px; line-height: 1.5; }
  .journey-row:last-child { border-bottom: none; }
  .journey-date { color: var(--muted); font-size: 11px; flex-shrink: 0; width: 52px; padding-top: 2px; }
  .journey-text { color: var(--text); }

  /* ---------- Discover ---------- */
  .sort-row { width: 100%; max-width: 520px; display: flex; gap: 8px; margin-bottom: 16px; }
  .sort-chip {
    flex: 1; background: var(--card); border: 1px solid var(--border); color: var(--muted);
    font-family: inherit; font-size: 11px; font-weight: 600; padding: 8px 0; border-radius: 999px; cursor: pointer;
    text-transform: uppercase; letter-spacing: 0.06em;
    transition: border-color var(--dur-1), color var(--dur-1);
  }
  .sort-chip.active { border-color: var(--accent); color: var(--accent); }
  .vote-btn {
    display: inline-flex; align-items: center; gap: 6px;
    background: transparent; border: 1px solid var(--border); color: var(--muted);
    font-family: inherit; border-radius: 999px; padding: 6px 14px; font-size: 12px; cursor: pointer;
    transition: border-color var(--dur-1), color var(--dur-1), background var(--dur-1);
  }
  .vote-btn.voted { border-color: var(--done-border); color: var(--accent); background: var(--done-bg); }
  .pub-items { font-size: 13px; color: var(--text); margin-top: 8px; line-height: 1.6; }
  .pub-by { font-size: 11px; color: var(--muted); margin-top: 6px; }

  /* ---------- Affiliate picks (hidden while catalog is empty) ---------- */
  .gear-block { margin-top: 12px; border-top: 1px solid var(--border); padding-top: 10px; }
  .gear-head { font-size: 10px; text-transform: uppercase; letter-spacing: 0.08em; color: var(--muted); margin-bottom: 6px; }
  .gear-link { display: block; font-size: 13px; color: var(--accent); margin: 4px 0; text-decoration: underline; text-underline-offset: 3px; }

  /* plan-aware picks rail — clean rows, clearly labeled, never pushy */
  .gearrail-card {
    width: 100%; background: var(--card); border: 1px solid var(--border);
    border-radius: 16px; padding: 4px 16px 8px; margin-top: 6px; box-shadow: var(--shadow-1);
  }
  .gearrail-title {
    font-size: 11px; text-transform: uppercase; letter-spacing: 0.12em; color: var(--muted);
    padding: 14px 0 4px;
  }
  .gearrail-title .aff { display: block; text-transform: none; letter-spacing: 0; font-size: 10px; margin-top: 2px; opacity: 0.8; }
  .gear-row {
    display: flex; align-items: center; gap: 12px; min-height: 56px;
    padding: 8px 0; border-bottom: 1px solid var(--border); text-decoration: none;
    -webkit-tap-highlight-color: transparent;
    transition: transform var(--dur-1) var(--ease-out);
  }
  .gear-row:last-child { border-bottom: none; }
  .gear-row:active { transform: scale(0.985); }
  .gear-row .emoji { font-size: 20px; width: 28px; text-align: center; flex-shrink: 0; }
  .gr-text { flex: 1; min-width: 0; }
  .gr-for { display: block; font-size: 10px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.08em; }
  .gr-name { display: block; font-size: 14px; font-weight: 600; color: var(--text); margin-top: 1px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .gr-note { display: block; font-size: 12px; color: var(--accent); margin-top: 1px; }
  .gr-arrow { color: var(--muted); font-size: 18px; flex-shrink: 0; }

  .why-line {
    width: 100%; max-width: 520px; text-align: center;
    font-size: 13px; color: var(--accent2); font-style: italic;
    line-height: 1.5; margin: -6px 0 14px;
  }
  .why-line .wplan { color: var(--muted); font-style: normal; }

  .empty-note {
    width: 100%; max-width: 520px; text-align: center; color: var(--muted);
    font-size: 14px; line-height: 1.6; padding: 30px 20px;
    border: 1px dashed var(--border); border-radius: 16px; margin-bottom: 18px;
  }

  /* Buttons */
  .ghost-btn {
    background: transparent; border: 1px solid var(--border); color: var(--muted);
    font-family: inherit; font-size: 13px; padding: 10px 22px; border-radius: 999px; cursor: pointer;
    min-height: 44px; transition: border-color 0.2s, color 0.2s;
    -webkit-tap-highlight-color: transparent;
  }
  .ghost-btn:hover { border-color: var(--accent3); color: var(--accent3); }

  .primary-btn {
    width: 100%; background: var(--accent);
    border: none; border-radius: 12px; color: var(--on-accent); font-size: 15px; font-weight: 700;
    padding: 13px; cursor: pointer; margin-top: 4px;
    transition: transform var(--dur-1) var(--ease-out);
    -webkit-tap-highlight-color: transparent;
  }
  .primary-btn:active { transform: scale(0.98); }
  .primary-btn:disabled { opacity: 0.4; cursor: default; }

  /* mobile-first: every interactive control clears 44px (min touch target) */
  .small-btn {
    background: transparent; border: 1px solid var(--border); color: var(--text);
    font-family: inherit; font-size: 12px; padding: 6px 16px; border-radius: 999px; cursor: pointer;
    min-height: 44px; min-width: 44px; -webkit-tap-highlight-color: transparent;
    white-space: nowrap;
  }
  .small-btn.danger { color: var(--accent3); }
  .small-btn.confirm-armed { border-color: var(--accent3); color: var(--accent3); background: var(--vellum); }

  .footer-row { margin-top: 22px; display: flex; gap: 12px; align-items: center; }

  /* Auth & gates */
  .gate {
    width: 100%; max-width: 400px; background: var(--card);
    border: 1px solid var(--border); border-radius: 20px; padding: 28px 24px; margin-top: 24px;
  }
  .gate h2 { font-size: 20px; margin-bottom: 6px; }
  .gate p { font-size: 13px; color: var(--muted); line-height: 1.5; margin-bottom: 18px; }
  .gate input {
    width: 100%; background: var(--bg); border: 1px solid var(--border); border-radius: 12px;
    color: var(--text); font-size: 15px; padding: 12px 14px; margin-bottom: 10px; outline: none;
  }
  .gate input:focus { border-color: var(--accent2); }
  .gate .alt, .alt {
    display: block; text-align: center; margin-top: 14px; font-size: 13px;
    color: var(--accent2); cursor: pointer; background: none; border: none; width: 100%;
    font-family: inherit; min-height: 44px; -webkit-tap-highlight-color: transparent;
  }
  .auth-err { color: var(--accent3); font-size: 13px; margin-top: 12px; text-align: center; min-height: 16px; line-height: 1.4; }

  .hidden { display: none !important; }

  /* ---------- Tab bar ---------- */
  .tabbar {
    position: fixed; bottom: 0; left: 0; right: 0;
    background: color-mix(in srgb, var(--vellum) 88%, transparent);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    border-top: 1px solid var(--hair);
    display: flex; justify-content: center; gap: 8px;
    padding: 8px 16px calc(8px + env(safe-area-inset-bottom));
    z-index: 50;
  }
  .tabbar button {
    flex: 1; max-width: 160px;
    background: none; border: none; cursor: pointer;
    color: var(--muted); font-size: 11px; font-weight: 600;
    display: flex; flex-direction: column; align-items: center; gap: 3px;
    padding: 6px 0; border-radius: 12px;
    letter-spacing: 0.01em;
    -webkit-tap-highlight-color: transparent;
  }
  .tabbar button .ticon { font-size: 20px; }
  .tabbar button.active { color: var(--accent); }

  .screen { width: 100%; display: flex; flex-direction: column; align-items: center; animation: screenIn var(--dur-2) var(--ease-out); }
  @keyframes screenIn {
    from { opacity: 0; transform: translateY(6px); }
    to { opacity: 1; transform: translateY(0); }
  }
  /* the screen's sections rise in one after the next — a calm cascade on tab
     entry only (these wrappers persist across re-renders, so checking an item
     never replays it). `backwards` holds each section invisible until its turn. */
  .screen > * { animation: screenIn var(--dur-3) var(--ease-out) backwards; }
  .screen > *:nth-child(2) { animation-delay: 40ms; }
  .screen > *:nth-child(3) { animation-delay: 80ms; }
  .screen > *:nth-child(4) { animation-delay: 120ms; }
  .screen > *:nth-child(5) { animation-delay: 160ms; }
  .screen > *:nth-child(n+6) { animation-delay: 200ms; }

  /* ---------- Plans ---------- */
  .plan-card {
    width: 100%; background: var(--card); border: 1px solid var(--border);
    border-radius: 16px; padding: 16px; margin-bottom: 10px;
  }
  .plan-head { display: flex; align-items: center; gap: 10px; }
  .plan-name { font-size: 16px; font-weight: 700; flex: 1; min-width: 0; }
  .status-chip {
    font-size: 9px; text-transform: uppercase; letter-spacing: 0.08em;
    border-radius: 999px; padding: 3px 9px; flex-shrink: 0;
    border: 1px solid var(--border); color: var(--muted);
  }
  .status-chip.active { border-color: var(--done-border); color: var(--accent); background: var(--done-bg); }
  .status-chip.paused { border-color: var(--gold-border); color: var(--warn); }
  .plan-meta { font-size: 12px; color: var(--muted); margin-top: 6px; line-height: 1.5; }
  .plan-bar-wrap { margin-top: 10px; background: var(--bg); border-radius: 999px; height: 8px; overflow: hidden; border: 1px solid var(--border); }
  .plan-bar { height: 100%; background: var(--accent); border-radius: 999px; transition: width 0.4s ease; }
  .plan-bar-lbl { display: flex; justify-content: space-between; font-size: 11px; color: var(--muted); margin-top: 5px; }
  .plan-actions { display: flex; gap: 8px; margin-top: 12px; flex-wrap: wrap; align-items: center; }

  /* Discover cards read as their own thing — a field-journal "specimen label",
     not a generic accent-edge tile. Depth comes from a whisper of TONE (the app's
     own principle), the title is set in the app's signature Fraunces serif, and a
     single hairline rule separates the label header from the body. No colour strip. */
  .discover-card {
    border: 1px solid var(--hair); border-radius: 14px;
    background: linear-gradient(176deg, var(--vellum), color-mix(in srgb, var(--fog) 50%, var(--vellum)));
    box-shadow:
      inset 0 1px 0 color-mix(in srgb, var(--vellum) 65%, transparent),
      0 2px 9px color-mix(in srgb, var(--ink) 6%, transparent);
    transition: transform var(--dur-1) var(--ease-out), box-shadow var(--dur-1) var(--ease-out);
  }
  .discover-card:hover {
    box-shadow:
      inset 0 1px 0 color-mix(in srgb, var(--vellum) 65%, transparent),
      0 6px 18px color-mix(in srgb, var(--ink) 11%, transparent);
  }
  .discover-card:active { transform: scale(0.995); }
  .discover-card .plan-head {
    padding-bottom: 11px; margin-bottom: 11px; border-bottom: 1px solid var(--hair);
  }
  .discover-card .plan-name {
    font-family: 'Fraunces', Georgia, 'Times New Roman', serif;
    font-weight: 500; font-size: 19px; letter-spacing: -0.01em; line-height: 1.2; color: var(--ink);
  }
  .discover-card .status-chip {
    border: none; background: none; padding: 0; text-transform: none; letter-spacing: 0;
    font-family: 'Fraunces', Georgia, serif; font-style: italic; font-size: 12.5px;
    font-weight: 500; color: var(--sage);
  }
  .adopt-btn {
    background: var(--sage); color: var(--on-accent); border: none; border-radius: 999px;
    font-family: inherit; font-size: 13px; font-weight: 700; padding: 9px 18px; cursor: pointer;
    margin-left: auto; -webkit-tap-highlight-color: transparent;
    transition: transform var(--dur-1) var(--ease-out), filter var(--dur-1) var(--ease-out);
  }
  .adopt-btn:hover { filter: brightness(1.05); }
  .adopt-btn:active { transform: scale(0.95); }

  /* ---------- Builder ---------- */
  .field-label { font-size: 11px; text-transform: uppercase; letter-spacing: 0.1em; color: var(--muted); margin: 14px 0 6px; padding-left: 2px; }
  .builder input[type="text"], .builder input[type="date"], .builder input[type="number"], .builder select {
    width: 100%; background: var(--card); border: 1px solid var(--border); border-radius: 12px;
    color: var(--text); font-size: 15px; padding: 12px 14px; outline: none;
    color-scheme: dark;
  }
  .builder input:focus, .builder select:focus { border-color: var(--accent2); }
  .builder { width: 100%; max-width: 520px; }
  .row2 { display: flex; gap: 10px; }
  .row2 > div { flex: 1; }

  .pick-item {
    background: var(--card); border: 1px solid var(--border); border-radius: 14px;
    padding: 11px 14px; display: flex; align-items: center; gap: 12px; margin-bottom: 7px;
    cursor: pointer; user-select: none; -webkit-tap-highlight-color: transparent;
    transition: background 0.15s, border-color 0.15s;
  }
  .pick-item.selected { border-color: var(--accent); background: var(--done-bg); }
  .pick-box {
    width: 22px; height: 22px; border-radius: 7px; border: 2px solid var(--border);
    flex-shrink: 0; display: flex; align-items: center; justify-content: center; font-size: 12px;
  }
  .pick-item.selected .pick-box { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
  .drag-dot { color: var(--muted); font-size: 15px; padding: 6px 4px 6px 0; cursor: grab; touch-action: none; flex-shrink: 0; -webkit-tap-highlight-color: transparent; }
  .drag-ghost {
    position: fixed; z-index: 120; background: var(--card); border: 1px solid var(--accent);
    border-radius: 10px; padding: 8px 14px; font-size: 13px; pointer-events: none;
    box-shadow: var(--shadow-2); opacity: 0.95; max-width: 200px; white-space: nowrap;
    overflow: hidden; text-overflow: ellipsis;
  }
  .drop-hint { outline: 2px dashed var(--accent); outline-offset: 2px; border-radius: 12px; }
  .pick-cat-empty { font-size: 12px; color: var(--muted); border: 1px dashed var(--border); border-radius: 12px; padding: 14px; text-align: center; margin-bottom: 7px; }

  .cadence-select {
    background: var(--bg) !important; font-size: 11px !important;
    padding: 4px 6px !important; border-radius: 8px !important;
    width: auto !important; flex-shrink: 0; max-width: 110px;
    color: var(--muted) !important;
  }

  .emoji-row { display: grid; grid-template-columns: repeat(8, 1fr); gap: 6px; margin-top: 2px; }
  .emoji-opt {
    font-size: 19px; padding: 7px 0; background: var(--bg); text-align: center;
    border: 1px solid var(--border); border-radius: 10px; cursor: pointer;
    transition: border-color 0.15s, background 0.15s;
  }
  .emoji-opt.selected { border-color: var(--accent); background: var(--done-bg); }

  /* Toggle switch */
  .switch {
    width: 46px; height: 27px; border-radius: 999px; flex-shrink: 0;
    background: var(--border); border: none; cursor: pointer; position: relative;
    transition: background 0.2s; padding: 0;
  }
  .switch::after {
    content: ''; position: absolute; top: 3px; left: 3px;
    width: 21px; height: 21px; border-radius: 50%; background: var(--muted);
    transition: transform 0.2s, background 0.2s;
  }
  .switch.on { background: var(--done-bg); }
  .switch.on::after { transform: translateX(19px); background: var(--accent); }

  .reminder-card {
    background: var(--card); border: 1px solid var(--border); border-radius: 14px;
    padding: 14px 16px; display: flex; align-items: center; gap: 14px;
  }
  .reminder-card .rtext { flex: 1; }
  .reminder-card .rname { font-size: 14px; font-weight: 600; }
  .reminder-card .rsub { font-size: 12px; color: var(--muted); margin-top: 2px; line-height: 1.4; }
  .reminder-card input[type="time"] {
    background: var(--bg); border: 1px solid var(--border); border-radius: 10px;
    color: var(--text); font-size: 14px; padding: 8px 10px; outline: none;
    color-scheme: dark; width: auto;
  }
  .reminder-card input[type="time"]:disabled { opacity: 0.35; }

  /* ---------- Calendar heatmap ---------- */
  .heat-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; }
  .heat-month { font-size: 13px; font-weight: 700; letter-spacing: 0.02em; }
  .heat-nav {
    background: transparent; border: 1px solid var(--border); color: var(--muted);
    width: 44px; height: 44px; border-radius: 12px; cursor: pointer; font-size: 17px;
    display: flex; align-items: center; justify-content: center; padding: 0;
    -webkit-tap-highlight-color: transparent;
  }
  .heat-nav:disabled { opacity: 0.25; cursor: default; }
  .heat-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 6px; touch-action: pan-y; }
  .heat-dow { font-size: 10px; color: var(--muted); text-align: center; text-transform: uppercase; letter-spacing: 0.06em; padding-bottom: 2px; }
  /* shrinking-miss heatmap: the CELL is a faint, even container; a centred FILL
     grows with how much of the day you completed. A miss is a small pale dot that
     recedes; a full day fills the tile — so the accumulating green is what the eye
     sees, and a bad day never shouts. 44px tap target is unchanged. */
  .heat-cell {
    aspect-ratio: 1; min-height: 40px; border-radius: 9px;
    border: 1px solid var(--hair);
    background: color-mix(in srgb, var(--ink-soft) 5%, transparent);
    position: relative; cursor: pointer; overflow: hidden;
    -webkit-tap-highlight-color: transparent;
  }
  .heat-cell::before {
    content: ''; position: absolute; left: 50%; top: 50%;
    width: 0; height: 0; transform: translate(-50%, -50%);
    border-radius: 7px; background: var(--accent); opacity: 0;
  }
  .heat-cell.blank { border-color: transparent; background: transparent; cursor: default; }
  .heat-cell.nolog { background: transparent; border-style: dashed; opacity: 0.5; }
  .heat-cell.l0::before { width: 26%; height: 26%; opacity: 0.28; }
  .heat-cell.l1::before { width: 46%; height: 46%; opacity: 0.42; }
  .heat-cell.l2::before { width: 66%; height: 66%; opacity: 0.62; }
  .heat-cell.l3::before { width: 86%; height: 86%; opacity: 0.85; }
  .heat-cell.l4::before { width: 100%; height: 100%; opacity: 1; border-radius: 8px; }
  .heat-cell.hittgt { box-shadow: inset 0 0 0 2px var(--accent); }
  .heat-cell.today { outline: 2px solid var(--dusk); outline-offset: 1px; }
  .heat-cell .dnum {
    position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
    font-size: 12px; color: var(--ink-soft); z-index: 1;
  }
  .heat-cell.l3 .dnum, .heat-cell.l4 .dnum { color: var(--on-accent); font-weight: 700; }
  .heat-legend { font-size: 11px; color: var(--muted); margin-top: 12px; line-height: 1.7; }
  .heat-legend .box { width: 12px; height: 12px; border-radius: 4px; display: inline-block; vertical-align: -2px; margin-right: 2px; }

  /* ---------- Item stats ---------- */
  .istat-row { display: flex; align-items: center; gap: 12px; padding: 9px 0; border-bottom: 1px solid var(--border); }
  .istat-row:last-child { border-bottom: none; }
  .istat-emoji { font-size: 17px; width: 24px; text-align: center; flex-shrink: 0; }
  .istat-name { font-size: 13px; font-weight: 600; flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .istat-bar-wrap { width: 90px; height: 6px; border-radius: 999px; background: var(--bg); border: 1px solid var(--border); overflow: hidden; flex-shrink: 0; }
  .istat-bar { height: 100%; border-radius: 999px; background: var(--accent); }
  .istat-pct { font-size: 12px; color: var(--muted); width: 38px; text-align: right; flex-shrink: 0; }

  /* ---------- Plan wrap-up ---------- */
  .wrapup-card {
    width: 100%; background: linear-gradient(135deg, var(--vellum), var(--vellum));
    border: 1px solid var(--border); border-radius: 16px; padding: 18px; margin-bottom: 12px;
  }
  .wrapup-kicker { font-size: 10px; text-transform: uppercase; letter-spacing: 0.14em; color: var(--accent2); margin-bottom: 6px; }
  .wrapup-title { font-size: 17px; font-weight: 700; }
  .wrapup-line { font-size: 13px; color: var(--text); margin-top: 8px; line-height: 1.6; }
  .wrapup-line b { color: var(--accent); }
  .status-chip.completed { border-color: var(--border); color: var(--accent2); background: var(--vellum); }

  /* ---------- Item notes ---------- */
  .note-btn {
    background: transparent; border: none; cursor: pointer; padding: 6px;
    color: var(--muted); flex-shrink: 0; border-radius: 8px; display: flex;
    align-items: center; justify-content: center;
    -webkit-tap-highlight-color: transparent; position: relative;
  }
  /* invisible expanded hit area — visual stays small, touch target clears 44px */
  .note-btn::after { content: ''; position: absolute; inset: -10px; }
  .note-btn.has-note { color: var(--accent2); }
  .note-btn svg { width: 16px; height: 16px; }
  .item-block { width: 100%; }
  .note-panel {
    background: var(--surface); border: 1px solid var(--border);
    border-radius: 0 0 14px 14px; border-top: none;
    margin: -6px 2px 8px; padding: 14px 16px 12px;
    font-size: 13px; color: var(--text); line-height: 1.6; white-space: pre-wrap;
  }
  .note-panel textarea {
    width: 100%; min-height: 90px; background: var(--bg);
    border: 1px solid var(--border); border-radius: 10px; color: var(--text);
    font-size: 13px; font-family: inherit; line-height: 1.6; padding: 10px 12px;
    outline: none; resize: vertical;
  }
  .note-panel textarea:focus { border-color: var(--accent2); }
  .note-actions { display: flex; gap: 8px; margin-top: 10px; justify-content: flex-end; }
  .note-empty { color: var(--muted); font-style: italic; }

  /* ---------- Me / dashboard ---------- */
  .chart-card {
    width: 100%; max-width: 520px; background: var(--card);
    border: 1px solid var(--border); border-radius: 16px; padding: 16px; margin-bottom: 18px;
  }
  .chart-title { font-size: 11px; text-transform: uppercase; letter-spacing: 0.12em; color: var(--muted); margin-bottom: 12px; }
  .chart-card svg { width: 100%; height: auto; display: block; }

  .screen-title { width: 100%; max-width: 520px; font-size: 20px; font-weight: 700; margin: 4px 0 14px; display: flex; justify-content: space-between; align-items: center; }
  /* toasts are the avatar speaking — a little speech bubble, not a system pill */
  .toast {
    position: fixed; bottom: calc(84px + env(safe-area-inset-bottom)); left: 50%;
    transform: translateX(-50%) translateY(20px);
    background: none; border: none; color: var(--text); padding: 0;
    display: flex; align-items: flex-end; gap: 8px; font-size: 13px;
    opacity: 0; pointer-events: none; transition: opacity 0.25s, transform 0.25s; z-index: 60;
    white-space: normal; max-width: calc(100% - 40px); width: max-content;
  }
  .toast .t-av { flex-shrink: 0; margin-bottom: -3px; }
  .toast .t-bubble {
    position: relative; background: var(--card); border: 1px solid var(--border);
    border-radius: 16px 16px 16px 5px; padding: 10px 16px;
    box-shadow: var(--shadow-2); text-align: left; line-height: 1.5;
  }
  .toast .t-bubble::before {
    content: ''; position: absolute; left: -5px; bottom: 7px; width: 9px; height: 9px;
    background: var(--card); border-left: 1px solid var(--border); border-bottom: 1px solid var(--border);
    transform: rotate(45deg); border-radius: 0 0 0 3px;
  }
  .toast { transition: opacity var(--dur-2), transform 300ms var(--ease-spring); }
  .toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }

  /* ---------- Settings ---------- */
  .settings-card {
    width: 100%; max-width: 520px; background: var(--card);
    border: 1px solid var(--border); border-radius: 16px;
    padding: 4px 16px; margin-bottom: 14px;
  }
  .settings-row {
    display: flex; align-items: center; justify-content: space-between;
    padding: 14px 0; border-bottom: 1px solid var(--border); gap: 12px;
  }
  .settings-row:last-child { border-bottom: none; }
  .settings-row .lbl { font-size: 14px; font-weight: 600; }
  .settings-row .sub { font-size: 12px; color: var(--muted); margin-top: 2px; }
  .settings-row .val { font-size: 13px; color: var(--muted); text-align: right; word-break: break-all; }
  .danger-zone { border-color: var(--vellum); }
  .danger-zone .lbl { color: var(--danger); }
  .danger-divider { width: 100%; max-width: 520px; border-top: 1px solid var(--border); margin: 10px 0 24px; }
  /* full-width destructive button: solid danger fill, white label, 44px+ tall */
  .danger-btn {
    width: 100%; min-height: 48px; background: var(--danger); border: none;
    border-radius: 12px; color: #fff; font-family: inherit; font-size: 15px;
    font-weight: 700; padding: 13px; cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    transition: transform var(--dur-1) var(--ease-out), opacity var(--dur-1);
  }
  .danger-btn:active { transform: scale(0.98); opacity: 0.9; }
  .legal-links { font-size: 12px; color: var(--muted); text-align: center; margin-top: 18px; }
  .legal-links a { color: var(--muted); text-decoration: underline; text-underline-offset: 3px; }
  .forgot-link {
    display: block; text-align: right; font-size: 12px; color: var(--muted);
    background: none; border: none; cursor: pointer; width: 100%;
    margin: -4px 0 8px; text-decoration: underline; text-underline-offset: 3px;
  }

  /* ---------- Onboarding ---------- */
  .onboard {
    position: fixed; inset: 0; z-index: 80; overflow-y: auto;
    background: var(--bg);
    display: flex; flex-direction: column; align-items: center;
    padding: calc(40px + env(safe-area-inset-top)) 20px 48px;
  }
  .onboard h2 { font-size: 24px; margin-bottom: 8px; text-align: center; }
  .onboard .lead { font-size: 14px; color: var(--muted); text-align: center; max-width: 420px; line-height: 1.6; margin-bottom: 26px; }
  .tpl-card {
    width: 100%; max-width: 440px; background: var(--card);
    border: 1px solid var(--border); border-radius: 16px;
    padding: 18px; margin-bottom: 12px; cursor: pointer; text-align: left;
    transition: border-color 0.15s, transform 0.1s;
    color: var(--text); font-family: inherit;
  }
  .tpl-card:active { transform: scale(0.99); }
  .tpl-card:hover { border-color: var(--accent2); }
  .tpl-card .tname { font-size: 16px; font-weight: 700; }
  .tpl-card .tdesc { font-size: 13px; color: var(--muted); margin-top: 4px; line-height: 1.5; }
  .tpl-card .titems { font-size: 12px; color: var(--accent2); margin-top: 8px; }
  .tab-svg { width: 21px; height: 21px; display: block; margin: 0 auto; }

  /* ---------- wizard direction chips ---------- */
  .dir-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 8px; width: 100%; max-width: 440px; }
  .dir-chip {
    background: var(--card); border: 1px solid var(--border); color: var(--text);
    font-family: inherit; font-size: 14px; font-weight: 600; padding: 14px 8px;
    border-radius: 12px; cursor: pointer; -webkit-tap-highlight-color: transparent;
    transition: border-color var(--dur-1), background var(--dur-1), transform var(--dur-1) var(--ease-out);
  }
  .dir-chip:active { transform: scale(0.97); }
  .dir-chip.on { border-color: var(--accent); background: var(--done-bg); color: var(--accent); }

  /* ---------- toast with an action (undo) ---------- */
  .toast button {
    background: none; border: none; color: var(--accent); font-family: inherit;
    font-size: 13px; font-weight: 700; margin-left: 12px; cursor: pointer; padding: 0;
  }

  /* ===================================================================
     FOG THEME — label pass. The all-caps letterspaced labels were the
     single most dated thing in v1. Section headings read as calm
     sentence case; the tiny kickers keep only a hair of tracking.
     Centralized here so it's one reversible block, not 20 edits.
     =================================================================== */
  .section-label, .chart-title, .field-label, .gear-head, .progress-sub,
  .date-badge, .streak-lbl, .heat-dow, .wrapup-kicker, .flip-kicker,
  .trait-label, .gr-for, .gr-head, .idet-stat .l, .sync-pill,
  .badge-reveal-card .bkicker {
    text-transform: none;
    letter-spacing: 0.005em;
  }
  .section-label {
    font-size: 13px; font-weight: 600; color: var(--ink-soft);
  }
  .section-label .mini { font-size: 12px; letter-spacing: 0; }

  /* ---------- The Daily Line — top of Today, above the ring ----------
     Printed on the page, not a widget: no card, no border, no icon.
     Fraunces with the soft axis dialed up makes it read written. */
  .daily-line-wrap {
    width: 100%; max-width: 520px;
    margin: 10px auto 20px;
    padding: 4px 12px 18px;
    border-bottom: 1px solid var(--hair);
    text-align: center;
  }
  .daily-line {
    font-family: 'Fraunces', Georgia, 'Times New Roman', serif;
    font-optical-sizing: auto;
    font-weight: 400; font-style: italic;
    font-variation-settings: 'SOFT' 40, 'WONK' 1, 'opsz' 40;
    font-size: 21px;
    line-height: 1.4;
    color: var(--ink);
    max-width: 34ch; margin: 0 auto;
    letter-spacing: 0.002em;
    /* arrives once, quietly — opacity only, honored by reduced-motion */
    animation: dailyFadeIn 700ms var(--ease-out) both;
  }
  .daily-line .attr {
    display: block; margin-top: 8px; font-style: normal;
    font-family: 'Karla', sans-serif;
    font-size: 13px; font-weight: 500; font-variation-settings: normal;
    color: var(--ink-soft);
  }
  /* the recognition line — milestone / foundation status as text, under the line */
  .recognition-line {
    margin-top: 12px; font-size: 13px; color: var(--ink-soft); line-height: 1.5;
  }
  .recognition-line:empty { display: none; }
  .recognition-line b { color: var(--sage); font-weight: 700; }
  @keyframes dailyFadeIn { from { opacity: 0; } to { opacity: 1; } }
  @media (prefers-reduced-motion: reduce) { .daily-line { animation: none; } }

  /* gear rail on Today (affiliate) — a light section under the habits.
     The rail carries its own FTC disclosure header, so no extra label here. */
  .gear-today { width: 100%; max-width: 520px; margin: 14px auto 0; }

  /* ---------- Today hero: greeting + living ring, on a time-of-day wash ----------
     One composed unit at the top of Today. The gradient shifts with the hour
     (dawn / day / dusk / night) but stays inside the fog palette — atmosphere,
     never a loud banner. */
  .today-hero {
    width: 100%; max-width: 520px; margin: 0 auto 8px;
    border-radius: 24px; padding: 16px 18px 18px;
    display: flex; flex-direction: column; align-items: center;
    position: relative; overflow: hidden;
    background:
      radial-gradient(120% 90% at 30% -10%, var(--hero-a), transparent 60%),
      radial-gradient(120% 90% at 90% 0%, var(--hero-b), transparent 55%),
      var(--vellum);
    border: 1px solid var(--hair);
    box-shadow: var(--shadow-1);
    --hero-a: color-mix(in srgb, var(--sage) 14%, transparent);
    --hero-b: color-mix(in srgb, var(--dusk) 12%, transparent);
  }
  .today-hero.hero-morning { --hero-a: color-mix(in srgb, var(--amber) 16%, transparent); --hero-b: color-mix(in srgb, var(--sage) 15%, transparent); }
  .today-hero.hero-day     { --hero-a: color-mix(in srgb, var(--sage) 15%, transparent);  --hero-b: color-mix(in srgb, var(--dusk) 10%, transparent); }
  .today-hero.hero-evening { --hero-a: color-mix(in srgb, var(--amber) 15%, transparent); --hero-b: color-mix(in srgb, var(--dusk) 18%, transparent); }
  .today-hero.hero-night   { --hero-a: color-mix(in srgb, var(--dusk) 20%, transparent);  --hero-b: color-mix(in srgb, var(--dusk) 12%, transparent); }

  .hero-greet { width: 100%; }
  .hero-greet .greet-card {
    background: none; border: none; box-shadow: none; padding: 0 0 4px;
    display: flex; align-items: center; gap: 12px; margin: 0;
  }
  .hero-greet .greet-hi { font-size: 21px; font-weight: 700; color: var(--ink); letter-spacing: -0.01em; }
  .hero-greet .greet-sub { font-size: 13px; color: var(--ink-soft); margin-top: 2px; }
  .hero-greet .avatar-tap { background: none; border: none; padding: 0; cursor: pointer; -webkit-tap-highlight-color: transparent; }

  /* the living ring, centred — sized so the first habit row stays near the
     fold at 375×812 (the ring is feedback, not the destination) */
  .today-hero .progress-wrap { width: 140px; height: 140px; margin: 6px auto 2px; }
  .today-hero .progress-wrap svg { width: 100%; height: 100%; }
  .progress-label .progress-pct { font-size: 36px; font-weight: 700; color: var(--ink); line-height: 1; letter-spacing: -0.02em; }
  .progress-label .progress-sub { font-size: 12px; color: var(--ink-soft); margin-top: 3px; }

  /* segmented ring — one arc per scheduled habit; filled = done */
  .ring-seg {
    fill: none; stroke: var(--hair); stroke-width: 7; stroke-linecap: butt;
    transition: stroke var(--dur-2) var(--ease-out);
  }
  .ring-seg.done { stroke: var(--sage); }
  /* the segment that just filled gives one calm pulse of light */
  .ring-seg.lit { animation: segLight 620ms var(--ease-out); }
  @keyframes segLight {
    0%   { stroke: var(--sage); stroke-width: 7; filter: drop-shadow(0 0 0 transparent); }
    35%  { stroke-width: 10; filter: drop-shadow(0 0 5px color-mix(in srgb, var(--sage) 70%, transparent)); }
    100% { stroke: var(--sage); stroke-width: 7; filter: drop-shadow(0 0 0 transparent); }
  }
  @media (prefers-reduced-motion: reduce) { .ring-seg.lit { animation: none; } }

  /* momentum section under the daily action — a quiet divider sets it apart */
  .momentum-below { width: 100%; max-width: 520px; margin: 8px auto 0; }

  /* ---------- frozen days — the freeze token, as a cool iceberg tile ----------
     A freeze protects a whole day that landed under the bar. Those day tiles read
     as frosted rather than missed: cool blue, an icy top sheen, the ❄ mark. */
  .hday.frozen {
    background: var(--frost-bg); border-color: var(--frost-border);
    position: relative; overflow: hidden;
  }
  .hday.frozen::before {
    content: ''; position: absolute; inset: 0; pointer-events: none;
    background: linear-gradient(160deg, color-mix(in srgb, var(--frost) 22%, transparent), transparent 55%);
  }
  .hday.frozen .d, .hday.frozen .s { color: var(--frost); position: relative; }
  .wdot.frozen { border-color: var(--frost-border); color: var(--frost); background: var(--frost-bg); }

  /* ---------- per-habit momentum — a habit quietly coming alive ----------
     Growth, not fire (the calm brand bans flame/hype). As a habit's current run
     deepens, the tile takes root: a sage edge that thickens, a faint tint, and a
     small leaf badge carrying the run count. Highest tier breathes, very slightly. */
  /* momentum shows through the growing leaf sprig (below) plus a soft sage light
     that gathers around it on the right — organic, radiating from the sprig, no
     hard edge-bar. Intensity rises with the run. */
  .item.mo-1::after, .item.mo-2::after, .item.mo-3::after {
    content: ''; position: absolute; inset: 0; pointer-events: none;
    background: radial-gradient(130% 150% at 100% 50%,
      color-mix(in srgb, var(--sage) var(--mo, 7%), transparent), transparent 52%);
  }
  .item.mo-1 { --mo: 6%; }
  .item.mo-2 { --mo: 11%; }
  .item.mo-3 { --mo: 17%; }
  .item.done.mo-1::after, .item.done.mo-2::after, .item.done.mo-3::after { display: none; }  /* the done wash owns it */
  /* the leaf badge: a sage sprig + the run count, right-aligned before the note */
  .mo-badge {
    display: inline-flex; align-items: center; gap: 3px; flex-shrink: 0;
    color: var(--sage); font-size: 12px; font-weight: 700; font-feature-settings: 'tnum' 1;
    margin-left: 4px;
  }
  .mo-badge .lf { width: 14px; height: 14px; display: block; }
  .mo-badge .lf .l2, .mo-badge .lf .l3 { opacity: 0; transform-origin: 8px 14px; }
  .item.mo-2 .mo-badge .lf .l2 { opacity: 1; }              /* a second leaf unfurls at 7+ */
  .item.mo-3 .mo-badge .lf .l2, .item.mo-3 .mo-badge .lf .l3 { opacity: 1; }  /* full sprig at 21+ */
  .item.mo-3 .mo-badge .lf { animation: leafBreathe 5.5s var(--ease-out) infinite; }
  @keyframes leafBreathe { 0%,100% { transform: scale(1); } 50% { transform: scale(1.08); } }
  @media (prefers-reduced-motion: reduce) { .item.mo-3 .mo-badge .lf { animation: none; } }

  /* ---------- flip card: hold a stable height so cycling faces don't jump ---------- */
  .flip-wrap .flip-inner { min-height: 128px; }
  .flip-face { min-height: 128px; display: flex; flex-direction: column; }
  .flip-face .flip-line { flex: 1; }

  /* ---------- Foundation card — recognition of what you've actually built ----------
     Cumulative, forgiving, identity-affirming. The number never resets; the copy
     reflects the person's own history back to them. See docs/recognition-framework.md. */
  .foundation-card {
    width: 100%; margin-bottom: 16px; position: relative; overflow: hidden;
    background:
      radial-gradient(120% 100% at 100% 0%, color-mix(in srgb, var(--sage) 12%, transparent), transparent 60%),
      var(--vellum);
    border: 1px solid var(--hair); border-radius: 16px;
    padding: 16px 18px; box-shadow: var(--shadow-1);
    display: flex; gap: 14px; align-items: flex-start;
    animation: dailyFadeIn 600ms var(--ease-out) both;
  }
  @media (prefers-reduced-motion: reduce) { .foundation-card { animation: none; } }
  .foundation-card .fc-avatar { flex-shrink: 0; }
  .foundation-card .fc-body { flex: 1; min-width: 0; }
  .foundation-card .fc-kicker {
    font-size: 11px; color: var(--sage); font-weight: 700; letter-spacing: 0.01em;
    display: flex; align-items: center; gap: 5px; margin-bottom: 6px;
  }
  .foundation-card .fc-kicker .lf { width: 15px; height: 15px; }
  .foundation-card .fc-kicker .lf .l2, .foundation-card .fc-kicker .lf .l3 { opacity: 1; }
  .foundation-card .fc-line { font-size: 15px; line-height: 1.5; color: var(--ink); }
  .foundation-card .fc-line b { color: var(--sage); font-weight: 700; }
  .foundation-card .fc-big {
    font-size: 34px; font-weight: 700; color: var(--sage); line-height: 1;
    letter-spacing: -0.02em; font-feature-settings: 'tnum' 1;
  }
  .foundation-card .fc-sub { font-size: 12px; color: var(--ink-soft); margin-top: 4px; line-height: 1.4; }

  /* ---------- avatar life — blink, breathe, and activity vignettes ----------
     The character mirrors the person's real logged habits (VIGNETTE_OF in
     app.js). All motion is transform/opacity, slow and soft — alive, not
     busy. The global prefers-reduced-motion rule silences all of it. */
  .avatar-svg g { transform-box: view-box; }
  .avatar-svg .av-eyes.av-open { animation: avBlink 4.6s ease-in-out infinite; }
  @keyframes avBlink {
    0%, 93.5%, 97.5%, 100% { transform: scaleY(1); }
    95.5% { transform: scaleY(0.12); }
  }
  .avatar-svg .av-fig { animation: avBreathe 4.8s ease-in-out infinite; }
  @keyframes avBreathe {
    0%, 100% { transform: scale(1); }
    50% { transform: scale(0.997, 1.008); }
  }

  /* lift — a slow, honest dumbbell press */
  .av-vig-lift .av-armL { animation: avLiftL 3s ease-in-out infinite; }
  .av-vig-lift .av-armR { animation: avLiftR 3s ease-in-out infinite; }
  @keyframes avLiftL {
    0%, 12%, 88%, 100% { transform: rotate(0deg); }
    42%, 62% { transform: rotate(150deg); }
  }
  @keyframes avLiftR {
    0%, 12%, 88%, 100% { transform: rotate(0deg); }
    42%, 62% { transform: rotate(-150deg); }
  }
  .av-vig-lift .av-fig { animation: avLiftDip 3s ease-in-out infinite; }
  @keyframes avLiftDip {
    0%, 12%, 88%, 100% { transform: translateY(0); }
    42%, 62% { transform: translateY(1.5px); }
  }

  /* walk — strolling in place, arms swinging opposite */
  .av-vig-walk .av-fig { animation: avStroll 1.8s ease-in-out infinite; }
  @keyframes avStroll {
    0%, 100% { transform: translateY(0) rotate(1.2deg); }
    50% { transform: translateY(-1.6px) rotate(-1.2deg); }
  }
  .av-vig-walk .av-armL { animation: avSwingL 1.8s ease-in-out infinite; }
  .av-vig-walk .av-armR { animation: avSwingR 1.8s ease-in-out infinite; }
  @keyframes avSwingL { 0%, 100% { transform: rotate(13deg); } 50% { transform: rotate(-13deg); } }
  @keyframes avSwingR { 0%, 100% { transform: rotate(-13deg); } 50% { transform: rotate(13deg); } }
  .av-vig-walk .av-mo1 { animation: avMo 1.8s ease-out infinite; }
  .av-vig-walk .av-mo2 { animation: avMo 1.8s ease-out 0.9s infinite; }
  @keyframes avMo {
    0%, 100% { opacity: 0; transform: translateX(3px); }
    40% { opacity: 0.55; transform: translateX(0); }
    80% { opacity: 0; transform: translateX(-4px); }
  }

  /* drink / eat — raise to the mouth, hold, lower; a small head tilt back */
  .av-vig-drink .av-armR { animation: avSip 4.2s ease-in-out infinite; }
  @keyframes avSip {
    0%, 18%, 82%, 100% { transform: rotate(0deg); }
    42%, 60% { transform: rotate(-150deg); }
  }
  .av-vig-drink .av-head { animation: avSipHead 4.2s ease-in-out infinite; }
  @keyframes avSipHead {
    0%, 20%, 80%, 100% { transform: rotate(0deg); }
    44%, 58% { transform: rotate(-5deg); }
  }
  .av-vig-eat .av-armR { animation: avBite 3.6s ease-in-out infinite; }
  @keyframes avBite {
    0%, 20%, 84%, 100% { transform: rotate(0deg); }
    40%, 46%, 56%, 62% { transform: rotate(-138deg); }
    50% { transform: rotate(-132deg); }
  }

  /* sleep — a slow lean with drifting z's */
  .av-vig-sleep .av-head { animation: avDoze 5.5s ease-in-out infinite; }
  @keyframes avDoze {
    0%, 100% { transform: rotate(5deg); }
    50% { transform: rotate(8.5deg); }
  }
  .av-vig-sleep .av-z { opacity: 0; animation: avZ 3.3s ease-out infinite; }
  .av-vig-sleep .av-z2 { animation-delay: 1.1s; }
  .av-vig-sleep .av-z3 { animation-delay: 2.2s; }
  @keyframes avZ {
    0% { opacity: 0; transform: translate(0, 3px); }
    30% { opacity: 0.85; }
    100% { opacity: 0; transform: translate(3px, -7px); }
  }

  /* meditate — floating just off the ground, glow breathing beneath */
  .av-vig-meditate .av-fig { animation: avFloat 5s ease-in-out infinite; }
  @keyframes avFloat {
    0%, 100% { transform: translateY(0); }
    50% { transform: translateY(-3px); }
  }
  .av-vig-meditate .av-glow { animation: avGlow 5s ease-in-out infinite; }
  @keyframes avGlow {
    0%, 100% { opacity: 0.14; transform: scale(0.94); }
    50% { opacity: 0.3; transform: scale(1); }
  }
  .av-vig-meditate .av-tw { animation: avTwinkle 3.4s ease-in-out infinite; }
  .av-vig-meditate .av-tw2 { animation-delay: 1.7s; }
  @keyframes avTwinkle { 0%, 100% { opacity: 0.1; } 50% { opacity: 0.9; } }

  /* read — settled into the page, tiny absorbed nods */
  .av-vig-read .av-head { animation: avRead 6s ease-in-out infinite; }
  @keyframes avRead {
    0%, 100% { transform: rotate(3.5deg); }
    46%, 54% { transform: rotate(5.5deg); }
  }

  /* sun — arms up, rays turning slowly, a gentle bask */
  .av-vig-sun .av-rays { animation: avRays 26s linear infinite; }
  @keyframes avRays { to { transform: rotate(360deg); } }
  .av-vig-sun .av-fig { animation: avBask 5.5s ease-in-out infinite; }
  @keyframes avBask {
    0%, 100% { transform: rotate(-1.5deg); }
    50% { transform: rotate(1.5deg); }
  }

  /* stretch — a full side bend, held, then the other side */
  .av-vig-stretch .av-fig { animation: avStretch 7s ease-in-out infinite; }
  @keyframes avStretch {
    0%, 100% { transform: rotate(-8deg); }
    18%, 32% { transform: rotate(-9.5deg); }
    50% { transform: rotate(8deg); }
    68%, 82% { transform: rotate(9.5deg); }
  }

  /* wave — three friendly waves, a rest, a floating heart */
  .av-vig-wave .av-armR { animation: avWave 3.4s ease-in-out infinite; }
  @keyframes avWave {
    0%, 8%, 44%, 100% { transform: rotate(0deg); }
    14%, 26%, 38% { transform: rotate(14deg); }
    20%, 32% { transform: rotate(-6deg); }
  }
  .av-vig-wave .av-heart { animation: avHeart 3.4s ease-out infinite; }
  @keyframes avHeart {
    0%, 45% { opacity: 0; transform: translateY(3px) scale(0.8); }
    58% { opacity: 0.85; transform: translateY(0) scale(1); }
    100% { opacity: 0; transform: translateY(-6px) scale(0.9); }
  }

  /* ponder — chin in hand, head tilted, the question bobbing overhead */
  .av-vig-ponder .av-head { animation: avPonderHead 4.6s ease-in-out infinite; }
  @keyframes avPonderHead {
    0%, 100% { transform: rotate(-4deg); }
    50% { transform: rotate(-8deg); }
  }
  .av-vig-ponder .av-qcloud { animation: avQBob 3.2s ease-in-out infinite; }
  @keyframes avQBob {
    0%, 100% { transform: translateY(0) scale(1); }
    50% { transform: translateY(-2.6px) scale(1.05); }
  }
  .av-vig-ponder .av-q { animation: avQPulse 3.2s ease-in-out infinite; }
  @keyframes avQPulse { 0%, 100% { opacity: 0.5; } 50% { opacity: 1; } }

  /* the medallion stage — fog banks drift, night stars breathe */
  .avatar-svg .av-mist1 { animation: avMistA 11s ease-in-out infinite; }
  .avatar-svg .av-mist2 { animation: avMistB 14s ease-in-out infinite; }
  @keyframes avMistA { 0%, 100% { transform: translateX(0); } 50% { transform: translateX(4px); } }
  @keyframes avMistB { 0%, 100% { transform: translateX(0); } 50% { transform: translateX(-5px); } }
  .avatar-svg .av-st { animation: avStar 3.8s ease-in-out infinite; }
  .avatar-svg .av-st2 { animation-delay: 1.3s; }
  .avatar-svg .av-st3 { animation-delay: 2.6s; }
  @keyframes avStar { 0%, 100% { opacity: 0.3; } 50% { opacity: 1; } }

  /* ---------- theme picker (Settings) ---------- */
  .theme-picker { display: flex; gap: 8px; }
  .theme-chip {
    width: 40px; height: 40px; border-radius: 12px; cursor: pointer;
    border: 2px solid var(--hair); position: relative; overflow: hidden;
    padding: 0; -webkit-tap-highlight-color: transparent;
    transition: border-color var(--dur-1) var(--ease-out), transform var(--dur-1) var(--ease-out);
  }
  .theme-chip:active { transform: scale(0.92); }
  .theme-chip.on { border-color: var(--sage); }
  .theme-chip .tc-dot { position: absolute; right: 5px; bottom: 5px; width: 11px; height: 11px; border-radius: 50%; }
  .theme-chip[data-t="fog"]  { background: #E9EEEC; }
  .theme-chip[data-t="fog"]  .tc-dot { background: #6E8E7F; }
  .theme-chip[data-t="sage"] { background: #E6EDE0; }
  .theme-chip[data-t="sage"] .tc-dot { background: #5C8460; }
  .theme-chip[data-t="dark"] { background: #1D2523; }
  .theme-chip[data-t="dark"] .tc-dot { background: #8FB0A0; }

  /* ---------- Me tab: the weekly recap chapter ---------- */
  .wr-head { font-size: 15px; font-weight: 700; color: var(--ink); }
  .wr-big { display: flex; align-items: baseline; gap: 8px; margin-top: 6px; }
  .wr-num { font-size: 40px; font-weight: 700; color: var(--sage); line-height: 1; letter-spacing: -0.02em; font-feature-settings: 'tnum' 1; }
  .wr-of { font-size: 13px; color: var(--ink-soft); }
  .wr-dots { display: flex; gap: 7px; margin: 14px 0 4px; }
  .wr-dot {
    flex: 1; aspect-ratio: 1; max-width: 40px; border-radius: 10px;
    display: flex; align-items: center; justify-content: center;
    font-size: 10px; color: var(--ink-soft);
    background: color-mix(in srgb, var(--ink-soft) 6%, transparent); border: 1px solid var(--hair);
  }
  .wr-dot.part { background: color-mix(in srgb, var(--sage) 30%, transparent); border-color: color-mix(in srgb, var(--sage) 22%, transparent); color: var(--ink); }
  .wr-dot.hit { background: var(--sage); border-color: var(--sage); color: var(--on-accent); font-weight: 700; }
  .wr-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 12px; }
  .wr-chip {
    font-size: 11px; font-weight: 600; color: var(--ink-soft);
    background: color-mix(in srgb, var(--ink-soft) 8%, transparent); border-radius: 999px; padding: 4px 10px;
  }
  .wr-chip.up { color: var(--sage); background: color-mix(in srgb, var(--sage) 12%, transparent); }
  .wr-best { font-size: 13px; color: var(--ink-soft); margin-top: 12px; }
  .wr-best b { color: var(--ink); font-weight: 700; }
  .wr-empty { font-size: 13px; color: var(--ink-soft); line-height: 1.5; }

  /* ---------- Me tab: a pattern in your days (Exist-style insight) ---------- */
  .insight-line { font-size: 15px; line-height: 1.55; color: var(--ink); }
  .insight-line b { color: var(--sage); font-weight: 700; }
  .insight-sub { font-size: 12px; color: var(--ink-soft); margin-top: 8px; line-height: 1.4; }

  /* ---------- the journey card: reflection prompt + one optional thought ---------- */
  .journey-prompt { margin-top: 10px; font-size: 13px; color: var(--ink-soft); font-style: italic; line-height: 1.5; }
  .journey-add {
    margin-top: 10px; background: none; border: none; cursor: pointer; padding: 0;
    font-family: inherit; font-size: 13px; font-weight: 600; color: var(--sage);
    -webkit-tap-highlight-color: transparent;
  }
  .journey-note { margin-top: 10px; font-size: 13px; color: var(--ink); line-height: 1.5; }
  .journey-edit {
    background: none; border: none; cursor: pointer; padding: 0 0 0 4px;
    font-family: inherit; font-size: 12px; color: var(--ink-soft); text-decoration: underline; text-underline-offset: 2px;
  }
  .journey-edit-row { margin-top: 10px; display: flex; gap: 8px; align-items: center; }
  .journey-edit-row input {
    flex: 1; min-width: 0; background: var(--bg); border: 1px solid var(--border); border-radius: 10px;
    color: var(--text); font-family: inherit; font-size: 13px; padding: 8px 10px; outline: none;
  }
  .journey-save {
    background: var(--sage); color: var(--on-accent); border: none; border-radius: 10px;
    font-family: inherit; font-size: 13px; font-weight: 700; padding: 8px 14px; cursor: pointer; flex-shrink: 0;
  }
  .flip-face.journeyface, .flip-face.journey-down { cursor: default; }
  .flip-face.journey-down { text-align: center; cursor: pointer; }

  /* ---------- the trip: away card, keepsake, and the trip sheet ---------- */
  .flip-face.journey-away { text-align: left; padding: 16px; }
  .flip-face.journey-away::after { animation-duration: 4.2s; }   /* calmer shimmer while they're out */
  .jaway { display: flex; gap: 14px; align-items: center; }
  .jaway-body { flex: 1; min-width: 0; }
  .jaway .win-tap { font-size: 15px; line-height: 1.3; }
  .jaway .win-sub { margin-top: 4px; font-size: 12px; }
  .jaway-trail, .js-bar {
    position: relative; height: 4px; border-radius: 4px; margin-top: 10px; overflow: hidden;
    background: color-mix(in srgb, var(--ink-soft) 18%, transparent);
  }
  .jaway-trail span, .js-bar span {
    position: absolute; left: 0; top: 0; bottom: 0; border-radius: 4px;
    background: linear-gradient(90deg, color-mix(in srgb, var(--amber) 55%, transparent), var(--amber));
    transition: width 350ms var(--ease-spring);
  }
  .journey-keep { margin-top: 10px; font-size: 13px; color: var(--ink); line-height: 1.5; }
  .journey-keep .jk-lbl { font-size: 11px; font-weight: 700; color: var(--ink-soft); margin-right: 2px; }
  .journey-carry { margin-top: 4px; font-size: 12px; color: var(--ink-soft); line-height: 1.5; }

  .js-hero { display: flex; align-items: center; gap: 14px; margin: 4px 0 12px; }
  .js-av { flex-shrink: 0; }
  .js-kicker { font-size: 12px; color: var(--ink-soft); }
  .js-place { font-family: 'Fraunces', Georgia, serif; font-size: 24px; font-weight: 500; color: var(--ink); line-height: 1.2; }
  .js-why { font-size: 14px; line-height: 1.55; color: var(--ink); }
  .js-trail { margin-top: 14px; }
  .js-bar { height: 6px; }
  .js-times { display: flex; justify-content: space-between; margin-top: 6px; font-size: 12px; color: var(--ink-soft); font-feature-settings: 'tnum' 1; }
  .js-pack { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
  .js-chip {
    font-size: 13px; padding: 6px 10px; border-radius: 999px; border: 1px solid var(--hair);
    background: color-mix(in srgb, var(--sage) 10%, var(--vellum)); color: var(--ink);
  }
  .js-empty { font-size: 13px; color: var(--ink-soft); }
  .js-note { font-size: 12px; color: var(--ink-soft); margin-top: 8px; line-height: 1.5; }
  .js-notify { margin-top: 14px; border-top: 1px solid var(--hair); border-bottom: none; padding-top: 12px; }

  /* ---------- Me tab: the Foundation view — everything you've built ---------- */
  .fv-head { display: flex; align-items: baseline; gap: 8px; }
  .fv-big { font-size: 30px; font-weight: 700; color: var(--sage); letter-spacing: -0.02em; line-height: 1; font-feature-settings: 'tnum' 1; }
  .fv-headsub { font-size: 12px; color: var(--ink-soft); }
  .fv-intro { font-size: 12px; color: var(--ink-soft); margin: 8px 0 6px; line-height: 1.5; }
  .fv-row { display: flex; align-items: center; gap: 10px; padding: 10px 0; border-top: 1px solid var(--hair); }
  .fv-emoji { font-size: 20px; width: 26px; text-align: center; flex-shrink: 0; }
  .fv-name { font-size: 14px; font-weight: 600; color: var(--ink); }
  .fv-meta { font-size: 11px; color: var(--ink-soft); margin-top: 1px; line-height: 1.4; }
  .fv-total { font-size: 17px; font-weight: 700; color: var(--sage); flex-shrink: 0; font-feature-settings: 'tnum' 1; }
  .fv-total span { font-size: 11px; color: var(--ink-soft); font-weight: 600; margin-left: 1px; }

  /* ---------- the one ambient moment — dawn fog drifting behind content ----------
     Two very large, very low-opacity radial gradients on a slow loop. This is the
     ENTIRE wispy budget: the only non-user-triggered motion in the app. No per-card
     entrances, no hover transitions elsewhere. */
  .fog-ambient {
    position: fixed; inset: -20vh -20vw; z-index: -1; pointer-events: none;
    overflow: hidden;
  }
  .fog-ambient::before, .fog-ambient::after {
    content: ''; position: absolute; border-radius: 50%;
    width: 1100px; height: 1100px; filter: blur(8px);
    will-change: transform;
  }
  .fog-ambient::before {
    top: -18%; left: -12%;
    background: radial-gradient(circle, color-mix(in srgb, var(--sage) 6%, transparent), transparent 62%);
    animation: fogDriftA 42s ease-in-out infinite alternate;
  }
  .fog-ambient::after {
    bottom: -22%; right: -14%;
    background: radial-gradient(circle, color-mix(in srgb, var(--dusk) 5%, transparent), transparent 62%);
    animation: fogDriftB 46s ease-in-out infinite alternate;
  }
  @keyframes fogDriftA { from { transform: translate3d(0,0,0) scale(1); } to { transform: translate3d(6vw,4vh,0) scale(1.12); } }
  @keyframes fogDriftB { from { transform: translate3d(0,0,0) scale(1.08); } to { transform: translate3d(-5vw,-3vh,0) scale(1); } }
  @media (prefers-reduced-motion: reduce) {
    .fog-ambient::before, .fog-ambient::after { animation: none; }
  }

  /* ===================================================================
     EDITORIAL BRAND SYSTEM — one voice throughout, drawn from the app's
     own identity rather than a generic accent. Titles are set in Fraunces
     (the display serif); raised surfaces get depth from a whisper of TONE;
     card headers are separated by a single hairline rule; empty states read
     as a written note. Applied late so it unifies every screen.
     =================================================================== */
  .screen-title, .chart-title, .plan-name, .me-head .mh-name,
  .badge-reveal-card .bname, .badge-tile .bname {
    font-family: 'Fraunces', Georgia, 'Times New Roman', serif;
    font-optical-sizing: auto; letter-spacing: -0.01em;
  }
  .screen-title { font-size: 24px; font-weight: 500; }
  .chart-title  { font-size: 15px; font-weight: 500; color: var(--ink); text-transform: none; letter-spacing: -0.005em; }
  .plan-name    { font-weight: 500; font-size: 18px; }
  .me-head .mh-name { font-weight: 500; }
  .badge-reveal-card .bname { font-weight: 500; }
  .badge-tile .bname { font-weight: 500; letter-spacing: 0; }

  /* depth from tone on every raised card (the specimen-label treatment) */
  .chart-card, .settings-card, .reminder-card, .plan-card:not(.discover-card) {
    background: linear-gradient(176deg, var(--vellum), color-mix(in srgb, var(--fog) 45%, var(--vellum)));
    box-shadow:
      inset 0 1px 0 color-mix(in srgb, var(--vellum) 60%, transparent),
      0 2px 8px color-mix(in srgb, var(--ink) 5%, transparent);
  }
  /* a hairline rule under card titles — the editorial header move */
  .chart-card > .chart-title {
    padding-bottom: 11px; margin-bottom: 13px; border-bottom: 1px solid var(--hair);
  }
  /* tier label on a badge reveal: small serif italic, not uppercase-tracked */
  .badge-reveal-card .bkicker {
    font-family: 'Fraunces', Georgia, serif; font-style: italic;
    text-transform: none; letter-spacing: 0; font-size: 13px;
  }
  /* empty states: a written note, not a dashed placeholder box */
  .empty-note {
    font-family: 'Fraunces', Georgia, serif; font-style: italic;
    border-style: solid; border-color: var(--hair); color: var(--ink-soft); font-size: 15px;
  }
