/* ============================================================
   GLOW · SPARK — canonical stylesheet
   Extracted from the source-of-truth prototype: "GLOW Home - Spark.html"
   Ink-on-paper. One living light. Hand-drawn.

   This is the authoritative component CSS for the Spark direction.
   The prototype should import this file so the two never drift.
   The hand-drawn look depends on one SVG filter (#sketch) + grain
   data-URIs; both are reproduced where used. Keep the <filter id="sketch">
   and <filter id="g"> markup in any page that uses .sketch / paper grain.
   ============================================================ */

/* structural mono — the third register (see PART 4) */
@import url('https://fonts.googleapis.com/css2?family=Roboto+Mono:wght@400;500;600&display=swap');

/* ---------- TOKENS ------------------------------------------ */
:root{
  /* Spark v1 is light-only. Declared explicitly so embedded orb/toast
     iframes (also light) always match the embedder — a color-scheme
     MISMATCH makes the browser paint an opaque white canvas behind
     transparent iframes (the "white square" bug). Keep in sync with
     the frame pages in handoff/. */
  color-scheme: light;

  /* Surface — warm near-white paper (locked Jul 2026; was #FBF4EC cream),
     one step off pure white — never #fff, never cool gray */
  --paper:#FEFCFA;          /* base surface */
  --paper-grain:0.05;       /* turbulence alpha baked into .spark-paper */

  /* Ink — one near-black carries ALL text, icons, bars, rules */
  --ink:#1A1714;            /* primary — text, strokes, fills */
  --muted:#6F655A;          /* secondary text, captions, eyebrows */
  --faint:rgba(26,23,20,0.30);  /* tertiary, dividers, todo states */

  /* Ink tints (structural fills — derived from --ink) */
  --ink-13:rgba(26,23,20,0.13); /* track backgrounds */
  --ink-12:rgba(26,23,20,0.12); /* bars, chart gridlines, focus ring */
  --ink-10:rgba(26,23,20,0.10); /* hairline dividers */
  --ink-05:rgba(26,23,20,0.05); /* recovery band / faint wash */
  --ink-18:rgba(26,23,20,0.18); /* heavier section rule */

  /* The Glow — the ONLY color in the system, and it is VARIABLE.
     The UI is monochrome (paper + ink); color lives only in the orb.
     The per-level palette is FINAL and lives ONCE in the ship component
     handoff/GLOW Orb.dc.html (levels() — authority: handoff/HANDOFF.md);
     spark/orb-slot.js mirrors it for flat chrome. Override --glow-1/2/3
     per level on pips / the level bar. Values below = Level 1 (Spark).
     Decorative, never text — and in chrome ONLY where color means level
     identity: the orb itself, the level pips, the level bar fill (--glow-2). */
  --glow-1:#FF6B5C;   /* level center — per-level override */
  --glow-2:#FF5C73;   /* mid          — per-level override */
  --glow-3:#FF4D8A;   /* level outer  — per-level override */
  --ember-hot:#FFB37A;/* ember spark highlight */

  /* Type — three registers (hybrid, locked Jul 2026) */
  --font-display:'Cormorant',Georgia,serif;     /* CEREMONY — italic only */
  --font-body:-apple-system,BlinkMacSystemFont,"SF Pro Text","SF Pro",system-ui,sans-serif; /* SPEECH */
  --font-mono:'Roboto Mono',ui-monospace,'SF Mono',Menlo,monospace; /* STRUCTURE — caps, tracked */

  /* Radius — the system is FLAT. Only pills + the device frame round. */
  --r-pill:9999px;
  --r-frame:54px;

  /* Spacing — Apple HIG 8pt grid (4pt sub-step). All layout lands on these.
     Named by their 4px multiple: --s-2 = 8px, --s-4 = 16px, and so on. */
  --s-1:4px;    /* icon-to-text, hairline gaps */
  --s-2:8px;    /* tight — inside a control */
  --s-3:12px;   /* related items in a row */
  --s-4:16px;   /* DEFAULT — internal padding, list gap */
  --s-5:20px;   /* comfortable */
  --s-6:24px;   /* gap between blocks in a screen */
  --s-8:32px;   /* between distinct sections */
  --s-10:40px;  /* big screen breaks */
  --s-12:48px;  /* major breaks / above a primary CTA */
  --s-16:64px;  /* screen top padding under the notch */

  /* Layout constants (HIG) */
  --screen-pad:24px;  /* horizontal screen margin */
  --hit:44px;         /* minimum tap target — never smaller */

  /* Buttons — one canonical size, plus a sanctioned compact.
     Tokenized so height/padding change in one place. */
  --btn-h:54px;          /* primary CTA height (standard) */
  --btn-h-compact:44px;  /* compact = the min hit target; dense rows / inline */
  --btn-pad:24px;        /* side padding (standard) */
  --btn-pad-compact:20px;/* side padding (compact) */

  /* Motion */
  --ease:cubic-bezier(.23,1,.32,1);
  --dur-view:280ms;     /* screen / panel transitions */
  --dur-quick:160ms;    /* selection states */
  --dur-emotional:640ms;/* emotional reveals — slower than efficient, on purpose */
  --breathe:4s;         /* resting orb */
  --breathe-calm:19s;   /* breathing-exercise orb */
}

/* ---------- PAPER + SKETCH PRIMITIVES ----------------------- */
.spark-paper{
  background-color:var(--paper);
  background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='180' height='180'><filter id='g'><feTurbulence type='fractalNoise' baseFrequency='0.72' numOctaves='2' stitchTiles='stitch'/><feColorMatrix type='saturate' values='0'/><feComponentTransfer><feFuncA type='linear' slope='0.05'/></feComponentTransfer></filter><rect width='180' height='180' filter='url(%23g)'/></svg>");
  background-size:180px 180px;
  color:var(--ink);
  font-family:var(--font-body);
}

/* interactive elements inherit the functional face — without this,
   buttons/inputs fall back to the UA default (Arial) in Chromium */
button, input, select, textarea{ font-family:var(--font-body); }

