@font-face{font-family:"Supermassive RS";src:url("/fonts/supermassive-rs.woff2?v=052a498d") format("woff2");font-weight:400;font-display:swap}
@font-face{font-family:"General Sans";src:url("/fonts/general-sans.woff2?v=49d3fbd2") format("woff2");font-weight:200 700;font-display:swap}
:root{
  --tapmin:64px;
  --ink:#0B0A0A; --surface:#141111; --raise:#1C1818; --hair:#2A2523; --hair2:#1E1A19;
  --bone:#E9E3DA; --dim:#A0958C; --quiet:#8A8079; --deco:#5A524D;
  --oxblood:#8E2F39; --oxblood-t:#CF5C68; --ember:#C4622D; --brass:#9A7B4F;
  --ochre:#B8912F; --violet:#8E79AE; --slate:#7098B8; --moss:#6F9A7B; --rose:#C06A7E;
  --grey:#A7ADB4; --teal:#7BAcC0; --rust:#B4664A; --gold:#C0A15A;
  --nav:#0E0C0C; --nav-on:#3A2115; --sel-ink:#0B0A0A;
  --s-limit:#D4545E; --s-no:#8F857C; --s-cur:#E0A93A; --s-yes:#B4C55E; --s-crave:#63C07C;
  --gut:clamp(18px,4.4vw,64px); --navh:56px;
  --tap:64px;
}
*{box-sizing:border-box;margin:0;padding:0}
html{-webkit-text-size-adjust:100%}
body{background:var(--ink);color:var(--bone);font-family:"General Sans",system-ui,sans-serif;font-weight:340;letter-spacing:.011em;
  line-height:1.5;-webkit-font-smoothing:antialiased;overflow-x:hidden;
  padding-bottom:calc(var(--navh) + env(safe-area-inset-bottom,0px))}
.sm{font-family:"Supermassive RS","General Sans",sans-serif;font-weight:400;letter-spacing:-.03em !important;line-height:.86;text-transform:uppercase}
button{font:inherit;color:inherit;background:none;border:none;cursor:pointer;text-align:left}
.mono{font-variant-numeric:tabular-nums;letter-spacing:.14em;text-transform:uppercase;font-size:10.5px;color:var(--quiet)}
:focus-visible{outline:2px solid var(--bone);outline-offset:2px}
::selection{background:var(--bone);color:var(--ink)}
@media(prefers-reduced-motion:reduce){*,*::before,*::after{transition-duration:.01ms !important;animation-duration:.01ms !important}}
.vh{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}

/* ---- persistent bottom nav ---- */
.nav{position:fixed;left:0;right:0;bottom:0;z-index:60;display:flex;background:var(--nav);
  border-top:1px solid var(--hair);padding-bottom:env(safe-area-inset-bottom,0px)}
.nav button{flex:1;min-height:var(--navh);display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;
  font-size:10px;letter-spacing:.1em;text-transform:uppercase;color:var(--dim);
  border-right:1px solid var(--hair);transition:color .2s,background .2s}
.nav button:last-child{border-right:none}
/* a 16px dash was too small to read as "you are here", so the whole tab lights
   up instead and the bar runs the full width of it */
.nav button[aria-current=page]{color:var(--bone);background:var(--nav-on);
  box-shadow:inset 0 2px 0 var(--ember)}
.nav i{width:16px;height:2px;background:currentColor;opacity:.5}
.nav button[aria-current=page] i{opacity:0}

.stage{display:none}.stage.on{display:block}

/* ================= ENTRY ================= */
.entry{padding:calc(var(--gut) + env(safe-area-inset-top,0px)) var(--gut) 30px;display:flex;flex-direction:column;min-height:calc(100vh - var(--navh));min-height:calc(100svh - var(--navh))}
.wordmark{font-size:clamp(60px,20vw,232px);margin:.2em 0 0;line-height:.8}
.wordmark span{color:var(--oxblood-t)}
.blurb{max-width:36ch;color:var(--dim);font-size:15.5px;margin-top:20px}
.blurb b{color:var(--bone);font-weight:500}
.doors{margin-top:34px}
/* any explicit display beats the UA rule for [hidden], which silently left
   both entry doors on screen at once. This has to win over every such rule. */
[hidden]{display:none !important}
.door{display:block;width:100%;padding:20px 0;border-top:1px solid var(--hair);position:relative;min-height:var(--tap)}
.door:last-child{border-bottom:1px solid var(--hair)}
.door h3{font-size:18px;font-weight:500}
.door p{font-size:13.5px;color:var(--dim);margin-top:3px;max-width:44ch}
.door .tag{position:absolute;right:0;top:22px;font-size:9.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--quiet)}
.vow{margin-top:30px;display:grid;gap:18px}
.vow p{font-size:12.5px;color:var(--dim);line-height:1.55;max-width:40ch}
.vow strong{display:block;color:var(--bone);font-weight:500;letter-spacing:.1em;text-transform:uppercase;font-size:9.5px;margin-bottom:4px}

/* Returning-visitor language offer: a single quiet line, never a modal, so it
   can never cover content or trap focus. Sits in normal document flow at the
   top of the entry screen, pushing the doors down by one row when it shows
   rather than overlaying them; [hidden] above already forces display:none
   regardless of the flex below. */
.langoffer{display:flex;flex-wrap:wrap;align-items:center;justify-content:center;
  gap:2px 22px;padding:4px var(--gut);text-align:center;
  border-bottom:1px solid var(--hair);background:var(--surface)}
.langoffer button{min-height:var(--tapmin);padding:0 2px;font-size:12.5px;
  text-decoration:underline;text-underline-offset:3px}
.langoffer__link{color:var(--bone)}
.langoffer__dismiss{color:var(--quiet)}

/* The entry screen's own permanent language control, below the doors: reuses
   .settings/.langs exactly as the results screen does, so it needs no rules
   of its own beyond spacing this instance slightly tighter than a full
   section break, since it is one small control among several on this
   screen, not its own heading-led block. */
.entry__b .settings{margin-top:24px}

/* Asset URLs are content hashed and served immutable for a year. Never fetch
   a NEW hash URL before the deployment serving it is live: Pages answers the
   miss with the catch-all page, and that HTML then sticks at the asset URL. */
/* ================= DECK ================= */
/* The complaint was "you have to scroll down to complete each question". So the
   answer controls are pinned: the scale, the refinements and Next are always on
   screen, and only the name and definition scroll, and only when a long one on a
   short screen actually needs it. In a browser with its own chrome showing, that
   is the difference between reaching Next and hunting for it. */
.deck{display:flex;flex-direction:column;height:calc(100vh - var(--navh));
  height:calc(100svh - var(--navh))}
/* The question itself never scrolls. Only the definition does, and only when a
   long one on a short screen needs it, so the activity name can never end up
   half cut off at the top of its own scroll box. */
/* not overflow:hidden: the display face runs at line-height .86, so its
   ascenders sit above their own text box and a clipping parent shears the
   tops off the activity name. Only .define needs to clip. */
/* The card sizes itself from the height it is actually given, rather than from
   fixed pixel blocks that happen to add up on the phones I own. Space is given
   up in a deliberate order: the definition shrinks and scrolls first, then the
   five positions shrink but never below a 44px touch target, and only if that
   still will not fit does the whole card scroll. That last part is the safety
   net: a control can never end up unreachable on a screen I have not tested,
   which is exactly what was reported on a 14 Pro. */
.deck{overflow-y:auto;-webkit-overflow-scrolling:touch}
/* Every block above .rest now sizes itself from its own content: the question,
   the segmented control and its one reserved line, and the parked toggle are
   all a fixed, known height, none of it stretchy any more now the five rows
   are a compact row instead of five flexible ones. .rest is what actually
   grows to soak up whatever is left, so the refinements and Next stay docked
   near the foot of the card on a tall screen instead of a dead gap opening up
   above the segmented control; on a short screen .rest simply holds its floor
   and the card scrolls, same safety net as before. */
.deck__body{display:flex;flex-direction:column}
/* the question never shrinks: it is the thing being asked */
.deck__body .activity{flex:none}
.define{flex:1 1 auto;min-height:0;overflow-y:auto;-webkit-overflow-scrolling:touch}
.deck__top,.dunno,.quals,.act,.stances{flex:none}
.deck__top{padding:calc(10px + env(safe-area-inset-top,0px)) var(--gut) 0;position:sticky;top:0;background:var(--ink);z-index:20;border-bottom:1px solid var(--hair2)}
/* wears the colour of the category you are in, so the way back is the one
   coloured thing on a dark screen and doubles as a reminder of where you are */