/* hand-drawn wobble — apply to any monoline svg */
.sketch{ filter:url(#sketch); }
/* QUIET CHROME (locked, Jul 2026): the wobble is for CONTENT —
   in-flow icons, underlines, faces, drawn frames. CHROME renders
   clean: same hand-drawn paths, no displacement. The frame stays
   quiet so content wobble reads as craft, not noise. */
.nav svg.sketch,
.chrome svg.sketch,
.topbar svg.sketch,
.chev.sketch,
.exhead svg.sketch{ filter:none; }
.sketch path,.sketch circle,.sketch line,.sketch polyline,.sketch ellipse,.sketch rect{
  stroke:var(--ink); stroke-width:2; fill:none;
  stroke-linecap:round; stroke-linejoin:round; vector-effect:non-scaling-stroke;
}
.glyph{ display:block; }
.glyph path{ fill:var(--ink); }
/* hand-drawn underline path */
.ul-stroke{ stroke:var(--ink); stroke-width:2.2; fill:none; stroke-linecap:round; }

/* ---------- TYPE ROLES ------------------------------------- */
.display{ font-family:var(--font-display); font-style:italic; font-weight:500; line-height:1.12; }
.body{ font-family:var(--font-body); font-size:14px; line-height:1.5; color:var(--muted); }
.eyebrow{
  display:flex; align-items:center; justify-content:space-between; gap:12px;
  font-size:10.5px; font-weight:600; letter-spacing:0.2em; text-transform:uppercase; color:var(--muted);
}
/* XP is never persistent chrome — it exists only at the moment of
   earning (ship toast / orb absorb / on-Home flash). Resting “+X XP”
   labels stay in markup for JS but never render. */
.eyebrow .xp, .composer .xp{ display:none; }
/* right-side eyebrow metadata that is NOT XP (“since day 1”, counts) */
.eyebrow .meta{ font-weight:500; letter-spacing:0.06em; }

/* ---------- THE ORB ---------------------------------------- */
/* DEPRECATED — legacy CSS orb, kept ONLY for parked reference pages
   (GLOW Home - Spark.html, archive/). Live surfaces mount the SHIP orb:
   handoff/GLOW Orb.dc.html via spark/orb-slot.js. Do not use for new work. */
.glow{ position:relative; width:var(--d); height:var(--d); display:flex; align-items:center; justify-content:center; }
.glow .core{ position:absolute; inset:0; border-radius:50%;
  background:radial-gradient(circle at 50% 50%, var(--glow-1) 0%, var(--glow-2) 26%, var(--glow-3) 46%, rgba(255,77,138,0.34) 60%, rgba(255,77,138,0) 72%);
  animation:breathe var(--breathe) ease-in-out infinite, flicker 2.6s steps(1,end) infinite; will-change:transform,filter; }
.glow .grain{ position:absolute; inset:0; border-radius:50%;
  background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='160' height='160'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/><feColorMatrix type='saturate' values='0'/></filter><rect width='160' height='160' filter='url(%23n)'/></svg>");
  background-size:160px 160px; mix-blend-mode:soft-light; opacity:0.55;
  -webkit-mask-image:radial-gradient(circle at 50% 50%, #000 0%, #000 40%, rgba(0,0,0,0.5) 58%, transparent 70%);
          mask-image:radial-gradient(circle at 50% 50%, #000 0%, #000 40%, rgba(0,0,0,0.5) 58%, transparent 70%);
  animation:breathe var(--breathe) ease-in-out infinite, grainshift 1.1s steps(2,end) infinite; pointer-events:none; }
.glow .grain.fine{ background-size:90px 90px; opacity:0.4; mix-blend-mode:overlay; animation-delay:-0.5s,-0.3s; }
.glow.calm .core{ animation:breathe19 var(--breathe-calm) ease-in-out infinite; }
.glow.calm .grain{ animation:breathe19 var(--breathe-calm) ease-in-out infinite, grainshift 1.4s steps(2,end) infinite; }
.glow .embers{ position:absolute; inset:0; pointer-events:none; }
.ember{ position:absolute; left:50%; top:54%; width:4px; height:4px; border-radius:50%;
  background:radial-gradient(circle,var(--ember-hot) 0%,var(--glow-1) 55%,rgba(255,77,138,0) 100%); opacity:0;
  animation:rise 4.4s ease-in infinite; }
.ember.e2{ animation-duration:5.1s; animation-delay:1.1s; left:46%; }
.ember.e3{ animation-duration:4.6s; animation-delay:2.2s; left:54%; }
.ember.e4{ animation-duration:5.5s; animation-delay:3.0s; left:49%; }
.ember.e5{ animation-duration:4.9s; animation-delay:0.6s; left:52%; }
.glow .label{ position:absolute; inset:0; display:flex; flex-direction:column; align-items:center; justify-content:center; pointer-events:none; }
.glow .label .n{ font-family:var(--font-display); font-style:italic; font-weight:600; line-height:1; }
.glow .label .u{ margin-top:2px; font-family:var(--font-mono); font-size:10px; font-weight:500; letter-spacing:0.24em; text-transform:uppercase; }

@keyframes breathe{ 0%,100%{ transform:scale(0.93);} 50%{ transform:scale(1.06);} }
@keyframes breathe19{ 0%,100%{ transform:scale(0.86);} 33%{ transform:scale(1.12);} 50%{ transform:scale(1.12);} }
@keyframes flicker{ 0%{filter:brightness(1.00);}18%{filter:brightness(1.08);}33%{filter:brightness(0.95);}50%{filter:brightness(1.04);}67%{filter:brightness(0.97);}82%{filter:brightness(1.06);} }
@keyframes grainshift{ 0%{background-position:0 0;}50%{background-position:30px -20px;}100%{background-position:-18px 26px;} }
@keyframes rise{ 0%{opacity:0; transform:translate(-50%,0) scale(0.7);} 12%{opacity:0.9;} 70%{opacity:0.55;} 100%{opacity:0; transform:translate(calc(-50% + var(--drift,8px)), calc(-1 * var(--rise,118px))) scale(0.5);} }
@keyframes viewslide{ from{ transform:translateY(8px);} to{ transform:none;} }
@keyframes viewin{ from{ opacity:0; transform:translateY(6px);} to{ opacity:1; transform:none;} }

/* ---------- MICROCOPY NOTE ROW ----------------------------- */
.note{ display:flex; align-items:center; justify-content:center; gap:8px; font-size:14px; color:var(--muted); line-height:1.4; text-align:center; }
.note svg{ display:block; flex:0 0 auto; }
.note b{ font-weight:600; color:var(--ink); }

/* ---------- LEVEL / PROGRESS BAR --------------------------- */
/* De-colored (editorial pass, Jul 2026): the glow hue lives on the
   orb ONLY. Every bar — including the level track — is ink on paper.
   Level identity is carried by the orb, the pips, and the tier name. */
.level .top{ display:flex; align-items:baseline; justify-content:space-between; }
.level .l{ font-size:15px; font-weight:600; }
.level .xp{ font-size:13px; color:var(--muted); }
.level .xp b{ font-weight:600; color:var(--ink); }
.track{ position:relative; height:5px; margin-top:12px; }
.track .bg{ position:absolute; inset:0; background:var(--ink-13); }
.track .fill{ position:absolute; left:0; top:0; bottom:0; background:var(--ink); }
.track .dot{ position:absolute; top:-3.5px; width:12px; height:12px; border-radius:50%; background:var(--ink); }
/* tiered variant — the home treatment. The tier NAME is the identity
   anchor (Cormorant italic, per the tier-name whitelist); the level
   number demotes to the eyebrow; the ends row reads XP → next tier.
   LEFT-aligned: it lives in the scroll flow — centering is reserved
   for ceremony (see §03 Alignment). */
.level.tiered .lv{ font-size:10.5px; font-weight:600; letter-spacing:0.2em; text-transform:uppercase; color:var(--muted); }
.level.tiered .tier{ font-family:var(--font-display); font-style:italic; font-weight:500; font-size:27px; line-height:1.1; margin-top:4px; }
.level.tiered .track{ margin-top:14px; }
.level.tiered .ends{ display:flex; justify-content:space-between; margin-top:10px; font-size:12.5px; color:var(--muted); }

/* Compact variant — for screens where level is ambient status, not the
   focus (e.g. Home). One quiet row + the track; no XP totals. */
.level.tiered.compact .l{ display:flex; align-items:baseline; gap:10px; white-space:nowrap; }
.level.tiered.compact .tier{ font-size:17px; margin-top:0; }
.level.tiered.compact .track{ margin-top:10px; }

/* ---------- AFFIRMATION / LEDE ----------------------------- */
.affirm{ font-family:var(--font-display); font-style:italic; font-weight:500; font-size:29px; line-height:1.16; }
.lede{ font-size:14px; color:var(--muted); line-height:1.5; }
.qlabel{ font-size:13px; font-weight:600; }

/* ---------- STATEMENT — eyebrow → large serif line --------- */
/* Editorial hero pattern: a body-fact or insight promoted to display
   type instead of caption treatment. Left-aligned, in the scroll flow.
   Markup: .statement > .eyebrow + .line */
.statement .line{ font-family:var(--font-display); font-style:italic; font-weight:500; font-size:30px; line-height:1.16; margin-top:16px; text-wrap:pretty; }

/* ---------- MOOD FACES ------------------------------------- */
.moods{ display:flex; gap:8px; }
.mood{ flex:1; display:flex; flex-direction:column; align-items:center; gap:8px; background:none; border:none; padding:8px 0; cursor:pointer; color:var(--ink); opacity:0.5; transition:opacity var(--dur-quick) ease; }
.mood .face{ position:relative; width:40px; height:40px; }
.mood .ring{ position:absolute; inset:-4px; opacity:0; transition:opacity var(--dur-quick) ease; }
.mood .lbl{ font-size:10px; font-weight:500; }
.mood.on{ opacity:1; } .mood.on .lbl{ font-weight:600; } .mood.on .ring{ opacity:1; }

/* ---------- UNDERLINE-SELECT CHIPS (no boxes) -------------- */
.chips{ display:flex; flex-wrap:wrap; gap:8px 16px; }
.chip{ position:relative; background:none; border:none; padding:4px 0 8px; cursor:pointer; color:var(--ink); font-size:15px; font-weight:400; opacity:0.55; transition:opacity var(--dur-quick) ease; }
.chip .ul{ position:absolute; left:0; width:100%; bottom:0; height:9px; opacity:0; transition:opacity var(--dur-quick) ease; }
.chip.on{ opacity:1; font-weight:500; } .chip.on .ul{ opacity:1; }
.chip.sm{ font-size:14px; }

/* ---------- PRIMARY BUTTON · the ink rectangle ------------- */
/* The committed primary CTA (editorial pass: SQUARE — round is
   reserved for the orb + device frame). Underline means SELECT; a
   filled or outlined RECTANGLE means ACTION — so the two never read
   alike. One filled rectangle is the single true primary per screen;
   .line is secondary. */
.btnx{
  position:relative; display:inline-flex; align-items:center; justify-content:center;
  gap:var(--s-3); min-height:var(--hit); height:var(--btn-h); padding:0 var(--btn-pad);
  background:none; border:none; border-radius:0;
  font-family:var(--font-body); font-size:17px; font-weight:600; line-height:1;
  color:var(--ink); cursor:pointer; -webkit-tap-highlight-color:transparent;
  transition:transform var(--dur-quick) var(--ease);
}
.btnx .cnt{ display:inline-flex; align-items:center; gap:var(--s-3); }
.btnx:active{ transform:scale(0.975); }
.btnx.fill{ background:var(--ink); color:var(--paper); }
.btnx.fill .sketch path{ stroke:var(--paper); }
.btnx.line{ background:none; box-shadow:inset 0 0 0 2px var(--ink); }
.btnx.block{ display:flex; width:100%; }   /* full-width — the default on mobile screens */
/* compact — a dense row / inline secondary. Same shape, smaller box.
   NOT a size ramp: these are the only two button sizes in the system. */
.btnx.compact{ height:var(--btn-h-compact); padding:0 var(--btn-pad-compact); font-size:15px; }

/* ---------- INLINE TEXT ACTION (hand-underlined) ----------- */
/* NOT a primary CTA — reserved for inline / tertiary moves: "See full
   timeline", "Not now", quiet log links. Primary actions use .btnx. */
.cta{ display:flex; align-items:center; gap:12px; background:none; border:none; padding:0; cursor:pointer; color:var(--ink); }
.cta .t{ position:relative; font-size:19px; font-weight:600; white-space:nowrap; }
.cta .t .ul{ position:absolute; left:0; width:100%; bottom:-5px; height:9px; }
.cta svg{ display:block; }
.cta.sm .t{ font-size:16px; }

/* ---------- STAT TRIO -------------------------------------- */
.stats{ display:flex; }
.stats .s{ flex:1; display:flex; flex-direction:column; align-items:center; gap:4px; text-align:center; }
.stats .s .v{ font-family:var(--font-display); font-style:italic; font-weight:600; font-size:30px; line-height:1; }
.stats .s .k{ font-size:9px; font-weight:600; letter-spacing:0.1em; text-transform:uppercase; color:var(--muted); }

/* ---------- CHART LEGEND ----------------------------------- */
.legend{ display:flex; flex-wrap:wrap; gap:8px 16px; }
.leg{ display:inline-flex; align-items:center; gap:8px; background:none; border:none; padding:0; cursor:pointer; color:var(--ink); font-size:12px; opacity:0.45; }
.leg.on{ opacity:1; font-weight:600; }
.leg svg{ display:block; }

/* ---------- EXPANDER ROWS ---------------------------------- */
.exhead{ display:flex; align-items:center; gap:12px; width:100%; background:none; border:none; padding:0; cursor:pointer; text-align:left; color:var(--ink); }
.exhead .ttl{ font-family:var(--font-display); font-style:italic; font-weight:500; font-size:21px; line-height:1.1; }
.exhead .xpbig{ margin-left:auto; text-align:right; }
.exhead .meta{ margin-left:auto; flex:0 0 auto; font-size:12px; font-weight:600; color:var(--muted); }
.exhead .xpbig .v{ font-size:17px; font-weight:700; }
.exhead .xpbig .k{ font-size:9px; font-weight:700; letter-spacing:0.12em; text-transform:uppercase; color:var(--muted); }
.exbody{ display:none; }
.exbody.open{ display:block; animation:viewslide 260ms var(--ease); }

/* ---------- LEVEL PIPS (ladder) ---------------------------- */
.pips{ display:flex; }
.pip{ flex:1; display:grid; grid-template-rows:26px auto auto; justify-items:center; align-content:start; row-gap:8px; position:relative; }
.pip .ln{ position:absolute; top:13px; left:50%; width:100%; height:2px; background:var(--faint); }
.pip .ln.done{ background:var(--ink); }
.pip .dot{ width:26px; height:26px; border-radius:50%; display:flex; align-items:center; justify-content:center; font-size:11px; font-weight:700; z-index:1; }
.pip .dot.done{ background:var(--ink); color:var(--paper); }
.pip .dot.todo{ color:var(--muted); background:var(--paper); box-shadow:inset 0 0 0 2px var(--faint); }
/* legacy flat fallback — live surfaces use .orb-mini (the ship orb's particle
   asset, mounted by spark/orb-slot.js). Kept only for parked reference pages. */
.pip .dot.orb{ background:radial-gradient(circle at 50% 42%, var(--glow-1,#FFB0C4) 0%, var(--glow-2,#FF7AA0) 45%, var(--glow-3,#FF4D8A) 92%); }
.pip .dot.orb.current,.pip .dot.orb-mini.current{ box-shadow:0 0 0 3px var(--ink-12); }
.pip .dot.lock{ background:var(--paper); box-shadow:inset 0 0 0 2px var(--faint); }
.pip .dot.lock svg{ width:15px; height:15px; }
.pip .dot.lock svg path,.pip .dot.lock svg rect{ stroke:var(--muted); }
.pip .nm{ font-size:10px; font-weight:600; }
.pip .dt{ font-size:9px; color:var(--faint); }

/* ---------- XP SOURCE BARS --------------------------------- */
.src{ display:flex; align-items:center; gap:12px; }
.src .nm{ width:92px; flex:0 0 auto; font-size:12px; color:var(--muted); }
.src .bar{ flex:1; height:6px; background:var(--ink-12); overflow:hidden; }
.src .bar i{ display:block; height:100%; background:var(--ink); }
.src .v{ width:42px; text-align:right; flex:0 0 auto; font-size:11px; font-weight:600; }

/* ---------- HEALTH TIMELINE -------------------------------- */
.tl .row{ display:flex; gap:16px; }
.tl .rail{ position:relative; width:18px; flex:0 0 auto; }
.tl .rail .line{ position:absolute; left:8px; top:0; bottom:0; width:2px; background:var(--faint); }
.tl .row:first-child .rail .line{ top:13px; }
.tl .row:last-child .rail .line{ bottom:calc(100% - 13px); }
.tl .rail .node{ position:absolute; left:0; top:4px; width:18px; height:18px; border-radius:50%; display:flex; align-items:center; justify-content:center; }
.tl .rail .node.done{ background:none; }
.tl .rail .node.done .orb-mini{ display:block; }
.tl .rail .node.now{ background:var(--ink); box-shadow:0 0 0 4px var(--ink-12); }
.tl .rail .node.todo{ background:var(--paper); box-shadow:inset 0 0 0 2px var(--faint); }
.tl .body{ flex:1; padding-bottom:16px; }
.tl .body .t{ font-size:10px; font-weight:600; letter-spacing:0.14em; text-transform:uppercase; }
.tl .body .t.todo{ color:var(--muted); }
.tl .body .c{ font-size:13px; margin-top:4px; line-height:1.4; }
.tl .body .c.todo{ color:var(--muted); }

/* ---------- CAPSULE: SEALED ROWS --------------------------- */
.seal{ display:flex; align-items:center; gap:16px; }
.seal svg{ flex:0 0 auto; }
.seal .to{ font-size:13px; font-weight:600; }
.seal .when{ font-size:11px; color:var(--muted); margin-top:2px; }
.seal .opens{ margin-left:auto; font-size:11px; font-weight:500; color:var(--muted); white-space:nowrap; }

/* ---------- FILM STRIP ------------------------------------- */
.film{ display:flex; gap:12px; }
.film .f{ flex:1; aspect-ratio:3/4; display:flex; flex-direction:column; align-items:center; justify-content:center; gap:8px; }
.film .f .d{ font-family:var(--font-display); font-style:italic; font-weight:500; font-size:14px; }
.film .f.add{ color:var(--muted); }
.film .f .frame{ width:100%; height:62%; }

/* ---------- MILESTONE BADGES ------------------------------- */
.badges{ display:flex; gap:16px; }
.badge{ flex:1; display:flex; flex-direction:column; align-items:center; }
.medal{ position:relative; width:100%; aspect-ratio:1; display:flex; flex-direction:column; align-items:center; justify-content:center; }
.medal .ringdeco{ position:absolute; inset:0; width:100%; height:100%; }
.medal .num{ font-family:var(--font-display); font-style:italic; font-weight:600; font-size:24px; line-height:1; }
.medal .dlabel{ font-size:8px; font-weight:700; letter-spacing:0.14em; text-transform:uppercase; color:var(--muted); margin-top:2px; }
.medal .lockico{ width:34%; height:auto; }
.badge.off .num,.badge.off .dlabel{ color:var(--faint); }
/* locked badge: the lock sits centered in the ring, so the label drops
   to the ring's lower inside edge instead of the stack center */
.badge.off .medal .dlabel{ position:absolute; left:0; right:0; bottom:24%; margin-top:0; text-align:center; }

/* ---------- COMMUNITY: TAG FILTER + FEED ------------------- */
.tags{ display:flex; gap:16px; overflow-x:auto; scrollbar-width:none; }
.tags::-webkit-scrollbar{ display:none; }
.tag{ position:relative; flex:0 0 auto; background:none; border:none; padding:4px 0 8px; cursor:pointer; color:var(--ink); font-size:13px; font-weight:400; opacity:0.5; white-space:nowrap; }
.tag .ul{ position:absolute; left:0; width:100%; bottom:0; height:9px; opacity:0; }
.tag.on{ opacity:1; font-weight:600; } .tag.on .ul{ opacity:1; }

/* inline composer prompt — the post affordance lives at the top of the
   feed (X-style), not as a floating button. The whole row is the target. */
.composer{ display:flex; align-items:center; gap:12px; width:100%; background:none; border:none; padding:24px 0; border-bottom:1px solid var(--ink-10); cursor:pointer; text-align:left; color:var(--ink); font-family:inherit; min-height:var(--hit); }
.composer .prompt{ flex:1; font-family:var(--font-display); font-style:italic; font-weight:500; font-size:19px; color:var(--muted); }
.composer .xp{ font-size:11px; font-weight:600; letter-spacing:0.04em; color:var(--faint); white-space:nowrap; }

/* inline reply input — functional face (it's conversation, not a letter),
   hairline underline, compact pill to send */
.replybox{ display:flex; align-items:center; gap:12px; margin-top:14px; }
.replybox input{ flex:1; min-width:0; background:none; border:none; outline:none; border-bottom:1px solid var(--ink-18); border-radius:0; font-family:var(--font-body); font-size:14px; color:var(--ink); padding:6px 0; }
.replybox input::placeholder{ color:var(--faint); }

/* feed list grammar — posts are rows in a list, separated by hairlines
   like every other list in the system */
.feed .post{ padding:32px 0 12px; }
.feed .post + .post{ border-top:1px solid var(--ink-10); }

.post .phead{ display:flex; align-items:center; gap:12px; }
.phead .pmain{ flex:1; }
/* avatar — the GLOW TOKEN, a dedicated community component. Her level orb (ship
   particle asset via ORB.mountToken / .orb-token) with her initial dead-centered
   on top — the core mounts at 1.3x the box so its bright center fills it — level
   identity IS the profile. Sanctioned color-in-chrome: it means level.
   Markup: <span class="av orb-token" data-orb="4" data-d="38"><span class="ini">M</span></span> */
.av{ width:38px; height:38px; flex:0 0 auto; position:relative; display:flex; align-items:center; justify-content:center; }
.av .ini{ position:absolute; font-size:13px; font-weight:600; z-index:1; }
.pwho{ font-size:13px; font-weight:600; }
.pmeta{ font-size:11px; color:var(--muted); margin-top:1px; display:flex; align-items:center; gap:8px; }
.ptext{ font-size:14.5px; line-height:1.55; }
.ptext.dim{ color:var(--muted); }
/* body variants — icon/medal · caption rows */
.prow{ display:flex; align-items:center; gap:16px; }
.prow > svg{ flex:0 0 auto; }
.pmile{ display:flex; align-items:center; gap:16px; }
.pmile .medal{ width:74px; flex:0 0 auto; }
.pmile .big{ font-family:var(--font-display); font-style:italic; font-weight:600; font-size:54px; line-height:1; }
/* level-up: the tier orb IS the visual — level identity carries the glow.
   In the FEED the orb runs at medal scale (data-d="64", matching .pmile's
   74px medal) so the moment reads as shareable, not as a list bullet.
   legacy flat fallback — live surfaces use .orb-mini (ship particle asset). */
.lvlorb{ width:26px; height:26px; border-radius:50%; flex:0 0 auto;
  background:radial-gradient(circle at 50% 42%, var(--glow-1) 0%, var(--glow-2) 45%, var(--glow-3) 92%); }
.psmall{ font-size:11px; font-weight:600; letter-spacing:0.14em; text-transform:uppercase; color:var(--muted); }
.pcap{ font-family:var(--font-display); font-style:italic; font-weight:500; font-size:19px; line-height:1.2; }
.psub{ font-size:12px; color:var(--muted); margin-top:4px; line-height:1.4; }
/* flat reply — 280 chars, no threading (§10.1a) */
.reply{ margin-top:20px; padding-left:14px; border-left:1px solid var(--ink-10); }
.reply .rwho{ font-size:12px; font-weight:600; }
.reply .rwho span{ font-weight:400; color:var(--muted); }
.reply .rtext{ font-size:13.5px; line-height:1.5; margin-top:2px; }
.preact{ display:flex; align-items:center; gap:16px; }
.react{ display:flex; align-items:center; gap:8px; background:none; border:none; padding:0; cursor:pointer; font-size:12px; color:var(--muted); font-weight:500; }
.react.liked{ color:var(--ink); font-weight:600; }
.react svg{ display:block; }

/* ---------- BOTTOM NAV ------------------------------------- */
.nav{ display:grid; grid-template-columns:repeat(5,1fr); padding:12px 16px 32px;
  background:linear-gradient(180deg, rgba(251,244,236,0) 0%, var(--paper) 34%); }
.nav button{ background:none; border:none; padding:8px 0; cursor:pointer; color:var(--ink); display:flex; flex-direction:column; align-items:center; gap:4px; opacity:0.4; }
.nav button .glyph, .nav button svg{ width:27px; height:27px; display:block; }
.nav button .lbl{ font-size:10px; font-weight:500; }
.nav button.active{ opacity:1; } .nav button.active .lbl{ font-weight:600; }

/* selection micro-bloom — the §9.3.4 dopamine tap (subtle, 260ms) */
@keyframes bloom{ 0%{ transform:scale(0.88); } 55%{ transform:scale(1.06); } 100%{ transform:scale(1); } }
.mood.on .face{ animation:bloom 260ms var(--ease); }
.chip.on{ animation:bloom 260ms var(--ease); }

/* ---------- REDUCED MOTION --------------------------------- */
@media (prefers-reduced-motion:reduce){
  .glow .core,.glow .grain,.ember{ animation:none; }
  .mood.on .face,.chip.on,.gscale .b.on .d{ animation:none; }
}

/* ============================================================
   PART 2 — surfaces added with the Progress + check-in build.
   All flat, ink-on-paper, hairline-only. Overlays are square
   (only pills + the frame round).
   ============================================================ */

/* ---------- ADD-DETAIL DISCLOSURE -------------------------- */
.detailtog{ display:flex; align-items:center; gap:8px; background:none; border:none; padding:0; cursor:pointer; color:var(--ink); text-align:left; }
.detailtog .t{ font-size:13px; font-weight:600; }
.detailtog .h{ font-size:12px; color:var(--muted); }
.detail{ display:none; flex-direction:column; gap:16px; }
.detail.open{ display:flex; }
.wlabel{ font-size:11px; font-weight:600; letter-spacing:0.12em; text-transform:uppercase; color:var(--muted); }
.wopts{ display:flex; flex-wrap:wrap; gap:8px 16px; margin-top:8px; }

/* ---------- CHECK-IN SLIDER (gscale) ----------------------- */
/* Bubble fill: five round bubbles fill up to the value — reads as
   intensity and pops as it fills (staggered bloom). Tap a bubble
   or drag across. Starts centered so tuning up or down is
   symmetric; the chosen word lives in the row header (right =
   metadata) — no end labels, no caption. Ink only. */
.qh{ display:flex; align-items:baseline; justify-content:space-between; }
.qh .q{ font-size:15px; font-weight:600; }
.qh .h{ font-size:12px; color:var(--muted); }
.qh .h.val{ font-family:var(--font-display); font-style:italic; font-weight:500; font-size:17px; color:var(--ink); }
.gscale{ display:flex; justify-content:space-between; touch-action:none; cursor:pointer; }
.gscale .b{ width:44px; height:44px; background:none; border:none; padding:0; cursor:pointer; display:flex; align-items:center; justify-content:center; }
.gscale .b .d{ width:21px; height:21px; border-radius:50%; box-shadow:inset 0 0 0 1.5px var(--ink-18); transition:box-shadow var(--dur-quick) ease; }
.gscale .b.on .d{ background:var(--ink); box-shadow:none; animation:bloom 260ms var(--ease); }

/* ---------- LINED TEXTAREA (Cormorant note) ---------------- */
.ta{ width:100%; resize:none; background:none; border:none; outline:none; color:var(--ink);
  font-family:var(--font-display); font-style:italic; font-size:22px; line-height:1.5;
  background-image:repeating-linear-gradient(to bottom, transparent 0, transparent 32px, var(--ink-13) 32px, var(--ink-13) 33px); }
.ta::placeholder{ color:var(--faint); }

/* ---------- SAVINGS: HERO NUMBER + "WHAT YOU COULD BUY" ---- */
.savehero{ display:flex; flex-direction:column; align-items:flex-start; gap:12px; }
.savehero .amt{ font-family:var(--font-display); font-style:italic; font-weight:600; font-size:62px; line-height:0.86; }
.savehero .cap{ font-size:13px; color:var(--muted); line-height:1.45; }
.savehero .cap br{ display:none; }
.buys{ display:flex; flex-direction:column; }
.buy{ display:flex; align-items:center; gap:16px; padding:16px 2px; border-top:1px solid var(--ink-10); }
.buy:last-child{ border-bottom:1px solid var(--ink-10); }
.buy svg{ flex:0 0 auto; }
.buy .txt{ flex:1; font-size:14px; line-height:1.4; }
.buy .txt b{ font-weight:600; }
.buy .price{ font-size:12px; font-weight:600; color:var(--muted); white-space:nowrap; }

/* ---------- STREAK HISTORY ROWS ---------------------------- */
.hist{ display:flex; gap:16px; padding:20px 0; border-top:1px solid var(--ink-10); }
.hist:last-child{ border-bottom:1px solid var(--ink-10); }
.hist .len{ font-family:var(--font-display); font-style:italic; font-weight:600; font-size:34px; line-height:0.9; width:66px; flex:0 0 auto; }
.hist .len small{ display:block; font-family:var(--font-mono); font-style:normal; font-size:9px; font-weight:500; letter-spacing:0.12em; text-transform:uppercase; color:var(--muted); margin-top:4px; }
.hist .meta .when{ font-family:var(--font-mono); text-transform:uppercase; letter-spacing:0.09em; font-size:10.5px; font-weight:500; }
.hist .meta .learn{ font-size:13px; color:var(--muted); line-height:1.45; margin-top:4px; }
.hist .meta .learn em{ font-family:var(--font-display); font-style:italic; font-size:14px; color:var(--ink); }

/* ---------- ONBOARDING COMPONENTS (promoted Jul 2026) -------- */
/* Big chip — the quiz selection: an underline chip at answer scale,
   stacked vertically. Same grammar as .chip (underline = select). */
.bigchip{ background:none; border:none; padding:0; margin:0; cursor:pointer; font-family:var(--font-body); font-size:17px; color:var(--ink); opacity:0.62; position:relative; text-align:left; line-height:1.3; }
.bigchip .ul{ position:absolute; left:0; width:100%; bottom:-7px; height:9px; opacity:0; }
.bigchip.on{ opacity:1; font-weight:500; }
.bigchip.on .ul{ opacity:1; }
.bigchip:active{ transform:scale(0.985); }

/* Commitment contract — ceremonial document: hairline frame, Cormorant
   ≥20px body, one .sigpad. One per flow. */
.contract{ border:1px solid var(--ink-10); padding:32px 24px; }
.contract .ln{ font-family:var(--font-display); font-style:italic; font-weight:500; font-size:22px; line-height:1.45; text-wrap:pretty; }

/* Signature pad — she DRAWS her name: ink on paper, literally.
   Markup: .sigpad > .lb + .redo + canvas + .base (hand-drawn baseline). */
.sigpad{ position:relative; }
.sigpad .lb{ display:block; font-family:var(--font-mono); font-size:10.5px; font-weight:500; letter-spacing:0.09em; text-transform:uppercase; color:var(--muted); }
.sigpad canvas{ display:block; width:100%; height:110px; margin-top:8px; touch-action:none; cursor:crosshair; }
.sigpad .base{ position:absolute; left:0; width:100%; bottom:26px; height:9px; pointer-events:none; }
.sigpad .redo{ position:absolute; right:0; top:0; background:none; border:none; padding:0; cursor:pointer; font-family:var(--font-mono); font-size:10.5px; letter-spacing:0.09em; text-transform:uppercase; color:var(--muted); display:none; }
.sigpad.signed .redo{ display:block; }

/* Plan rows — the hard-paywall subscription choice: radio · name+note ·
   price as right metadata. Uses the system .radio inside. */
.plans{ display:flex; flex-direction:column; }
.plan{ display:flex; align-items:center; gap:16px; width:100%; background:none; border:none; border-bottom:1px solid var(--ink-10); padding:20px 0; margin:0; cursor:pointer; color:var(--ink); text-align:left; font-family:inherit; }
.plan:first-child{ border-top:1px solid var(--ink-10); }
.plan .radio{ flex:0 0 auto; }
.plan .nm{ flex:1 1 auto; font-size:15px; font-weight:500; }
.plan .nm small{ display:block; font-size:12.5px; font-weight:400; color:var(--muted); margin-top:3px; }
.plan .pr{ font-family:var(--font-mono); text-transform:uppercase; letter-spacing:0.09em; font-size:10.5px; color:var(--muted); text-align:right; }
.plan .pr b{ display:block; font-size:13px; font-weight:600; color:var(--ink); letter-spacing:0.05em; }

/* ---------- SOS · DISTRACTION GRID (promoted Jul 2026) -------- */
/* Eight evidence-based craving interruptions (PRD §7.4). Cards are
   square-cornered, hairline-framed; tapping one starts the 3-minute
   wave timer. One grid, two columns on the phone. */
.dgrid{ display:grid; grid-template-columns:1fr 1fr; gap:12px; }
.dcard{ display:flex; flex-direction:column; align-items:flex-start; gap:10px; background:none; border:1px solid var(--ink-10); padding:16px 14px; margin:0; cursor:pointer; color:var(--ink); text-align:left; font-family:inherit; min-height:var(--hit); }
.dcard:active{ transform:scale(0.985); }
.dcard .t{ font-size:14px; font-weight:600; line-height:1.25; }
.dcard .d{ font-size:12px; color:var(--muted); line-height:1.4; }
.dcard svg{ display:block; }

/* the 3-minute wave timer — a ceremonial pause: Cormorant numerals
   over an ink track that drains as the wave passes */
.wavetimer{ display:flex; flex-direction:column; align-items:center; gap:16px; }
.wavetimer .t{ font-family:var(--font-display); font-style:italic; font-weight:500; font-size:56px; line-height:1; color:var(--ink); }
.wavetimer .track{ position:relative; width:200px; height:5px; background:var(--ink-13); }
.wavetimer .track i{ position:absolute; left:0; top:0; bottom:0; background:var(--ink); }

/* ---------- DATE STEPPER ----------------------------------- */
.datepick{ display:flex; align-items:center; justify-content:center; gap:24px; }
.datepick .step{ width:54px; height:54px; border-radius:0; background:none; box-shadow:inset 0 0 0 2px var(--ink); cursor:pointer; color:var(--ink); display:flex; align-items:center; justify-content:center; }
.datepick .step:active{ transform:scale(0.95); }
.datepick .cur{ text-align:center; min-width:150px; }
.datepick .cur .d{ font-family:var(--font-display); font-style:italic; font-weight:600; font-size:30px; line-height:1; }
.datepick .cur .k{ font-family:var(--font-mono); font-size:10.5px; font-weight:500; letter-spacing:0.09em; text-transform:uppercase; color:var(--muted); margin-top:8px; }

/* ---------- TAPPABLE STREAK HERO (opens options) ----------- */
.streakhero{ width:100%; background:none; border:none; padding:0; margin:0; cursor:pointer; color:inherit; font-family:inherit; display:flex; flex-direction:column; align-items:center; }
.streakhero:active{ transform:scale(0.99); }

/* ============================================================
   OVERLAYS — scrim + bottom sheet, full-screen pane, and the
   emotional "sealed" reveal. Elevation = the ONLY shadow in the
   system (a warm lift under the sheet). Everything stays square.
   ============================================================ */
@keyframes fadein{ from{opacity:0;} to{opacity:1;} }

.scrim{ position:absolute; inset:0; z-index:44; background:rgba(26,23,20,0.30); display:none; }
.scrim.on{ display:block; animation:fadein .22s ease; }

.sheet{ position:absolute; left:0; right:0; bottom:0; z-index:45; background:var(--paper);
  box-shadow:0 -1px 0 var(--ink-10), 0 -30px 60px rgba(40,30,10,0.16);
  padding:12px 24px 40px; transform:translateY(100%); transition:transform .34s var(--ease); }
.sheet.on{ transform:none; }
.sheet .grab{ width:40px; height:5px; border-radius:var(--r-pill); background:rgba(26,23,20,0.16); margin:0 auto 22px; }
.sheet h3{ font-family:var(--font-display); font-style:italic; font-weight:500; font-size:27px; line-height:1.1; margin:0; }
.sheet .subx{ font-size:13px; color:var(--muted); margin-top:8px; line-height:1.5; }
.sheetopt{ display:flex; align-items:flex-start; gap:16px; width:100%; background:none; border:none; text-align:left; padding:20px 0; border-top:1px solid var(--ink-10); cursor:pointer; color:var(--ink); font-family:inherit; }
.sheetopt:first-of-type{ margin-top:20px; }
.sheetopt:active{ transform:scale(0.995); }
.sheetopt svg{ flex:0 0 auto; margin-top:2px; }
.sheetopt .t{ font-size:15px; font-weight:600; }
.sheetopt .d{ font-size:12.5px; color:var(--muted); margin-top:3px; line-height:1.45; }
.sheetopt .chev{ margin-left:auto; align-self:center; opacity:0.4; }

.pane{ position:absolute; inset:0; z-index:30; background:var(--paper); display:none; flex-direction:column; padding:64px 24px 40px; }
.pane.on{ display:flex; animation:viewslide 320ms var(--ease); }

.sealed{ position:absolute; inset:0; z-index:35; background:var(--paper); display:none; flex-direction:column; align-items:center; justify-content:center; text-align:center; padding:0 32px; }
.sealed.on{ display:flex; animation:viewslide var(--dur-emotional) var(--ease); }
.sealed .big{ font-family:var(--font-display); font-style:italic; font-weight:500; font-size:34px; line-height:1.15; margin-top:28px; }
.sealed .rec-eb{ font-family:var(--font-mono); font-size:10px; font-weight:500; letter-spacing:0.18em; text-transform:uppercase; color:var(--muted); }
/* Recovery mode · what stays / what softens — structure register, ink hairlines */
.sealed .rec-facts{ width:100%; max-width:272px; margin-top:32px; }
.sealed .rec-facts > div{ display:flex; align-items:baseline; justify-content:space-between; gap:16px; padding:12px 2px; border-top:1px solid var(--ink-10); }
.sealed .rec-facts > div:last-child{ border-bottom:1px solid var(--ink-10); }
.sealed .rec-facts .k{ font-family:var(--font-mono); font-size:10px; font-weight:600; letter-spacing:0.14em; text-transform:uppercase; color:var(--muted); white-space:nowrap; }
.sealed .rec-facts .v{ font-family:var(--font-body); font-size:13px; line-height:1.4; color:var(--ink); text-align:right; }

/* breathing / SOS overlay */
.breath{ position:absolute; inset:0; z-index:40; background:var(--paper); display:none; flex-direction:column; align-items:center; justify-content:center; padding:0 24px; text-align:center; }
.breath.on{ display:flex; animation:viewslide 320ms var(--ease); }
.breath .eb{ font-family:var(--font-mono); font-size:10px; font-weight:500; letter-spacing:0.18em; text-transform:uppercase; color:var(--muted); }
.breath .pass{ font-family:var(--font-display); font-style:italic; font-weight:500; font-size:30px; margin-top:8px; margin-bottom:40px; }
.breath .phase{ position:absolute; font-family:var(--font-display); font-style:italic; font-weight:500; font-size:26px; }
.breath .guide{ font-size:14px; color:var(--muted); margin-top:40px; max-width:260px; line-height:1.6; }

/* ---------- NOVA CHAT -------------------------------------- */
/* You speak in the ink pill (right); Nova answers as plain ink
   on paper — her validating lines in Cormorant italic (voice
   whitelist), everything functional in SF. Flat: no cards. */
.chat{ display:flex; flex-direction:column; gap:14px; align-items:stretch; }
.chat .who{ font-size:11px; font-weight:600; letter-spacing:0.14em; text-transform:uppercase; color:var(--muted); }
.msg{ max-width:86%; font-size:15px; line-height:1.55; color:var(--ink); animation:viewslide 260ms var(--ease); }
.msg.nova{ align-self:flex-start; }
.msg.nova .em{ font-family:var(--font-display); font-style:italic; font-weight:500; font-size:20px; line-height:1.3; }
.msg.user{ align-self:flex-end; background:var(--ink); color:var(--paper); padding:11px 18px; border-radius:var(--r-pill); font-size:14.5px; }
.typing{ display:inline-flex; gap:5px; padding:4px 0; align-self:flex-start; }
.typing i{ width:5px; height:5px; border-radius:50%; background:var(--faint); animation:typebob 1.1s ease-in-out infinite; }
.typing i:nth-child(2){ animation-delay:0.15s; }
.typing i:nth-child(3){ animation-delay:0.3s; }
@keyframes typebob{ 0%,100%{ transform:translateY(0); opacity:0.5; } 40%{ transform:translateY(-3px); opacity:1; } }
.nova-input{ display:flex; gap:12px; align-items:center; margin-top:24px; }
.nova-input input{ flex:1; min-height:var(--hit); border:none; border-bottom:1px solid var(--ink-18); background:transparent; font-family:var(--font-body); font-size:15px; color:var(--ink); outline:none; padding:10px 2px; border-radius:0; }
.nova-input input:focus{ border-bottom-color:var(--ink); }
.nova-input input::placeholder{ color:var(--faint); }


/* ============================================================
   PART 3 — SYSTEM COMPLETION (Apple HIG base, drawn in Spark).
   Semantic color · dark appearance · interaction states ·
   form controls · top bar · page dots · toast · dialog ·
   badges · empty state. Everything stays ink-on-paper, flat,
   hairline-only, square except pills. Loading = the .typing
   dots above (no spinner in the system).
   ============================================================ */

/* ---------- SEMANTIC COLOR (rare, text-safe) ----------------
   The UI stays monochrome; these exist for the few moments ink
   alone can't carry: destructive actions, errors, and (rarely)
   a caution/positive word in dense data. Warm-toned mirrors of
   Apple's system red/green/orange, dark enough for TEXT on
   paper (≥4.5:1). NEVER fills, washes, bars or decoration —
   text + icon stroke only. Success in practice = ink + a check;
   reach for --ok only where a word must read "good" at a glance. */
:root{
  --danger:#A6402E;   /* destructive actions, errors, field errors */
  --ok:#3E6B4F;       /* reserved positive — rare */
  --warn:#8A5312;     /* reserved caution — rare */
}
.t-danger{ color:var(--danger); } .t-ok{ color:var(--ok); } .t-warn{ color:var(--warn); }
.btnx.danger.fill{ background:var(--danger); color:var(--paper); }
.btnx.danger.line{ box-shadow:inset 0 0 0 2px var(--danger); color:var(--danger); }
.btnx.danger.line .sketch path{ stroke:var(--danger); }
.sheetopt.danger .t{ color:var(--danger); }
.sheetopt.danger > svg:first-child path,.sheetopt.danger > svg:first-child rect,
.sheetopt.danger > svg:first-child circle,.sheetopt.danger > svg:first-child line{ stroke:var(--danger); }

/* ---------- DARK APPEARANCE (specified, not shipped) ---------
   v1 ships light-only; this inversion is defined so nothing is
   improvised later. Paper darkens to warm near-black (never
   #000), ink lightens to warm off-white (never #FFF); tints and
   faint re-derive from the light ink; semantics lighten to stay
   text-safe. The orb palette is FINAL and identical in both
   appearances. Opt in with data-appearance="dark" on the root. */
[data-appearance="dark"]{
  --paper:#211B14;
  --ink:#F2E9DE;
  --muted:#A79B8C;
  --faint:rgba(242,233,222,0.30);
  --ink-05:rgba(242,233,222,0.06);
  --ink-10:rgba(242,233,222,0.11);
  --ink-12:rgba(242,233,222,0.13);
  --ink-13:rgba(242,233,222,0.14);
  --ink-18:rgba(242,233,222,0.20);
  --danger:#E08A76; --ok:#8FBF9F; --warn:#D9A15C;
}

/* ---------- INTERACTION STATES (every control) ---------------
   One state grammar across the system:
   · resting   ~0.5 opacity (chips, moods, tags, nav)
   · selected  full ink + weight, plus the control's mark
               (underline / ring / fill) — never a color flash
   · pressed   scale(0.975) pills · scale(0.99) rows, --dur-quick
   · disabled  0.35 opacity, inert — same rule for everything
   · focus     2px ink outline, offset 2 — keyboard only; text
               inputs focus by darkening their underline instead */
:where(button,a,select,[tabindex]):focus-visible{ outline:2px solid var(--ink); outline-offset:2px; }
:where(input,textarea):focus-visible{ outline:none; }
:where(input,textarea):focus{ border-bottom-color:var(--ink); }
:where(button,input,textarea,select):disabled,.is-disabled{ opacity:0.35; pointer-events:none; cursor:default; }
.btnx:disabled{ transform:none; }

/* ---------- TEXT FIELD (labelled) ----------------------------
   The one text input: hairline underline on paper, no box —
   same grammar as the Nova + reply inputs. Label 13/600, help
   in muted; .error swaps the hairline + help line to --danger.
   Cormorant never in a field (the .ta stationery is the one
   ceremonial exception). */
.field{ display:flex; flex-direction:column; }
.field .flabel{ font-size:13px; font-weight:600; }
.field input{ min-height:var(--hit); background:none; border:none; outline:none;
  border-bottom:1px solid var(--ink-18); border-radius:0; padding:10px 2px 8px;
  font-family:var(--font-body); font-size:15px; color:var(--ink); }
.field input::placeholder{ color:var(--faint); }
.field .fhelp{ font-size:12px; color:var(--muted); margin-top:6px; line-height:1.45; }
.field.error input{ border-bottom-color:var(--danger); }
.field.error .fhelp{ color:var(--danger); }

/* ---------- CHECKBOX + RADIO (hand-drawn) --------------------
   Real inputs, visually hidden; the mark is a sketch square /
   circle that follows the selection grammar (resting 0.55 →
   checked full ink + bloom). Row is the tap target (≥44px).
   Markup:
   <label class="check"><input type="checkbox">
     <span class="box"><svg class="sketch" viewBox="0 0 24 24"><rect x="3.2" y="3.2" width="17.6" height="17.6" rx="2"/></svg>
       <svg class="tick sketch" viewBox="0 0 24 24"><path d="M6 12.5l4 4.5 8-10"/></svg></span>
     <span class="lbl2">Label</span></label>
   <label class="radio"><input type="radio" name="g">
     <span class="ring2"><svg class="sketch" viewBox="0 0 24 24"><circle cx="12" cy="12" r="8.8"/></svg><span class="dot2"></span></span>
     <span class="lbl2">Label</span></label> */
.check,.radio,.switch{ position:relative; display:flex; align-items:center; gap:var(--s-3);
  min-height:var(--hit); cursor:pointer; font-size:15px; color:var(--ink); }
.check input,.radio input,.switch input{ position:absolute; opacity:0; width:1px; height:1px; margin:0; }
.check .box,.radio .ring2{ position:relative; width:24px; height:24px; flex:0 0 auto;
  opacity:0.55; transition:opacity var(--dur-quick) ease; }
.check .box svg,.radio .ring2 svg{ position:absolute; inset:0; width:100%; height:100%; overflow:visible; }
.check .box .tick{ opacity:0; }
.check input:checked ~ .box{ opacity:1; }
.check input:checked ~ .box .tick{ opacity:1; animation:bloom 260ms var(--ease); }
.radio .dot2{ position:absolute; left:50%; top:50%; width:11px; height:11px; margin:-5.5px 0 0 -5.5px;
  border-radius:50%; background:var(--ink); transform:scale(0); transition:transform var(--dur-quick) var(--ease); }
.radio input:checked ~ .ring2{ opacity:1; }
.radio input:checked ~ .ring2 .dot2{ transform:scale(1); }
.check input:focus-visible ~ .box,.radio input:focus-visible ~ .ring2,
.switch input:focus-visible ~ .tr{ outline:2px solid var(--ink); outline-offset:3px; border-radius:4px; }

/* ---------- SWITCH (the one toggle) --------------------------
   Apple's 50×30 switch in Spark clothes: ink-tint track, paper
   knob with a hairline; ON fills the track solid ink. A pill —
   sanctioned round. For binary settings only; anything with more
   options is chips or a select row. */
.switch .tr{ position:relative; width:50px; height:30px; flex:0 0 auto; border-radius:var(--r-pill);
  background:var(--ink-13); transition:background var(--dur-quick) ease; }
.switch .tr::after{ content:""; position:absolute; top:3px; left:3px; width:24px; height:24px;
  border-radius:50%; background:var(--paper); box-shadow:inset 0 0 0 1.5px var(--ink-18);
  transition:transform var(--dur-quick) var(--ease); }
.switch input:checked ~ .tr{ background:var(--ink); }
.switch input:checked ~ .tr::after{ transform:translateX(20px); box-shadow:none; }
.switch .lbl2,.check .lbl2,.radio .lbl2{ flex:1; line-height:1.4; }

/* ---------- SELECT / PICKER ROW ------------------------------
   There are no dropdown menus in the system. A select is a row —
   label left, current value + chevron right (metadata column) —
   that opens a BOTTOM SHEET of underline-select options. */
.selrow{ display:flex; align-items:center; gap:var(--s-3); width:100%; min-height:var(--hit);
  background:none; border:none; border-bottom:1px solid var(--ink-10); border-radius:0;
  padding:12px 2px; cursor:pointer; text-align:left; color:var(--ink); font-family:var(--font-body); }
.selrow:active{ transform:scale(0.99); }
.selrow .lbl2{ font-size:15px; }
.selrow .val{ margin-left:auto; font-size:15px; color:var(--muted); }
.selrow > svg{ flex:0 0 auto; opacity:0.4; }

/* ---------- TOP BAR (sub-screens) ----------------------------
   Navigation is flat: five tabs + sub-screens one level deep,
   entered via .pane. The top bar is the way back — chevron
   (44px target) + 17/600 title, left-aligned like everything in
   the flow; optional action in the right (metadata) slot. No
   breadcrumbs — the hierarchy is never deep enough. */
.topbar{ display:flex; align-items:center; gap:var(--s-2); min-height:var(--hit); }
.topbar .back{ display:flex; align-items:center; justify-content:center; width:var(--hit); height:var(--hit);
  margin-left:-14px; background:none; border:none; cursor:pointer; color:var(--ink); }
.topbar .back:active{ transform:scale(0.95); }
.topbar .ttl2{ font-size:17px; font-weight:600; }
.topbar .act{ margin-left:auto; }

/* ---------- PAGE DOTS (onboarding / paged content) ----------- */
.dots{ display:flex; gap:8px; justify-content:center; }
.dots i{ width:7px; height:7px; border-radius:50%; background:var(--ink-18);
  transition:background var(--dur-quick) ease; }
.dots i.on{ background:var(--ink); }

/* ---------- CONFIRMATION TOAST -------------------------------
   The quiet functional confirm ("Note sealed", "Post shared") —
   an ink pill that drops in under the notch and leaves on its
   own (~2s). XP earned is NOT this: XP uses the ship XP toast
   (handoff/GLOW XP Toast.dc.html) via ORB.toast(). */
.toastx{ position:absolute; left:50%; top:70px; transform:translate(-50%,-12px); opacity:0; z-index:60;
  display:flex; align-items:center; gap:8px; padding:12px 20px; border-radius:var(--r-pill);
  background:var(--ink); color:var(--paper); font-size:14px; font-weight:600; pointer-events:none;
  transition:opacity var(--dur-view) var(--ease), transform var(--dur-view) var(--ease); }
.toastx.on{ opacity:1; transform:translate(-50%,0); }
.toastx svg path,.toastx svg circle{ stroke:var(--paper); }

/* ---------- ALERT DIALOG -------------------------------------
   For the rare blocking decision (discard a note? sign out?).
   Square paper card over the scrim, sharing the sheet's one warm
   lift. Title 17/600 + muted body; actions right-aligned as
   compact pills — destructive ones wear .danger. Everything
   else uses the bottom sheet; alerts interrupt, sheets offer. */
.dialog{ position:absolute; left:50%; top:50%; transform:translate(-50%,-50%); z-index:46;
  width:min(320px, calc(100% - 48px)); background:var(--paper); padding:28px 24px 24px;
  box-shadow:0 0 0 1px var(--ink-10), 0 30px 60px rgba(40,30,10,0.16); display:none; }
.dialog.on{ display:block; animation:viewin var(--dur-view) var(--ease); }
.dialog .dt2{ font-size:17px; font-weight:600; line-height:1.3; }
.dialog .db2{ font-size:14px; color:var(--muted); line-height:1.5; margin-top:8px; }
.dialog .da2{ display:flex; justify-content:flex-end; gap:var(--s-3); margin-top:24px; }

/* ---------- NOTIFICATION BADGES ------------------------------
   Ink only — never the glow, never red. A dot means "something
   new"; a count pill carries a number (cap at 9+). Sits on the
   top-right of an icon or as row metadata. */
.ndot{ width:8px; height:8px; border-radius:50%; background:var(--ink); flex:0 0 auto; }
.ncount{ min-width:18px; height:18px; padding:0 5px; border-radius:var(--r-pill); background:var(--ink);
  color:var(--paper); font-size:11px; font-weight:700; display:inline-flex; align-items:center; justify-content:center; }

/* ---------- EMPTY STATE --------------------------------------
   In-flow (left-aligned, like everything that scrolls): a faded
   sketch icon, one Cormorant line that holds space, one muted
   sentence, and at most one compact CTA. Voice rule: an empty
   state is an invitation, never a scold — "nothing here yet"
   framing, always pointing at the first small action. */
.emptyx{ display:flex; flex-direction:column; align-items:flex-start; padding:var(--s-8) 0; }
.emptyx > svg{ opacity:0.45; }
.emptyx .el{ font-family:var(--font-display); font-style:italic; font-weight:500; font-size:22px; line-height:1.2; margin-top:14px; }
.emptyx .es{ font-size:13.5px; color:var(--muted); line-height:1.55; margin-top:6px; max-width:260px; }
.emptyx .btnx{ margin-top:20px; }

/* ============================================================
   PART 4 — TYPE REGISTERS (hybrid, locked Jul 2026)
   Three faces, three non-overlapping jobs:
   · CEREMONY  — Cormorant italic: greetings, numeric reveals, tiers,
     affirmations, milestone captions. Unchanged; scarcity is its power.
   · STRUCTURE — --font-mono, UPPERCASE, tracked 0.09em (eyebrows
     0.18em): the app speaking as an instrument. Eyebrows, labels,
     metadata, values, dates, prices, tags, attributions, chart
     legend/axes, ALL rectangle buttons (.btnx), nav labels.
   · SPEECH    — --font-body sentence case: anything speaking TO or
     AS the user. Tidbits, chips (her own words), notes, captions,
     post bodies, replies, chat, ledes, tertiary/inline actions (.cta).
   Rule of thumb: if a human could say it out loud, it is speech;
   if it names, measures or files something, it is structure.
   ============================================================ */
.eyebrow{ font-family:var(--font-mono); font-size:10px; letter-spacing:0.18em; }
.qlabel, .wlabel{ font-family:var(--font-mono); text-transform:uppercase; letter-spacing:0.09em; font-size:10.5px; font-weight:500; }
/* daily-log row headers: the label NAMES a measure → structure; the
   right-side hint is metadata. The chosen VALUE (.h.val, Cormorant)
   stays ceremony — it's her own state word. */
.qh .q{ font-family:var(--font-mono); text-transform:uppercase; letter-spacing:0.09em; font-size:10.5px; font-weight:500; }
.qh .h{ font-family:var(--font-mono); text-transform:uppercase; letter-spacing:0.09em; font-size:9px; }
.qh .h.val{ font-family:var(--font-display); text-transform:none; letter-spacing:0; font-size:17px; }
.level.tiered .lv{ font-family:var(--font-mono); font-size:10.5px; letter-spacing:0.09em; }
.level .xp{ font-family:var(--font-mono); text-transform:uppercase; letter-spacing:0.09em; font-size:10.5px; }
.stats .s .k{ font-family:var(--font-mono); font-size:10.5px; letter-spacing:0.09em; }
.buy .price{ font-family:var(--font-mono); text-transform:uppercase; letter-spacing:0.09em; font-size:10.5px; }
.tl .body .t{ font-family:var(--font-mono); letter-spacing:0.09em; }
.seal .to{ font-family:var(--font-mono); text-transform:uppercase; letter-spacing:0.09em; font-size:10.5px; }
.seal .when, .seal .opens{ font-family:var(--font-mono); text-transform:uppercase; letter-spacing:0.09em; font-size:9px; }
.film .f .d{ font-family:var(--font-mono); font-style:normal; font-weight:400; text-transform:uppercase; letter-spacing:0.09em; font-size:9px; }
.medal .dlabel{ font-family:var(--font-mono); letter-spacing:0.1em; }
.tag{ font-family:var(--font-mono); text-transform:uppercase; letter-spacing:0.09em; font-size:10.5px; }
.pwho{ font-family:var(--font-mono); text-transform:uppercase; letter-spacing:0.09em; font-size:10.5px; }
.pmeta, .psmall{ font-family:var(--font-mono); text-transform:uppercase; letter-spacing:0.09em; font-size:9px; }
.react, .pact{ font-family:var(--font-mono); text-transform:uppercase; letter-spacing:0.09em; font-size:10.5px; }
.reply .rwho, .reply .rwho span{ font-family:var(--font-mono); text-transform:uppercase; letter-spacing:0.09em; font-size:9px; }
.chat .who{ font-family:var(--font-mono); letter-spacing:0.14em; font-size:10px; }
.nav .lbl{ font-family:var(--font-mono); text-transform:uppercase; letter-spacing:0.1em; font-size:8.5px; }
/* buttons are ONE family — filled + outlined rectangles both speak the
   structural register; hierarchy comes from the fill, not the face.
   Tertiary/inline (.cta) stays speech. */
.btnx{ white-space:nowrap; }
.btnx .cnt, .btnx{ font-family:var(--font-mono); text-transform:uppercase; letter-spacing:0.09em; font-size:13px; font-weight:500; }
.btnx.compact{ font-size:12px; }
/* wellness chart chrome (component injects its own DOM) */
.wellness-chart .wc-rsw, .wellness-chart .wc-leg{ font-family:var(--font-mono); text-transform:uppercase; letter-spacing:0.09em; }
.wellness-chart svg text{ font-family:var(--font-mono); letter-spacing:0.06em; text-transform:uppercase; }
/* tertiary / inline action (.cta) — SPEECH register: the flow's voice
   offering an optional continuation. SF sentence case, never mono,
   never uppercase; the hand-drawn underline marks it where it stands
   alone (e.g. "See full timeline"). */
.cta .t{ font-family:var(--font-body); font-weight:500; font-size:14px; }
.cta.sm .t{ font-size:13px; }
/* Home: “Tap to open” micro-label — child combinator ONLY: the envelope
   component reuses `open` as a STATE class on .nova-env, so a descendant
   selector here would leak mono onto the wax ✶ and spark glyphs */
.nova .open > span, #nova-teaser .open > span{ font-family:var(--font-mono); text-transform:uppercase; letter-spacing:0.09em; font-size:10.5px; }