.jump{display:flex;align-items:center;gap:9px;min-height:46px;padding:0 15px;margin-bottom:10px;
  width:100%;border:1px solid var(--c);background:var(--c);color:var(--ink);
  font-size:13px;font-weight:500;letter-spacing:.01em}
.jump::before{content:"";width:7px;height:7px;border-left:1.5px solid currentColor;border-bottom:1.5px solid currentColor;transform:rotate(45deg);flex:none}
.jump:hover{filter:brightness(1.12)}
.jump:active{filter:brightness(.94)}
.crumb{display:flex;align-items:baseline;gap:10px;margin-bottom:5px}
.crumb b{font-size:13px;font-weight:500;letter-spacing:.01em}
.crumb span{font-size:11px;color:var(--quiet);font-variant-numeric:tabular-nums;margin-left:auto;line-height:1.2}
/* the filled bar needs something to be filling, or an early item just shows
   a stray dash floating at the left edge */
.chunkwrap{height:2px;background:var(--hair);margin-bottom:6px}
.chunk{height:2px;background:var(--c);max-width:100%}

/* flex-start, not center: a centred flex child that overflows gets pushed out
   past the top of its own scroll box, which hid the activity name. */
.deck__body{padding:10px var(--gut) 0;display:flex;flex-direction:column;
  justify-content:flex-start}
/* Before an answer, .rest was the only thing that could grow, so every spare
   pixel on a tall phone piled up as one dead gap just above the action row.
   Growing (never shrinking: shrink stays 0, exactly as before) lets the
   definition/selector block share that slack with .rest instead of dumping
   it all at the bottom, while the title itself stays exactly where it was,
   pinned to the top of this same box by justify-content:flex-start above. */
.deck__body{flex:1 0 auto}
.activity{font-size:clamp(28px,7.6vw,44px);max-width:16ch}
.define{font-size:13.5px;color:var(--dim);margin-top:9px;max-width:52ch;line-height:1.45}
.define button{display:inline-block;color:var(--bone);border-bottom:1px solid var(--quiet);font-size:13px;line-height:1.35}
.define .more{margin-top:10px;min-height:44px;display:flex;align-items:center;border-bottom:none;color:var(--bone);font-size:13px}
.define .more::after{content:"";display:inline-block;width:22px;height:1px;background:var(--quiet);margin-left:9px}

/* One horizontal ramp, hard limit to crave, instead of five stacked rows: the
   five positions read as one spectrum rather than a list to work down. The
   segments carry no text of their own (bar a very faint X/heart on the two
   ends, see .stance__glyph), colour plus an inset ring says which is chosen,
   and the name and description that used to live inside the row now live in
   the one reserved line underneath, so every card, answered or not, shows
   exactly one line of help there and never reflows. Limit/Love used to flank
   the track and eat width from it; they sit on their own line above it
   instead, so all five segments run the full card width. */
.stances{padding:10px var(--gut) 0}
.stances__row{display:flex;flex-direction:column;gap:7px}
.stances__scale{display:flex;justify-content:space-between}
.stances__scale span{font-size:9.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--quiet)}
.stances__track{display:flex;gap:4px;width:100%}
/* --raise on --ink read as near-black on black: the five unclaimed segments
   barely registered as separate targets. A visibly lighter fill and a border
   with real contrast fix that without borrowing any of the selected look
   (solid stance colour plus an inset ring). */
.stance{position:relative;flex:1;height:58px;min-height:44px;background:#252020;border:1px solid #4A4038;
  transition:background .16s,border-color .16s,transform .16s}
.stance:hover{background:#2E2828}
/* fill plus an inset ring, never colour alone, so selection reads even for a
   colour-blind viewer or in a washed-out screenshot */
.stance[aria-checked=true]{background:var(--k);border-color:var(--k);
  outline:2px solid rgba(11,10,10,.55);outline-offset:-5px;transform:translateY(-3px)}
/* Same inert-but-tappable treatment as the split tracks (see
   .stances__strack.is-na) for the single main track, when a nondirectional
   item is marked not applicable. */
.stances__track.is-na .stance{opacity:.32}
.stances__track.is-na .stance:hover{opacity:.55}
/* The hard-limit X and the crave heart: a hint of what each end of the scale
   means, faint enough to read as texture rather than a label, and white so it
   reads the same whether the segment is still unclaimed or filled with its
   own stance colour once selected. */
/* Sized off each track's own height, the smaller of a segment's two
   dimensions at every width in the supported range (58px main track, 44px
   split track), never off its width, which varies with viewport and column
   count. ~59% of that height either way, just two fixed sizes rather than
   true per-element math, which plain CSS has no way to express. */
.stance__glyph{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);
  width:34px;height:34px;opacity:.18;pointer-events:none}
.stances__strack .stance__glyph{width:26px;height:26px}
.stances__desc{margin-top:10px;min-height:2.8em;font-size:12.5px;color:var(--quiet);line-height:1.4}

/* Two shorter tracks, one per side, sharing one Limit/Love scale line between
   them rather than repeating it. Same colours, same behaviour as the single
   track, just 44px tall instead of 58px, which is what buys back the room a
   second full row needs inside the same card that used to hold one. Shown
   for every directional item from the moment the card opens (see
   app.js's updateStancesUI): there is no longer a toggle between this and
   the single track above, only which of the two a given item ever uses. */
.stances__srow{display:flex;flex-direction:column;gap:5px;margin-top:9px}
.stances__srow:first-child{margin-top:8px}
/* Giving/Receiving are the whole point of this layout, so they read bright
   against the muted Limit/Love scale above them: brightness carries the
   emphasis, the size stays the same small label size. */
.stances__slabel{font-size:9.5px;letter-spacing:.1em;text-transform:uppercase;color:var(--bone);font-weight:500}
.stances__srowhead{display:flex;align-items:baseline;justify-content:space-between;gap:8px}
/* Compact "N/A" text, but never a near-invisible one: an underline gives it
   an obvious link affordance at a glance, while colour keeps it visually
   secondary to the bright Giving/Receiving label beside it. The ::before
   pseudo-element is the actual 44px tap target (Ryan's touch-target rule),
   painted with no visible box of its own, so the compact link look on
   screen never has to fight a genuinely large hit area. */
.na-toggle{position:relative;flex:none;font-size:11px;font-weight:600;
  letter-spacing:.03em;text-transform:uppercase;color:var(--dim);
  text-decoration:underline;text-decoration-color:var(--quiet);text-underline-offset:3px;
  line-height:1;padding:4px 2px}
.na-toggle::before{content:"";position:absolute;inset:-16px -12px}
.na-toggle:hover{color:var(--bone);text-decoration-color:var(--bone)}
/* Marked: flips to a filled pill, unmistakably closed out rather than merely
   a slightly darker link. */
.na-toggle[aria-pressed="true"]{color:var(--ink);background:var(--bone);
  text-decoration:none;border-radius:3px;padding:4px 8px}
.stances__strack{display:flex;gap:4px;width:100%}
.stances__strack .stance{height:44px}
/* The five segments stay tappable (never pointer-events:none) so a change of
   mind is one tap away, but read as inert once 'na' has closed the row out:
   nothing here is claiming a position on the scale any more. */
.stances__strack.is-na .stance{opacity:.32}
.stances__strack.is-na .stance:hover{opacity:.55}

.dunno{margin:10px var(--gut) 0;min-height:44px;width:calc(100% - (2 * var(--gut)));
  display:flex;align-items:center;gap:10px;padding:8px 14px;font-size:12.5px;
  border:1px dashed var(--hair);color:var(--dim);font-size:13px}
.dunno:hover:not([aria-pressed="true"]){color:var(--bone);border-color:var(--quiet)}
.dunno[aria-pressed="true"]{color:var(--ochre);border-style:solid;border-color:var(--ochre);background:#171208}
/* Not applicable sits directly under "not sure yet", same dashed-border
   family, but marked in bone rather than parked's ochre: a resolved "does
   not apply" must never read as the same state as an unresolved "come back
   to this". */
.dunno--na{margin-top:6px}
.dunno--na[aria-pressed="true"]{color:var(--ink);border-style:solid;border-color:var(--bone);background:var(--bone)}
.rest{flex:1 1 auto;min-height:26px}

/* qualifiers sit on the card permanently, no gating class */
/* The side and the flags refine an answer, so they arrive with one. Before you
   have chosen, that space belongs to the definition, which is the thing people
   said they valued most. Next stays put either way. */
/* .act is sticky, not fixed, so it is already a real participant in .deck's
   flow; on a tall card that never needs to scroll it simply sits after this
   row with nothing else to fix. The bug was specific to a short card: once
   .deck's content overflows even slightly, sticky glues .act to the visible
   bottom edge for the ENTIRE scroll range, including scrollTop:0, so the tail
   of .quals renders underneath it rather than above it, unreachable, until
   .deck happens to have exactly enough natural overflow to clear it (it
   rarely does). --act-h, set from .act's own measured height (app.js,
   syncActClearance), reserves that exact amount of extra scroll room below
   .quals so scrolling the card fully always leaves .quals completely clear
   of .act, on every viewport, not just the ones with enough overflow to have
   accidentally worked already. The 70px fallback only covers the first paint
   before that measurement lands; --act-h supersedes it immediately after. */
.quals{padding:10px var(--gut) var(--act-h,70px);display:grid;gap:8px}
/* Pinned to the foot of the card. On a small phone the content genuinely
   cannot all fit at 44px minimums, so it scrolls, but the way to move on
   must never be the thing that scrolls out of reach. This is what the 14
   Pro report was about, and it bites hardest on an SE. */
.act{display:flex;gap:10px;padding:10px var(--gut) calc(12px + env(safe-area-inset-bottom));
  flex:none;position:sticky;bottom:0;z-index:15;background:var(--ink);
  border-top:1px solid var(--hair2)}
/* fantasy and note sit side by side: two short controls, one row, not two */
.flags{display:flex;gap:10px}
.flags .notebtn{flex:1;margin-top:0;justify-content:center;min-height:44px}
.flag{flex:1;min-height:44px;display:flex;align-items:center;justify-content:center;gap:9px;
  font-size:12.5px;color:var(--dim);border:1px solid var(--hair);padding:0 12px}
.flag[aria-checked=true]{border-color:var(--ochre)}
.flag i{width:16px;height:16px;border:1px solid var(--quiet);flex:none}
.flag[aria-checked=true]{color:var(--bone)}
.flag[aria-checked=true] i{background:var(--ochre);border-color:var(--ochre)}
/* a dashed hairline in --dim read as disabled and got missed entirely */
.notebtn{margin-top:12px;min-height:46px;padding:0 16px;display:flex;align-items:center;gap:10px;
  border:1px solid var(--quiet);background:var(--raise);color:var(--bone);
  font-size:13.5px;font-weight:500}
.notebtn::before{content:"";width:9px;height:9px;flex:none;border:1.5px solid var(--ochre)}
.notebtn:hover{border-color:var(--bone)}
/* once something is written, the button says so at a glance from across the card */
.notebtn.has-note{border-color:var(--ochre);color:var(--ochre)}
.notebtn.has-note::before{background:var(--ochre)}
/* Opens over the card rather than pushing it around, so choosing a position and
   writing a note never fight for the same space. */
.notewrap{position:fixed;inset:0;z-index:80;background:rgba(6,5,5,.86);
  display:flex;align-items:flex-end;justify-content:center}
.notewrap__box{width:min(100%,560px);background:var(--surface);border-top:1px solid var(--hair);
  padding:var(--gut);padding-bottom:calc(var(--gut) + env(safe-area-inset-bottom))}
.notewrap label{display:block;font-size:15px;color:var(--bone);font-weight:500;margin-bottom:4px}
.notewrap__sub{font-size:12px;color:var(--quiet);margin-bottom:12px}
.notewrap .btn-primary{margin-top:14px;width:100%}
@media(min-width:900px){
  .notewrap{align-items:center}
  .notewrap__box{border:1px solid var(--hair)}
}
.note{width:100%;background:var(--surface);border:1px solid var(--hair);color:var(--bone);
  padding:11px 12px;font-size:14px;font-family:inherit;min-height:52px;resize:vertical}
.note:focus{outline:2px solid var(--bone);outline-offset:-1px;border-color:transparent}
.note::placeholder{color:var(--quiet)}
.prev{width:56px;min-height:52px;border:1px solid var(--hair);flex:none;
  display:flex;align-items:center;justify-content:center}
.prev::before{content:"";width:9px;height:9px;border-left:1.5px solid var(--dim);
  border-bottom:1.5px solid var(--dim);transform:rotate(45deg) translate(2px,-2px)}
.prev:hover{border-color:var(--quiet)}
.next{flex:1;min-height:52px;background:var(--bone);color:var(--ink);
  font-weight:500;font-size:15px;text-align:center;display:flex;align-items:center;justify-content:center;gap:8px}

/* toast */
.toast{position:fixed;left:var(--gut);right:var(--gut);bottom:calc(var(--navh) + 14px + env(safe-area-inset-bottom,0px));
  z-index:70;background:var(--raise);border:1px solid var(--hair);padding:12px 14px;
  display:none;align-items:center;gap:12px;font-size:13px}
.toast.on{display:flex}
.toast b{font-weight:500}
.toast button{color:var(--ember);font-size:12.5px;letter-spacing:.06em;text-transform:uppercase;
  min-height:40px;display:flex;align-items:center;flex:none}

/* ================= MAP (was overview) ================= */
.map{padding:var(--gut)}
.map h2{font-size:clamp(28px,8vw,58px)}
.map__sub{color:var(--dim);font-size:14px;margin-top:12px;max-width:48ch}
.cats{margin-top:24px;display:grid;gap:0}
.catrow{width:100%;display:flex;align-items:center;gap:12px;min-height:60px;padding:12px 0;border-bottom:1px solid var(--hair2)}
.catrow .swatch{width:4px;align-self:stretch;background:var(--c);flex:none}
.catrow .nm{flex:1;min-width:0}
.catrow .nm b{display:block;font-size:15px;font-weight:500}
.catrow .nm span{font-size:11.5px;color:var(--quiet)}
.catrow .st{font-size:10.5px;letter-spacing:.1em;text-transform:uppercase;color:var(--dim);flex:none;
  font-variant-numeric:tabular-nums}
.catrow .st.skipped{color:var(--ochre)}
.catrow .st.done{color:var(--moss)}
.catbar{width:64px;height:3px;background:var(--hair);flex:none;position:relative}
.catbar i{position:absolute;inset:0 auto 0 0;background:var(--c);width:var(--w)}

/* ================= CARD ================= */
.summary{padding:var(--gut)}
.summary h2{font-size:clamp(28px,8vw,60px);max-width:12ch}
.summary>p{color:var(--dim);font-size:14.5px;max-width:46ch;margin-top:16px}
.cardwrap{margin-top:26px;display:flex;justify-content:center}
.card{width:min(100%,380px);aspect-ratio:4/5;background:linear-gradient(163deg,#191414,#0D0B0B 62%);
  border:1px solid #322A28;padding:26px 24px;display:flex;flex-direction:column;position:relative;overflow:hidden}
.card::after{content:"";position:absolute;right:-58px;top:-58px;width:190px;height:190px;
  border:1px solid rgba(207,92,104,.3);border-radius:50%}
.card__hd{display:flex;justify-content:space-between}
.card__hd b{font-size:9.5px;letter-spacing:.18em;text-transform:uppercase;color:var(--quiet);font-weight:400}
.card h3{font-size:clamp(34px,9vw,50px);margin-top:22px}
.card h3 em{font-style:normal;color:var(--ember);display:block}
.card__role{margin-top:12px;font-size:12.5px;color:var(--dim)}
.card__themes{margin-top:auto;display:flex;flex-wrap:wrap;gap:5px}
.card__themes span{border:1px solid #3A312F;padding:5px 9px;font-size:10.5px}
.card__vals{margin-top:14px;display:grid;gap:5px}
.card__vals span{font-size:11.5px;color:var(--dim);display:flex;gap:8px;align-items:center}
.card__vals span::before{content:"";width:9px;height:1px;background:var(--brass);flex:none}
.card__ft{margin-top:18px;padding-top:12px;border-top:1px solid #262020;display:flex;justify-content:space-between}
.card__ft b{font-size:9px;letter-spacing:.14em;text-transform:uppercase;color:var(--quiet);font-weight:400}
.curate{margin-top:30px}
.curate h4{font-size:9.5px;letter-spacing:.16em;text-transform:uppercase;color:var(--quiet);margin-bottom:8px}
.tog{display:flex;align-items:center;gap:12px;min-height:52px;padding:8px 0;border-bottom:1px solid var(--hair2);width:100%;font-size:13.5px;color:var(--dim)}
.tog i{width:34px;height:18px;border:1px solid var(--quiet);position:relative;flex:none;transition:border-color .2s}
.tog i::after{content:"";position:absolute;top:2px;left:2px;width:12px;height:12px;background:var(--quiet);transition:transform .2s,background .2s}
.tog[aria-checked=true]{color:var(--bone)}
.tog[aria-checked=true] i{border-color:var(--moss)}
.tog[aria-checked=true] i::after{transform:translateX(16px);background:var(--moss)}
.tog em{margin-left:auto;font-style:normal;font-size:11px;color:var(--quiet);flex:none}
.warn{margin-top:18px;padding:13px 15px;border-left:2px solid var(--oxblood-t);background:#160F10;
  font-size:12.5px;color:var(--dim);max-width:48ch}

.deck__side{display:none}

/* ================= DESKTOP ================= */
/* tablet: keep the stack from stretching into a very wide, cheap-looking column */
@media(min-width:620px) and (max-width:899px){
  .deck{max-width:640px;margin-inline:auto}
}
@media(min-width:760px){
  .about__group.cols{display:grid;grid-template-columns:1fr 1fr;gap:0 var(--gut);align-items:start}
  .about__group.cols h4{grid-column:1/-1}
}
@media(min-width:900px){
  :root{--navh:44px}
  .nav button{flex-direction:row;gap:8px;font-size:10.5px}
  .nav i{width:12px}
  .entry{display:grid;grid-template-columns:1.05fr .95fr;gap:0 var(--gut);align-content:center;padding:var(--gut)}
  .entry__a{border-right:1px solid var(--hair);padding-right:var(--gut);display:flex;flex-direction:column;justify-content:center}
  .entry__b{display:flex;flex-direction:column;justify-content:center}
  .doors{margin-top:0}
  .vow{grid-template-columns:repeat(3,1fr);gap:26px}
  /* col3's ceiling was a definite length (360px), so CSS Grid's track sizing
     grows it to that value before the stances column (the only fr track)
     ever sees any leftover space: at narrower desktop widths that starved
     the five-segment selector down to single-digit pixels. Trimming col3's
     own ceiling, still inside its already-authored 300-360 range, hands the
     difference back to the stances column at every desktop width. */
  .deck{display:grid;grid-template-columns:272px minmax(0,1fr) minmax(300px,310px) 264px;min-height:calc(100vh - var(--navh));max-width:1560px;margin-inline:auto;width:100%}
  .deck__top{grid-column:1;grid-row:1;position:static;border-bottom:none;border-right:1px solid var(--hair);
    padding:var(--gut) 20px;align-self:stretch}
  .deck__body{grid-column:2/4;grid-row:1;padding:var(--gut) var(--gut) 0;align-items:flex-start}
  .stances{grid-column:2;grid-row:2;padding:0 var(--gut);width:100%;max-width:680px}
  .quals{grid-column:3;grid-row:2/5;align-self:start;display:flex;flex-direction:column;
    padding:0 var(--gut) var(--gut) 0;width:100%}
  /* the action row is its own grid child on desktop, pinned to the bottom of
     the refinements column */
  .act{grid-column:3;grid-row:2/5;align-self:end;padding:0 var(--gut) var(--gut) 0}
  /* the mobile card pins its controls and scrolls the definition; the desktop
     grid has room for all of it, so those constraints are lifted */
  .deck{height:auto}
  .deck__body{overflow:visible;display:flex}
  .define{overflow:visible;flex:none;min-height:0}
  .dunno{grid-column:2;grid-row:3;align-self:start;width:calc(100% - (2 * var(--gut)));max-width:680px;margin:14px var(--gut) 0 !important}
  .rest{display:none}
  .deck{grid-template-rows:auto auto auto 1fr}
  .deck__top{grid-row:1/-1}
  .deck__side{grid-column:4;grid-row:1/-1;border-left:1px solid var(--hair);padding:var(--gut) 20px;display:block}
  .activity{font-size:clamp(40px,4.2vw,68px)}
  .map__grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:0 30px}
  .deck__side{display:block}
  /* start, not center: the columns are different heights and centring left the
     heading floating below the list it belongs to */
  .summary{display:grid;grid-template-columns:1fr .8fr;gap:var(--gut);align-items:start;
    padding-top:calc(var(--gut) - 8px)}
  .rhead{margin-top:0}
  .summary__a{border-right:1px solid var(--hair);padding-right:var(--gut)}
  .cardwrap{margin-top:0}
}
@media(min-width:900px){
  .side h4{font-size:9.5px;letter-spacing:.16em;text-transform:uppercase;color:var(--quiet);margin-bottom:10px}
  .side p{font-size:12px;color:var(--dim);display:flex;justify-content:space-between;margin-top:9px}
  .side p b{color:var(--bone);font-weight:500;font-variant-numeric:tabular-nums}
  .side .bar{height:2px;background:var(--hair);margin-top:5px;position:relative}
  .side .bar i{position:absolute;inset:0 auto 0 0;background:var(--b);width:var(--w)}
}

/* ============================================================
   Components the controller builds. Same language as the rest:
   hairlines not shadows, square corners, stance spectrum, no chrome.
   ============================================================ */

/* --- category map rows --- */
.cat-row{display:block;width:100%;text-align:left;padding:14px 0;border-bottom:1px solid var(--hair2);cursor:pointer;
  transition:background .16s}
.cat-row:hover{background:var(--surface)}
.cat-row__header{display:flex;align-items:center;gap:11px}
.cat-swatch{width:9px;height:9px;flex:none;background:var(--c)}
.cat-name{font-size:15px;font-weight:500;flex:1;min-width:0}
.cat-count{font-size:11.5px;color:var(--quiet);font-variant-numeric:tabular-nums;flex:none}
.cat-status{font-size:10px;letter-spacing:.1em;text-transform:uppercase;color:var(--quiet);flex:none}
.cat-status.status-done{color:var(--s-crave)}
.cat-status.status-skipped{color:var(--ochre)}
.cat-status.status-in-progress{color:var(--dim)}
.cat-progress-track{height:3px;background:var(--hair);margin-top:9px;position:relative;overflow:hidden}
.cat-progress-fill{height:100%;transform-origin:left;transition:transform .3s cubic-bezier(.22,1,.36,1)}
.cat-controls{margin-top:8px;display:flex;gap:14px}
.cat-skip-toggle{display:inline-flex;align-items:center;gap:7px;min-height:38px;font-size:11.5px;color:var(--quiet);cursor:pointer}
.cat-skip-toggle:hover{color:var(--dim)}
.skip-checkbox{appearance:none;width:14px;height:14px;border:1px solid var(--quiet);background:transparent;margin:0;cursor:pointer}
.skip-checkbox:checked{background:var(--ochre);border-color:var(--ochre)}
.cat-tag{font-size:10px;letter-spacing:.08em;text-transform:uppercase;color:var(--quiet);
  border:1px solid var(--hair);padding:3px 7px}

/* --- risk marker beside a definition --- */
.riskflag{display:inline-block;margin-left:8px;font-size:10.5px;letter-spacing:.06em;text-transform:uppercase;
  color:var(--ochre);border-bottom:1px dotted var(--ochre);white-space:nowrap}

/* --- buttons --- */
.btn-primary,.btn-secondary,.btn-resolve{min-height:50px;padding:0 20px;font-size:14.5px;font-weight:500;
  display:inline-flex;align-items:center;justify-content:center;gap:8px;border:1px solid transparent;transition:.16s}
.btn-primary{background:var(--bone);color:var(--ink)}
.btn-primary:hover{background:#fff}
.btn-secondary{background:transparent;color:var(--dim);border-color:var(--hair)}
.btn-secondary:hover{color:var(--bone);border-color:var(--quiet)}
.btn-resolve{background:transparent;color:var(--ochre);border-color:var(--ochre);min-height:42px;font-size:13px}
.btn-resolve:hover{background:var(--ochre);color:var(--ink)}

/* --- end of category --- */
.completion-header{padding:var(--gut) var(--gut) 0}
.completion-header h2{font-size:clamp(26px,7vw,44px);font-family:"Supermassive RS","General Sans",sans-serif;
  font-weight:400;letter-spacing:-.03em;line-height:.9;text-transform:uppercase}
.completion-header p{color:var(--dim);font-size:14.5px;margin-top:14px;max-width:46ch}
.completion-actions{padding:22px var(--gut);display:grid;gap:10px}
.completion-unknowns{padding:0 var(--gut) var(--gut)}
.completion-unknowns h4{font-size:9.5px;letter-spacing:.16em;text-transform:uppercase;color:var(--quiet);margin-bottom:10px}
.unknown-list{display:grid;gap:0}
.unknown-list li{list-style:none;display:flex;align-items:center;gap:12px;padding:12px 0;
  border-bottom:1px solid var(--hair2);font-size:13.5px}
.unknown-list li span{flex:1;min-width:0}

/* --- import modal --- */
.modal-dialog{position:fixed;inset:0;z-index:80;background:rgba(6,5,5,.86);
  display:flex;align-items:flex-end;justify-content:center;padding:0}
.modal-dialog>div,.modal-dialog form{width:min(100%,560px);max-height:88vh;overflow-y:auto;
  background:var(--surface);border-top:1px solid var(--hair);padding:var(--gut)}
.modal-intro{font-size:14.5px;color:var(--dim);max-width:48ch}
.modal-intro strong{color:var(--bone);font-weight:500}
.modal-note{margin-top:14px;padding:12px 14px;border-left:2px solid var(--ochre);background:#171208;
  font-size:12.5px;color:var(--dim)}
.modal-stats{margin-top:18px;display:grid;grid-template-columns:repeat(3,1fr);gap:2px}
.stat-box{background:var(--raise);padding:14px 12px;text-align:center}
.stat-box b{display:block;font-size:24px;font-weight:500;font-variant-numeric:tabular-nums}
.stat-box span{display:block;font-size:10px;letter-spacing:.1em;text-transform:uppercase;color:var(--quiet);margin-top:4px}
.stat-matched b{color:var(--s-crave)}
.stat-review b{color:var(--ochre)}
.stat-unmatched b{color:var(--quiet)}
.modal-actions{margin-top:20px;display:grid;gap:10px}

/* --- what's new (whatsnew.js): plain bullets, no icons, reusing the same
   modal-dialog shell as reset/import above rather than a stylesheet of its
   own --- */
.whatsnew-list{margin-top:14px;display:grid;gap:12px}
.whatsnew-list li{list-style:none;padding-left:16px;border-left:2px solid var(--hair);
  font-size:14px;color:var(--dim);line-height:1.5}

/* --- about you: a real section with the first fields on show, and only the
   longer detail behind a dropdown, so it neither hides nor buries the exports --- */
.about{padding:var(--gut) var(--gut) 0;border-bottom:1px solid var(--hair);
  margin-bottom:calc(var(--gut) - 10px)}
/* same scale as the Export heading below it: they are peer sections */
.about h2{font-size:clamp(28px,8vw,60px);max-width:12ch;margin-bottom:14px}
.about__intro{font-size:13.5px;color:var(--dim);max-width:56ch;line-height:1.6;margin-bottom:22px}
.about__lead{margin-bottom:6px}
.about__more{border-top:1px solid var(--hair)}
.about__head{display:flex;align-items:center;gap:12px;min-height:60px;cursor:pointer;
  list-style:none;padding:16px 0;flex-wrap:wrap}
.about__head::-webkit-details-marker{display:none}
.about__title{font-size:14.5px;font-weight:500;color:var(--bone)}
.about__head::after{content:"";width:9px;height:9px;flex:none;margin-left:auto;
  border-right:1.5px solid var(--quiet);border-bottom:1.5px solid var(--quiet);
  transform:rotate(45deg) translate(-3px,-3px);transition:transform .2s}
.about__more[open] .about__head::after{transform:rotate(-135deg) translate(-2px,-2px)}
.about__state{font-size:11px;letter-spacing:.06em;text-transform:uppercase;color:var(--quiet);
  white-space:nowrap}
.about__state.is-set{color:var(--ochre)}
.about__body{padding-bottom:12px}
.about__group{margin-bottom:26px}
.about__group h4{font-size:9.5px;letter-spacing:.16em;text-transform:uppercase;color:var(--quiet);
  margin-bottom:14px;padding-bottom:8px;border-bottom:1px solid var(--hair)}
.about__group.is-safety h4{color:var(--oxblood-t);border-bottom-color:var(--oxblood)}
.afield{margin-bottom:16px}
.afield label{display:block;font-size:13px;color:var(--bone);margin-bottom:5px}
.afield .ahint{display:block;font-size:11.5px;color:var(--quiet);margin-bottom:7px;max-width:52ch}
.afield input,.afield textarea{width:100%;max-width:52ch;background:var(--surface);
  border:1px solid var(--hair);color:var(--bone);padding:11px 12px;font-size:14px;
  font-family:inherit;min-height:46px}
.afield textarea{min-height:78px;resize:vertical;line-height:1.55}
.afield input:focus,.afield textarea:focus{outline:2px solid var(--bone);outline-offset:-1px;border-color:transparent}
.about__saved{font-size:11.5px;color:var(--quiet);margin:-10px 0 24px}

/* --- health notices: saving broken, or data recovered --- */
.health{position:fixed;left:0;right:0;top:0;z-index:75;background:var(--oxblood);color:var(--bone);
  padding:11px var(--gut);font-size:12.5px;line-height:1.5;
  display:flex;align-items:center;gap:14px;flex-wrap:wrap}
.health b{font-weight:500}
.health button{min-height:38px;padding:0 12px;border:1px solid var(--bone);color:var(--bone);
  font-size:11.5px;letter-spacing:.06em;text-transform:uppercase;flex:none}
.health button:hover{background:var(--bone);color:var(--oxblood)}
.health.is-recovery{background:var(--ochre);color:var(--ink)}
.health.is-recovery button{border-color:var(--ink);color:var(--ink)}
.health.is-recovery button:hover{background:var(--ink);color:var(--ochre)}

/* --- language switcher, sits with Reset: both are device settings, not
   checklist content. A compact button (.langbtn) is the only always-visible
   part; it opens the picker modal (LangModal in wiring.js), whose own
   radiogroup reuses .langpicker/.lang below, the same radio look this
   switcher always had. --- */
.settings{margin-top:26px;padding-top:20px;border-top:1px solid var(--hair)}
.settings h4{font-size:9.5px;letter-spacing:.16em;text-transform:uppercase;color:var(--quiet);margin-bottom:8px}
.settings p{font-size:12.5px;color:var(--quiet);max-width:44ch;margin-bottom:12px}
.langbtn{min-height:44px;padding:0 16px;font-size:13px;color:var(--dim);
  border:1px solid var(--hair);border-radius:2px;background:transparent;
  transition:border-color .2s,color .2s,background .2s}
.langbtn:hover{border-color:var(--moss);color:var(--bone)}
.langpicker{display:flex;flex-wrap:wrap;gap:8px;margin-top:14px}
.lang{min-height:var(--tapmin);padding:0 18px;border:1px solid var(--hair);border-radius:2px;
  color:var(--dim);font-size:13.5px;transition:border-color .2s,color .2s,background .2s}
.lang[aria-checked=true]{color:var(--bone);border-color:var(--moss);background:var(--raise)}

/* --- start again (destructive, so it is quiet until deliberately opened) --- */
.danger{margin-top:26px;padding-top:20px;border-top:1px solid var(--hair)}
.danger h4{font-size:9.5px;letter-spacing:.16em;text-transform:uppercase;color:var(--quiet);margin-bottom:8px}
.danger p{font-size:12.5px;color:var(--quiet);max-width:44ch;margin-bottom:12px}
.resetbtn{min-height:44px;padding:0 16px;font-size:13px;color:var(--oxblood-t);
  border:1px solid var(--oxblood);background:transparent}
.resetbtn:hover{background:#1A0F11;border-color:var(--oxblood-t)}
.startover{margin-top:16px;font-size:12.5px;color:var(--quiet);text-decoration:underline;
  text-underline-offset:3px;min-height:44px}
.startover:hover{color:var(--oxblood-t)}
.modal-danger{margin-top:14px;padding:12px 14px;border-left:2px solid var(--oxblood-t);
  background:#160F10;font-size:12.5px;color:var(--dim)}
.btn-danger{min-height:50px;padding:0 20px;font-size:14.5px;font-weight:500;
  background:var(--oxblood);color:var(--bone);border:1px solid var(--oxblood)}
.btn-danger:hover:not(:disabled){background:#A3363F;border-color:#A3363F}
/* until the backup question has been answered this button is not usable, and
   it has to LOOK unusable or the first tap reads as the app being broken */
.btn-danger:disabled{background:transparent;border-color:var(--hair);color:var(--deco);cursor:not-allowed}

/* --- resume / entry state --- */
.resume-info{font-size:13.5px;color:var(--dim);margin-top:3px}
.card-empty{padding:26px;border:1px dashed var(--hair);color:var(--quiet);font-size:13.5px;text-align:center}

/* --- packet preview / summary --- */
.summary-overview{display:grid;gap:2px;grid-template-columns:repeat(auto-fit,minmax(120px,1fr));margin-top:16px}
.summary-list{margin-top:18px;display:grid;gap:0}
.summary-list li{list-style:none;padding:10px 0;border-bottom:1px solid var(--hair2);font-size:13.5px;
  display:flex;gap:10px;align-items:baseline}
.summary-qualifiers{font-size:11px;color:var(--quiet);letter-spacing:.04em}

@media(min-width:900px){
  .modal-dialog{align-items:center}
  .modal-dialog>div,.modal-dialog form{border:1px solid var(--hair)}
  .completion-actions{grid-auto-flow:column;justify-content:start}
}

/* --- results --- */
/* the stacked mobile order puts this straight under the unanswered notice,
   which left the two touching. The desktop grid overrides it back to 0. */
.rhead{font-size:9.5px;letter-spacing:.16em;text-transform:uppercase;color:var(--quiet);
  margin-top:30px;margin-bottom:12px}
/* two classes so the second group keeps its gap under the desktop override */
.rhead.rhead--split{margin-top:30px;padding-top:22px;border-top:1px solid var(--hair)}
.rstats{margin-top:26px;display:grid;grid-template-columns:repeat(auto-fit,minmax(90px,1fr));gap:2px}
.rstat{background:var(--raise);padding:14px 12px}
.rstat b{display:block;font-size:26px;font-weight:500;font-variant-numeric:tabular-nums;line-height:1}
.rstat span{display:block;font-size:9.5px;letter-spacing:.1em;text-transform:uppercase;color:var(--quiet);margin-top:6px}
.rstat.limit b{color:var(--s-limit)}.rstat.crave b{color:var(--s-crave)}
.rgaps{margin-top:18px;font-size:13px;color:var(--dim);border-left:2px solid var(--ochre);padding:11px 14px;background:#171208}
.rgaps b{color:var(--bone);font-weight:500}
.rgaps__len{margin-bottom:6px;color:var(--bone)}
.dl{display:grid;gap:2px}
.dlrow{width:100%;text-align:left;background:var(--raise);padding:16px 16px;min-height:64px;
  border:1px solid transparent;transition:background .16s,border-color .16s}
.dlrow:hover{background:#221d1d;border-color:var(--hair)}
.dlrow__t b{display:block;font-size:15px;font-weight:500}
.dlrow__t span{display:block;font-size:12.5px;color:var(--dim);margin-top:3px;max-width:46ch}

/* --- expanded category item list --- */
.catback{display:flex;align-items:center;gap:8px;min-height:44px;font-size:12.5px;color:var(--dim)}
.catback::before{content:"";width:6px;height:6px;border-left:1px solid currentColor;border-bottom:1px solid currentColor;transform:rotate(45deg)}
.item-row{width:100%;display:flex;align-items:center;gap:12px;min-height:54px;padding:10px 0;
  border-bottom:1px solid var(--hair2);text-align:left}
.item-row:hover{background:var(--surface)}
.item-row__mark{width:4px;align-self:stretch;flex:none;background:var(--hair)}
.item-row__mark.limit{background:var(--s-limit)}.item-row__mark.no{background:var(--s-no)}
.item-row__mark.cur{background:var(--s-cur)}.item-row__mark.yes{background:var(--s-yes)}
.item-row__mark.crave{background:var(--s-crave)}.item-row__mark.unknown{background:var(--ochre)}
.item-row__name{flex:1;min-width:0;font-size:14px}
.item-row__state{font-size:10.5px;letter-spacing:.08em;text-transform:uppercase;color:var(--quiet);flex:none}

/* --- category detail: the grid --- */
/* the category page carries its own accent, so Impact reads red and Role Play
   violet the moment you land, matching the row you tapped to get here */
.cat-detail__head{display:flex;align-items:center;gap:12px;margin:14px 0 4px;flex-wrap:wrap;
  border-bottom:2px solid var(--c);padding-bottom:11px}
.cat-detail__head h3{font-size:clamp(22px,6vw,34px);font-family:"Supermassive RS","General Sans",sans-serif;
  font-weight:400;letter-spacing:-.03em;text-transform:uppercase;line-height:.9}
.runbtn{width:100%;min-height:54px;margin:14px 0 6px;background:var(--c,var(--bone));color:var(--ink);
  font-size:15px;font-weight:500;display:flex;align-items:center;justify-content:center;transition:background .16s}
button.runbtn:hover{filter:brightness(1.12)}
button.runbtn:active{filter:brightness(.94)}
.runbtn--done{background:transparent;color:var(--quiet);font-weight:340;font-size:13px;
  border:1px dashed var(--hair);min-height:46px}
.skipnote{font-size:12.5px;color:var(--ochre);padding:9px 12px;background:#171208;border-left:2px solid var(--ochre);margin-bottom:6px}

.ghead{display:flex;align-items:center;gap:10px;padding:12px 0 6px;border-bottom:1px solid var(--hair)}
.ghead>span:first-child{flex:1}
/* Wider than the marks it labels when the words need it: the header sits
   right-aligned to the grid and borrows the empty space over the activity
   column, so the ramp always has room to read as a ramp. */
.ghead__g{display:flex;gap:8px;flex:none;justify-content:space-between;
  width:max(200px, calc((var(--cellw) * 5) + (var(--cellgap) * 4)))}
.ghead__g{align-items:center}
.ghead__ramp{flex:1;height:2px;min-width:40px;align-self:center;
  background:linear-gradient(90deg,var(--s-limit),var(--s-no),var(--s-cur),var(--s-yes),var(--s-crave))}
.ghead__g b{flex:none;font-size:8.5px;letter-spacing:.08em;text-transform:uppercase;color:var(--dim);
  font-weight:400;text-align:center;line-height:1.1}
.grid-rows{display:grid}
.grow{display:flex;align-items:center;gap:10px;min-height:46px;padding:7px 0;
  border-bottom:1px solid var(--hair2);text-align:left;width:100%}
.grow:hover{background:var(--surface)}
.grow__n{flex:1;min-width:0;font-size:13.5px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.grow.unans .grow__n{color:var(--quiet)}
.grow__g{display:flex;gap:var(--cellgap);flex:none;align-items:center;position:relative}
:root{--cellw:26px;--cellgap:3px}
.gcell{width:var(--cellw);height:11px;background:#221E1C;display:block}
.gcell.on{background:var(--bone)}
.gcell.on.limit{background:var(--s-limit)}
.gcell.on.no{background:var(--s-no)}
.gcell.on.cur{background:var(--s-cur)}
.gcell.on.yes{background:var(--s-yes)}
.gcell.on.crave{background:var(--s-crave)}
.gq{position:absolute;right:-14px;font-style:normal;font-size:12px;color:var(--ochre)}

/* A split answer marks each column twice, giving on top and receiving below,
   rather than picking one side to show and losing the other. */
.gcell.split{background:none;display:flex;flex-direction:column;gap:1px}
.gcell__half{flex:1;background:#221E1C}
.gcell__half.on.limit{background:var(--s-limit)}
.gcell__half.on.no{background:var(--s-no)}
.gcell__half.on.cur{background:var(--s-cur)}
.gcell__half.on.yes{background:var(--s-yes)}
.gcell__half.on.crave{background:var(--s-crave)}
/* 'na' is a resolution, not a position, so it never lights one of the five
   columns above; instead a short muted dash floats centred over the whole
   row (or, split, over that side's own half-band), claiming no column and no
   stance colour of its own. */
.gna{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);
  width:14px;height:2px;background:var(--quiet);pointer-events:none}
.gna--give{top:25%}
.gna--receive{top:75%}
.glegend{margin:8px 0 2px;font-size:10.5px;color:var(--quiet)}
.ghint{margin:2px 0 4px;font-size:12px;color:var(--quiet)}

/* --- answering from the grid ---
   A row opens in place: the definition, then the card's own tracks (same
   classes, same colours), so a position given here looks exactly like one
   given on the card. The open row is lifted a step onto --surface; the tint
   runs 12px past the text column on each side so nothing sits flush against
   its edge. */
.gitem{border-bottom:1px solid var(--hair2)}
.gitem .grow{border-bottom:none}
.gitem.is-open{background:var(--surface);margin:0 -12px;padding:0 12px 14px}
.gitem.is-open .grow__n{color:var(--bone)}
.qa__def{margin:2px 0 12px;max-width:62ch;font-size:12.5px;line-height:1.45;color:var(--dim)}
.qa .stances__scale{margin-bottom:6px}
.qa__track .stance{height:50px}
.qa .stances__srow:first-of-type{margin-top:2px}
.qa__foot{display:flex;align-items:center;gap:16px;margin-top:10px;flex-wrap:wrap}
.qa__now{flex:1;min-width:12ch;font-size:12px;line-height:1.4;color:var(--quiet)}
.qa__card{flex:none;min-height:44px;padding:0 2px;font-size:12.5px;color:var(--dim);
  text-decoration:underline;text-decoration-color:var(--quiet);text-underline-offset:3px}
.qa__card:hover{color:var(--bone);text-decoration-color:var(--bone)}

/* --- the end of a category points at the next one --- */
.nextcat{display:flex;align-items:center;gap:10px;width:100%;min-height:62px;margin-top:22px;padding:14px 2px 14px 0;
  border-top:2px solid var(--c,var(--hair))}
.nextcat__k{flex:none;font-size:13px;color:var(--dim)}
.nextcat__n{flex:1;min-width:0;font-size:15px;font-weight:500;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.nextcat__m{flex:none;font-size:11px;color:var(--quiet);font-variant-numeric:tabular-nums}
.nextcat::after{content:"";flex:none;width:7px;height:7px;margin:0 4px 0 2px;
  border-right:1.5px solid currentColor;border-top:1.5px solid currentColor;transform:rotate(45deg)}
.nextcat:hover .nextcat__n{text-decoration:underline;text-underline-offset:4px;text-decoration-thickness:1px}
.nextcat--done{border-top-color:var(--s-crave)}

/* --- checklist length ---
   A plain three-way switch over the category list; before anything is
   answered it opens up into a question with a line on each option. */
.lenbar{margin:22px 0 6px}
.lenbar__q{margin-bottom:8px;font-size:10.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--quiet)}
.lenbar__opts{display:grid;grid-template-columns:repeat(3,1fr);gap:4px;max-width:520px}
.lenopt{display:flex;flex-direction:column;justify-content:center;gap:1px;min-height:54px;padding:8px 12px;
  background:#1A1616;border:1px solid var(--hair);transition:background .16s,border-color .16s,color .16s}
.lenopt:hover{border-color:var(--quiet)}
.lenopt__n{font-size:14px;font-weight:500}
.lenopt__c{font-size:11px;color:var(--quiet);font-variant-numeric:tabular-nums}
.lenopt[aria-checked=true]{background:var(--bone);border-color:var(--bone);color:var(--ink)}
.lenopt[aria-checked=true] .lenopt__c,.lenopt[aria-checked=true] .lenopt__d{color:#4A433D}
.lenbar--intro .lenbar__q{font-size:16px;letter-spacing:0;text-transform:none;color:var(--bone);font-weight:500}
.lenbar--intro .lenbar__opts{grid-template-columns:1fr;gap:6px;max-width:none}
.lenbar--intro .lenopt{padding:12px 14px;min-height:72px}
.lenopt__d{margin-top:4px;font-size:12.5px;line-height:1.4;color:var(--dim);font-weight:340}
.lenbar__note{margin-top:10px;font-size:12px;color:var(--quiet);max-width:60ch}
@media(min-width:760px){
  .lenbar--intro .lenbar__opts{grid-template-columns:repeat(3,1fr);max-width:960px}
  .lenbar--intro .lenopt{justify-content:flex-start}
}

@media(max-width:420px){
  :root{--cellw:20px}
  .ghead__g b{font-size:7.5px}
  .gcell{height:10px}
  .grow__n{font-size:13px}
}
@media(min-width:900px){
  :root{--cellw:52px}
  .ghead__g b{font-size:9.5px}
  .gcell{height:13px}
  .grow{min-height:40px}
  .grow__n{font-size:14px}
  .runbtn{max-width:340px}
}

/* the category grid wants one wide column, not the multi column list layout */
#cats.is-detail{display:block}
.cat-detail{max-width:960px}
@media(min-width:900px){
  .cat-detail__head h3{font-size:38px}
  .grow{min-height:36px;padding:5px 0}
  .ghead{padding-top:18px}
}

/* Body copy needed a touch more tracking to read at length on a dark ground.
   Anything that sets its own letter-spacing keeps it. */
.blurb,.define,.door p,.vow p,.summary>p,.summary__a>p,.dlrow__t span,
.rgaps,.warn,.map__sub,.note,.grow__n,.stances__desc{letter-spacing:.014em}
.door h3,.dlrow__t b{letter-spacing:.008em}

/* Heading to body rhythm. The display face is set very tight (line-height .86)
   so a following paragraph needs a deliberate gap, not the default. These are
   set on the element rather than a parent selector because the headings sit at
   different depths in each pane. */
.sm + p, .sm + .map__sub, h2.sm + p{margin-top:18px}
.summary__a > p{margin-top:18px;color:var(--dim);font-size:14.5px;max-width:46ch}
.map__sub{margin-top:18px}
.completion-header p{margin-top:16px}
.cat-detail__head{margin-top:18px}
@media(min-width:900px){
  .sm + p, .sm + .map__sub, h2.sm + p, .summary__a > p{margin-top:22px}
}

/* --- category list rows --- */
/* Not doing a category IS skipping it, so the row carries no separate skip
   control any more, and the whole row is the one tap target: no dead strip
   down the right edge where a tap used to land on nothing. */
.crow{position:relative;border-bottom:1px solid var(--hair2)}
.crow__go{display:flex;align-items:center;gap:11px;width:100%;min-height:58px;padding:10px 0;text-align:left}
.crow__go:hover{background:var(--surface)}
.crow__dot{width:9px;height:9px;flex:none;background:var(--c)}
.crow__nm{flex:1;min-width:0;font-size:15px;font-weight:500;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.crow__st{font-size:10px;letter-spacing:.1em;text-transform:uppercase;color:var(--quiet);flex:none}
.crow__st.skipped{color:var(--ochre)}
.crow__frac{font-size:10.5px;color:var(--quiet);font-variant-numeric:tabular-nums;flex:none;white-space:nowrap}
.crow__bar{position:absolute;left:0;right:0;bottom:0;height:2px;background:transparent;pointer-events:none}
.crow__bar i{display:block;height:100%;background:var(--c)}
.crow.is-skipped .crow__nm{color:var(--quiet)}
@media(min-width:900px){
  .crow__go{min-height:48px}
  .crow__nm{font-size:15.5px}
}

/* --- progress ring ---
   Replaces the plain count text in two places (the workbook row and the
   category page) with the same component at two sizes, so a percentage
   means the same shape wherever it turns up. */
.ring{position:relative;flex:none;display:inline-flex;align-items:center;justify-content:center}
.ring__track{fill:none;stroke:var(--hair)}
.ring__fill{fill:none;stroke-linecap:round;transition:stroke-dashoffset .3s ease,stroke .3s ease}
.ring__pct{position:absolute;font-variant-numeric:tabular-nums;font-weight:500;color:var(--bone)}
.ring--row{width:40px;height:40px}
.ring--row .ring__pct{font-size:9.5px}
.ring--cat{width:64px;height:64px;margin-left:auto}
.ring--cat .ring__pct{font-size:16px}
.ring--cat.is-done .ring__pct{color:var(--s-crave)}

/* ================= SET-UP (setup.js) =================
   Four one-tap questions, a summary and the optional own-words step. Laid
   out like the entry doors (hairline rows, display-face question) so it
   reads as part of the way in, not a form bolted onto it. Padded clear of
   the fixed nav so the foot buttons are never under it. */
#s-setup{min-height:100svh;padding-bottom:calc(var(--navh) + env(safe-area-inset-bottom,0px))}
.su{max-width:560px;margin:0 auto;padding:0 var(--gut);display:flex;flex-direction:column;
  min-height:min(calc(100svh - var(--navh)), 860px)}
.su-top{display:flex;justify-content:space-between;align-items:center;gap:12px;padding-top:6px}
.su-top .mono{text-align:center}
.su-link{min-height:44px;font-size:12.5px;color:var(--quiet);text-decoration:underline;text-underline-offset:3px}
.su-link:hover{color:var(--bone)}
.su-steps{display:flex;gap:4px;margin-top:6px}
.su-steps i{flex:1;height:3px;border-radius:2px;background:var(--hair)}
.su-steps i.on{background:var(--bone)}
.su-body{flex:1;padding-top:28px}
.su-q{font-size:clamp(34px,9.4vw,52px);outline:none}
.su-sub{margin-top:14px;font-size:13.5px;line-height:1.5;color:var(--dim);max-width:42ch}
.su-opts{margin-top:22px}
.su-opt{display:block;width:100%;padding:14px 44px 14px 0;border-top:1px solid var(--hair);position:relative;min-height:var(--tap)}
.su-opt:last-child{border-bottom:1px solid var(--hair)}
.su-opt b{display:block;font-size:17px;font-weight:500}
.su-opt span{display:block;margin-top:2px;font-size:13px;color:var(--dim);max-width:40ch;line-height:1.45}
.su-opt::after{content:"";position:absolute;right:2px;top:50%;width:18px;height:18px;margin-top:-9px;
  border:1px solid var(--deco);border-radius:50%;transition:border-color .16s,background .16s}
.su-opt[aria-checked=true]::after{border-color:var(--ember);background:radial-gradient(circle,var(--ember) 0 5px,transparent 6px)}
.su-opt:hover::after{border-color:var(--quiet)}
.su-foot{display:flex;flex-direction:column;gap:4px;padding:18px 0 20px}
.su-go{min-height:56px;border-radius:4px;background:var(--bone);color:var(--ink);font-size:15px;font-weight:500;text-align:center}
.su-go:disabled{background:var(--raise);color:var(--quiet);cursor:not-allowed}
.su-ghost{min-height:44px;font-size:13px;color:var(--quiet);text-align:center;text-decoration:underline;text-underline-offset:3px}
.su-big{display:flex;align-items:baseline;gap:12px;margin-top:20px}
.su-big b{font-family:"Supermassive RS","General Sans",sans-serif;font-weight:400;font-size:64px;line-height:.8;
  letter-spacing:-.03em;font-variant-numeric:tabular-nums}
.su-big span{font-size:13.5px;color:var(--dim)}
.su-note{margin-top:12px;font-size:13px;color:var(--bone);padding:10px 12px;background:var(--surface);border:1px solid var(--hair);border-radius:4px}
.su-rows{margin-top:18px}
.su-row{display:flex;align-items:center;gap:12px;min-height:52px;border-top:1px solid var(--hair);font-size:14px}
.su-row:last-child{border-bottom:1px solid var(--hair)}
.su-row span{flex:none;width:84px;color:var(--dim)}
.su-row b{flex:1;font-weight:500}
.su-words-res{display:flex;justify-content:space-between;align-items:center;gap:12px;margin-top:12px;font-size:13px;color:var(--dim)}
.su-lenq{margin-top:22px;margin-bottom:8px;font-size:10.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--quiet)}
.su-len{display:grid;grid-template-columns:repeat(3,1fr);gap:4px}
.su-lenopt{display:flex;flex-direction:column;justify-content:center;gap:1px;min-height:54px;padding:8px 12px;
  background:#1A1616;border:1px solid var(--hair);transition:background .16s,border-color .16s,color .16s}
.su-lenopt b{font-size:14px;font-weight:500}
.su-lenopt span{font-size:11px;color:var(--quiet);font-variant-numeric:tabular-nums}
.su-lenopt[aria-checked=true]{background:var(--bone);border-color:var(--bone);color:var(--ink)}
.su-lenopt[aria-checked=true] span{color:#4A433D}
.su-wordsbtn{display:block;width:100%;margin-top:22px;padding:14px;border:1px solid var(--hair);border-radius:4px;background:var(--surface)}
.su-wordsbtn:hover{border-color:var(--quiet)}
.su-wordsbtn b{display:block;font-size:14px;font-weight:500}
.su-wordsbtn span{display:block;margin-top:3px;font-size:12.5px;color:var(--dim);line-height:1.45}
.su-text{display:block;width:100%;min-height:150px;margin-top:18px;padding:12px;background:var(--surface);color:var(--bone);
  border:1px solid var(--hair);border-radius:4px;font:inherit;font-size:15px;line-height:1.5;resize:vertical}
.su-text:focus{border-color:var(--quiet);outline:none}
.su-text::placeholder{color:var(--quiet)}
.su-notice{margin-top:14px;padding-left:18px;display:grid;gap:6px;font-size:12.5px;color:var(--dim);line-height:1.5}
.su-more{margin-top:8px;font-size:12.5px}
.su-more a{color:var(--bone);text-underline-offset:3px}
.su-check{display:flex;gap:12px;align-items:flex-start;margin-top:16px;font-size:13.5px;line-height:1.45;cursor:pointer;min-height:44px}
.su-check input{flex:none;width:22px;height:22px;margin-top:1px;accent-color:var(--ember)}
.su-ts{margin-top:10px}
.su-err{margin-top:12px;font-size:13px;color:var(--oxblood-t)}

/* Workbook: the set-up's line above the length switch (catlist.js). */
.tailor{margin-top:20px;padding:14px 0;border-top:1px solid var(--hair);border-bottom:1px solid var(--hair);
  display:flex;justify-content:space-between;align-items:center;gap:14px}
.tailor p{font-size:13px;color:var(--dim);line-height:1.45}
.tailor p b{display:block;color:var(--bone);font-weight:500;font-size:14px}
.tailor button{flex:none;min-height:44px;font-size:12.5px;color:var(--bone);text-decoration:underline;text-underline-offset:3px}
.tailor--intro{display:block;padding:16px;border:1px solid var(--hair);border-radius:4px;background:var(--surface)}
.tailor--intro p b{font-size:16px;margin-bottom:3px}
.tailor--intro .su-go{display:block;width:100%;margin-top:12px;text-decoration:none;color:var(--ink)}

/* The card's "with someone new" row (app.js) and its twin in the grid's
   inline panel (catlist.js). One compact scale for the whole activity,
   blank meaning "same as above". */
.alt{margin-top:12px;padding-top:10px;border-top:1px dashed var(--hair)}
.alt__head{display:flex;justify-content:space-between;align-items:baseline;gap:8px}
.alt__label{font-size:9.5px;letter-spacing:.1em;text-transform:uppercase;color:var(--brass);font-weight:500}
.alt__hint{font-size:11px;color:var(--quiet)}
.alt__track{display:flex;gap:4px;margin-top:6px}
.alt__same{flex:none;min-height:36px;padding:0 12px;border:1px solid #4A4038;border-radius:3px;background:#252020;
  font-size:12px;color:var(--dim)}
.alt__same[aria-checked=true]{background:var(--bone);border-color:var(--bone);color:var(--ink)}
.alt__seg{position:relative;flex:1;min-height:36px;min-width:0;background:#252020;border:1px solid #4A4038;border-radius:3px}
/* Each segment carries its position's colour as a small dot, so the row
   reads limit to love like the scale above it before anything is tapped. */
.alt__seg::after{content:"";position:absolute;left:50%;top:50%;width:8px;height:8px;margin:-4px 0 0 -4px;border-radius:50%;
  background:var(--k);opacity:.7}
.alt__seg[aria-checked=true]::after{background:var(--ink);opacity:.55}
.alt__seg:hover,.alt__same:hover{border-color:var(--quiet)}
.alt__seg[aria-checked=true]{background:var(--k);border-color:var(--k)}
.alt__chips{display:flex;flex-wrap:wrap;gap:5px;margin-top:7px}
.alt__chip{display:inline-flex;align-items:center;gap:6px;min-height:36px;padding:0 10px;border:1px solid #4A4038;border-radius:18px;
  font-size:12px;color:var(--dim);transition:border-color .16s,background .16s,color .16s}
.alt__chip i{width:8px;height:8px;border-radius:50%;background:var(--k)}
.alt__chip:hover{border-color:var(--quiet)}
.alt__chip[aria-checked=true]{border-color:var(--bone);background:var(--raise);color:var(--bone)}
