@import "/assets/tokens.css";

/* ---------- base ---------- */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--body);
  font-size: var(--t-body);
  line-height: 1.55;
  letter-spacing: -0.011em;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}
h1,h2,h3,h4 { font-family: var(--disp); font-weight: 640; letter-spacing: -0.028em; line-height: 1.12; margin: 0; }
h1 { font-size: var(--t-h1); }
h2 { font-size: var(--t-h2); }
h3 { font-size: var(--t-h3); letter-spacing: -0.018em; }
p { margin: 0 0 var(--s4); }
a { color: inherit; text-decoration-color: var(--ink-4); text-underline-offset: 3px; }
img, svg { max-width: 100%; height: auto; display: block; }
:focus-visible { outline: 2.5px solid var(--signal); outline-offset: 3px; border-radius: 4px; }
::selection { background: var(--signal-soft); color: var(--ink); }

.wrap { width: min(100% - 2.5rem, 68rem); margin-inline: auto; }
.narrow { max-width: var(--measure); }
.mono { font-family: var(--mono); font-size: .82em; letter-spacing: .02em; font-variant-numeric: tabular-nums; }
.eyebrow {
  font-family: var(--mono); font-size: var(--t-micro); text-transform: uppercase;
  letter-spacing: .13em; color: var(--ink-3); margin: 0 0 var(--s3);
}
.muted { color: var(--ink-2); }
.tiny { font-size: var(--t-micro); color: var(--ink-3); line-height: 1.5; }
.center { text-align: center; }
.stack > * + * { margin-top: var(--s4); }
.sr-only {
  position:absolute; width:1px; height:1px; padding:0; margin:-1px;
  overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; border:0;
}
.skip {
  position: absolute; left: -9999px; top: var(--s3); z-index: 200;
  background: var(--ink); color: var(--paper); padding: var(--s3) var(--s4); border-radius: var(--r-sm);
}
.skip:focus { left: var(--s4); }

/* ---------- mark ---------- */
.mark { display: inline-flex; align-items: center; gap: 10px; text-decoration: none; font-family: var(--disp); }
.mark svg, .mark img { width: 26px; height: 26px; display: block; }
.mark-word { font-weight: 700; letter-spacing: .16em; font-size: .95rem; }

/* ---------- buttons ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s2);
  font: inherit; font-weight: 570; font-family: var(--disp); letter-spacing: -.01em;
  padding: 14px 22px; border-radius: var(--r-full); border: 1px solid transparent;
  background: var(--signal); color: var(--on-signal); cursor: pointer;
  text-decoration: none; min-height: 48px;
  transition: transform var(--dur) var(--ease), background var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.btn:hover { transform: translateY(-1px); box-shadow: var(--shadow-md); }
.btn:active { transform: translateY(0); }
.btn[disabled] { opacity: .45; pointer-events: none; }
.btn-ghost { background: transparent; color: var(--ink); border-color: var(--paper-edge); }
.btn-ghost:hover { background: var(--paper-sunk); }
.btn-quiet { background: var(--paper-sunk); color: var(--ink); }
.btn-clay { background: var(--clay); color: var(--on-clay); }
.btn-sm { padding: 9px 16px; min-height: 40px; font-size: var(--t-small); }
.btn-block { width: 100%; }

/* ---------- cards ---------- */
.card {
  background: var(--paper-raised); border: 1px solid var(--paper-edge);
  border-radius: var(--r-lg); padding: var(--s5); box-shadow: var(--shadow-sm);
}
.card-flat { box-shadow: none; }
.card-sunk { background: var(--paper-sunk); border-color: transparent; box-shadow: none; }
.card + .card { margin-top: var(--s4); }
.card-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--s3); margin-bottom: var(--s4); }

.grid { display: grid; gap: var(--s4); }
@media (min-width: 720px) { .grid-2 { grid-template-columns: 1fr 1fr; } .grid-3 { grid-template-columns: repeat(3,1fr); } }

.pill {
  display: inline-flex; align-items: center; gap: 6px; font-family: var(--mono);
  font-size: var(--t-micro); letter-spacing: .06em; text-transform: uppercase;
  padding: 5px 11px; border-radius: var(--r-full);
  background: var(--paper-sunk); color: var(--ink-2);
}
.pill-signal { background: var(--signal-soft); color: var(--signal); }
.pill-clay   { background: var(--clay-soft); color: var(--clay); }
.pill-caution{ background: var(--caution-soft); color: var(--caution); }
.dot { width: 7px; height: 7px; border-radius: 50%; background: currentColor; flex: none; }

/* ---------- app shell ---------- */
.appbar {
  position: sticky; top: 0; z-index: 40;
  display: flex; align-items: center; justify-content: space-between; gap: var(--s3);
  padding: var(--s4) 0; background: color-mix(in srgb, var(--paper) 88%, transparent);
  backdrop-filter: saturate(150%) blur(14px);
  border-bottom: 1px solid var(--paper-edge);
}
.bar-row { display: flex; align-items: center; justify-content: space-between; }
.appbar-actions { display: flex; align-items: center; gap: var(--s2); }

/* Three items fit on a phone only if they stop asking for desktop padding.
   The Guides link earns its place in the bar because it is the only route
   into the writing from any page that is not the homepage, and a link that
   exists solely for a crawler is not a link. */
@media (max-width: 560px) {
  .appbar-actions .btn-sm { padding: 8px 12px; font-size: .8rem; }
  .appbar-actions { gap: 6px; }
}
@media (max-width: 400px) {
  .appbar .mark-word, .sitebar .mark-word { display: none; }
  .appbar-actions .btn-sm { padding: 8px 10px; }
}

main { padding-bottom: calc(var(--tab-h) + env(safe-area-inset-bottom) + var(--s7)); }
.view { padding-top: var(--s5); animation: rise var(--dur-slow) var(--ease) both; }
@keyframes rise { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }

.tabbar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 50;
  display: grid; grid-template-columns: repeat(5, 1fr);
  background: color-mix(in srgb, var(--paper-raised) 92%, transparent);
  backdrop-filter: saturate(160%) blur(18px);
  border-top: 1px solid var(--paper-edge);
  padding-bottom: env(safe-area-inset-bottom);
}
.tab {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px;
  min-height: var(--tab-h); text-decoration: none; color: var(--ink-3);
  font-family: var(--mono); font-size: 10px; letter-spacing: .1em; text-transform: uppercase;
  transition: color var(--dur) var(--ease);
}
.tab svg { width: 22px; height: 22px; stroke: currentColor; fill: none; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.tab[aria-current="page"] { color: var(--signal); }
.tab:hover { color: var(--ink); }

@media (min-width: 960px) {
  .tabbar {
    top: 0; bottom: 0; right: auto; width: 96px; grid-template-columns: 1fr;
    grid-auto-rows: max-content; align-content: center; gap: var(--s2);
    border-top: none; border-right: 1px solid var(--paper-edge);
  }
  body.in-app { padding-left: 96px; }
  main { padding-bottom: var(--s8); }
}

/* ---------- today / floor ---------- */
.today-date { font-family: var(--mono); font-size: var(--t-micro); letter-spacing: .12em; text-transform: uppercase; color: var(--ink-3); }
.today-h { font-size: var(--t-hero); letter-spacing: -.038em; line-height: 1.02; margin: var(--s2) 0 var(--s4); }

.floor { display: grid; gap: var(--s3); }
.floor-item {
  display: flex; align-items: center; gap: var(--s4);
  padding: var(--s4); border-radius: var(--r-md);
  background: var(--paper-raised); border: 1px solid var(--paper-edge);
  cursor: pointer; text-align: left; width: 100%; font: inherit; color: inherit;
  transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease);
}
.floor-item:hover { border-color: var(--signal-edge); }
.floor-item[data-done="1"] { background: var(--signal-soft); border-color: var(--signal-edge); }
.floor-item[data-done="1"] .floor-label { color: var(--ink-2); text-decoration: line-through; text-decoration-color: var(--ink-4); }
.floor-check {
  width: 28px; height: 28px; flex: none; border-radius: 50%;
  border: 2px solid var(--ink-4); display: grid; place-items: center;
  transition: all var(--dur) var(--ease);
}
.floor-item[data-done="1"] .floor-check { background: var(--signal); border-color: var(--signal); }
.floor-check svg { width: 15px; height: 15px; stroke: var(--on-signal); stroke-width: 3; fill: none; stroke-linecap: round; stroke-linejoin: round; opacity: 0; }
.floor-item[data-done="1"] .floor-check svg { opacity: 1; }
.floor-body { flex: 1; min-width: 0; }
.floor-label { display: block; font-weight: 560; font-family: var(--disp); letter-spacing: -.015em; }
.floor-cue { display: block; font-size: var(--t-small); color: var(--ink-3); margin-top: 2px; }

/* ---------- why card ---------- */
.why {
  background: var(--clay-soft); border: 1px solid transparent;
  border-radius: var(--r-lg); padding: var(--s5);
}
.why h3 { color: var(--clay); font-size: var(--t-small); font-family: var(--mono); font-weight: 500;
  text-transform: uppercase; letter-spacing: .12em; margin-bottom: var(--s3); }
.why p { margin: 0; }

/* ---------- path ---------- */
.path-rail { position: relative; padding-left: 34px; }
.path-rail::before {
  content: ""; position: absolute; left: 12px; top: 10px; bottom: 10px; width: 2px;
  background: linear-gradient(var(--signal-edge), var(--paper-edge));
}
.step { position: relative; padding-bottom: var(--s5); }
.step::before {
  content: ""; position: absolute; left: -28px; top: 5px; width: 13px; height: 13px;
  border-radius: 50%; background: var(--paper); border: 2.5px solid var(--paper-edge);
}
.step[data-state="done"]::before   { background: var(--signal); border-color: var(--signal); }
.step[data-state="active"]::before { background: var(--paper); border-color: var(--signal); box-shadow: 0 0 0 5px var(--signal-soft); }
.step-when { font-family: var(--mono); font-size: var(--t-micro); letter-spacing: .1em; text-transform: uppercase; color: var(--ink-3); }
.step-what { font-family: var(--disp); font-weight: 590; letter-spacing: -.018em; margin: 3px 0; }
.step-why { font-size: var(--t-small); color: var(--ink-2); }

/* ---------- plan stages ---------- */
.stagebar { display: flex; gap: var(--s2); overflow-x: auto; padding-bottom: var(--s2); scrollbar-width: none; }
.stagebar::-webkit-scrollbar { display: none; }
.stagebtn {
  font: inherit; font-family: var(--mono); font-size: var(--t-micro); text-transform: uppercase; letter-spacing: .1em;
  padding: 9px 16px; border-radius: var(--r-full); border: 1px solid var(--paper-edge);
  background: transparent; color: var(--ink-3); cursor: pointer; white-space: nowrap;
  transition: all var(--dur) var(--ease);
}
.stagebtn[aria-selected="true"] { background: var(--ink); color: var(--paper); border-color: var(--ink); }

.portion { display: flex; align-items: center; gap: var(--s4); padding: var(--s4) 0; border-bottom: 1px solid var(--paper-edge); }
.portion:last-child { border-bottom: none; }
.portion-icon { width: 46px; height: 46px; flex: none; display: grid; place-items: center; border-radius: var(--r-md); background: var(--signal-soft); }
.portion-icon svg { width: 26px; height: 26px; stroke: var(--signal); fill: none; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.portion-amt { font-family: var(--disp); font-weight: 620; letter-spacing: -.02em; }
.portion-note { font-size: var(--t-small); color: var(--ink-3); }

.exercise { display: flex; justify-content: space-between; gap: var(--s4); padding: var(--s4) 0; border-bottom: 1px solid var(--paper-edge); }
.exercise:last-child { border-bottom: none; }
.exercise-name { font-family: var(--disp); font-weight: 560; letter-spacing: -.015em; }
.exercise-cue { font-size: var(--t-small); color: var(--ink-3); margin-top: 2px; }
.exercise-dose { font-family: var(--mono); font-size: var(--t-small); color: var(--ink-2); white-space: nowrap; }

.list-plain { list-style: none; margin: 0; padding: 0; }
.list-plain li { padding: var(--s3) 0; border-bottom: 1px solid var(--paper-edge); display: flex; justify-content: space-between; gap: var(--s4); }
.list-plain li:last-child { border-bottom: none; }

/* ---------- progress ---------- */
.meter { display: grid; gap: 6px; }
.meter-top { display: flex; justify-content: space-between; align-items: baseline; gap: var(--s3); }
.meter-label { font-size: var(--t-small); font-weight: 540; }
.meter-val { font-family: var(--mono); font-size: var(--t-small); color: var(--ink-2); }
.meter-track { height: 9px; border-radius: var(--r-full); background: var(--paper-sunk); overflow: hidden; }
.meter-fill { height: 100%; border-radius: var(--r-full); background: var(--signal); transition: width var(--dur-slow) var(--ease); }
.meter + .meter { margin-top: var(--s4); }

.stat { text-align: left; }
.stat-n { font-family: var(--disp); font-size: 2.1rem; font-weight: 660; letter-spacing: -.035em; line-height: 1; font-variant-numeric: tabular-nums; }
.stat-l { font-family: var(--mono); font-size: var(--t-micro); text-transform: uppercase; letter-spacing: .1em; color: var(--ink-3); margin-top: 6px; }
.statrow { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s4); }

/* ---------- shop ---------- */
.sku { display: flex; gap: var(--s4); padding: var(--s5) 0; border-bottom: 1px solid var(--paper-edge); }
.sku:last-of-type { border-bottom: none; }
.sku-thumb { width: 72px; height: 72px; flex: none; border-radius: var(--r-md); background: var(--paper-sunk); display: grid; place-items: center; }
.sku-thumb svg { width: 34px; height: 34px; stroke: var(--ink-3); fill: none; stroke-width: 1.4; stroke-linecap: round; stroke-linejoin: round; }
.sku-body { flex: 1; min-width: 0; }
.sku-name { font-family: var(--disp); font-weight: 590; letter-spacing: -.018em; }
.sku-why { font-size: var(--t-small); color: var(--ink-2); margin: 4px 0 var(--s3); }
.sku-foot { display: flex; align-items: center; justify-content: space-between; gap: var(--s3); flex-wrap: wrap; }
.sku-price { font-family: var(--mono); font-size: var(--t-small); }
.spend {
  display: flex; justify-content: space-between; align-items: center; gap: var(--s3);
  padding: var(--s4); border-radius: var(--r-md); background: var(--paper-sunk); margin-bottom: var(--s5);
}

/* ---------- guardrail ---------- */
.guard { border-left: 3px solid var(--caution); background: var(--caution-soft); border-radius: var(--r-md); padding: var(--s5); }
.guard h3 { color: var(--caution); margin-bottom: var(--s2); }
.guard-stop { border-left-color: var(--clay); background: var(--clay-soft); }
.guard-stop h3 { color: var(--clay); }

/* ---------- forms / intake ---------- */
.field { display: block; margin-bottom: var(--s5); }
.field > .lab { display: block; font-family: var(--disp); font-weight: 570; letter-spacing: -.015em; margin-bottom: var(--s2); }
.field > .hint { display: block; font-size: var(--t-small); color: var(--ink-3); margin-bottom: var(--s3); }
input[type="text"], input[type="email"], input[type="number"], select, textarea {
  width: 100%; font: inherit; font-size: 1rem; color: var(--ink);
  background: var(--paper-raised); border: 1px solid var(--paper-edge);
  border-radius: var(--r-md); padding: 14px 16px; min-height: 50px;
  transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
input:focus, select:focus, textarea:focus { border-color: var(--signal); box-shadow: 0 0 0 4px var(--signal-soft); outline: none; }
textarea { min-height: 110px; resize: vertical; line-height: 1.5; }

.choices { display: grid; gap: var(--s3); }
@media (min-width: 640px) { .choices-2 { grid-template-columns: 1fr 1fr; } }
.choice {
  display: flex; align-items: flex-start; gap: var(--s3); cursor: pointer;
  padding: var(--s4); border: 1px solid var(--paper-edge); border-radius: var(--r-md);
  background: var(--paper-raised); transition: all var(--dur) var(--ease);
}
.choice:hover { border-color: var(--signal-edge); }
.choice input { position: absolute; opacity: 0; pointer-events: none; }
.choice-box {
  width: 22px; height: 22px; flex: none; margin-top: 1px; border-radius: 7px;
  border: 2px solid var(--ink-4); display: grid; place-items: center; transition: all var(--dur) var(--ease);
}
.choice input[type="radio"] ~ .choice-box { border-radius: 50%; }
.choice-box svg { width: 12px; height: 12px; stroke: var(--on-signal); stroke-width: 3.2; fill: none; stroke-linecap: round; stroke-linejoin: round; opacity: 0; }
.choice:has(input:checked) { border-color: var(--signal); background: var(--signal-soft); }
/* KEYBOARD FOCUS WAS INVISIBLE ON ALL 51 INTAKE OPTIONS.
   The real input is hidden two rules above with opacity: 0, which is the right
   way to build a custom control, and the global :focus-visible ring at the top
   of this file was therefore being drawn on an invisible element. `.choice`
   itself had a hover state and a checked state and no focus state at all, so
   somebody tabbing through the intake could not see where they were: eleven
   questions, fifty-one options, including every question on the medical safety
   screen. WCAG 2.4.7, and the same pattern `.tiercard:focus-within` already
   uses six hundred lines away.

   :focus-within rather than :focus-visible on the label, because the focus
   lands on the hidden input and has to be reflected onto the card the person
   can actually see. */
.choice:focus-within { outline: 2.5px solid var(--signal); outline-offset: 3px; border-color: var(--signal); }
.choice:has(input:focus-visible) .choice-box { border-color: var(--signal); box-shadow: 0 0 0 3px var(--signal-soft); }
.choice:has(input:checked) .choice-box { background: var(--signal); border-color: var(--signal); }
.choice:has(input:checked) .choice-box svg { opacity: 1; }
.choice-t { display: block; font-weight: 550; }
.choice-d { display: block; font-size: var(--t-small); color: var(--ink-3); margin-top: 2px; }

.steps-meter { height: 4px; background: var(--paper-sunk); border-radius: var(--r-full); overflow: hidden; margin-bottom: var(--s6); }
.steps-fill { height: 100%; background: var(--signal); transition: width var(--dur-slow) var(--ease); }
.step-panel[hidden] { display: none; }
.intake-foot { display: flex; gap: var(--s3); justify-content: space-between; margin-top: var(--s6); }

/* ---------- marketing ---------- */
.hero { padding: var(--s9) 0 var(--s8); }
.hero h1 { font-size: var(--t-hero); letter-spacing: -.042em; line-height: 1.0; }
.hero-sub { font-size: 1.2rem; color: var(--ink-2); max-width: 32rem; margin-top: var(--s5); }
.hero-cta { display: flex; gap: var(--s3); flex-wrap: wrap; margin-top: var(--s6); }
.rule { height: 1px; background: var(--paper-edge); border: 0; margin: var(--s8) 0; }
.refuse { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s3); }
.refuse li { display: flex; gap: var(--s3); align-items: baseline; }
.refuse .x { color: var(--clay); font-family: var(--mono); flex: none; }
.site-foot { padding: var(--s7) 0 var(--s8); border-top: 1px solid var(--paper-edge); color: var(--ink-3); font-size: var(--t-small); }
.site-foot a { color: var(--ink-2); }

.toast {
  position: fixed; left: 50%; bottom: calc(var(--tab-h) + 20px); transform: translate(-50%, 12px);
  background: var(--ink); color: var(--paper); padding: 12px 20px; border-radius: var(--r-full);
  font-size: var(--t-small); z-index: 90; opacity: 0; pointer-events: none;
  transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease);
  box-shadow: var(--shadow-lg); max-width: calc(100vw - 3rem);
}
.toast[data-show="1"] { opacity: 1; transform: translate(-50%, 0); }

/* check-in options: big tap targets, radio hidden behind the card edge */
.ck-row { display: flex; gap: var(--s3); flex-wrap: wrap; margin-top: var(--s3); }
/* Stacked, because the automaticity answers are sentences and a wrapped row
   of four turns them into a word puzzle on a phone. */
.ck-col { display: flex; flex-direction: column; gap: var(--s2); margin-top: var(--s3); }
.ck-col .ck-opt { width: 100%; }
.ck-opt { display: inline-flex; align-items: center; gap: 8px; padding: 10px 16px;
  border: 1px solid var(--paper-edge); border-radius: var(--r-full); cursor: pointer;
  background: var(--paper-raised); }
.ck-opt:has(input:checked) { border-color: var(--signal); background: var(--signal-soft); }
.ck-opt input { accent-color: var(--signal); }

/* ============================================================
   THE SCAN
   Restrained on purpose. The feeling of technology comes from observations
   genuinely arriving one at a time, not from chrome.
   ============================================================ */
.consent-list { margin: 0; padding-left: 1.2em; display: grid; gap: var(--s4); }
.consent-list li { line-height: 1.6; }

.scan-drop {
  display: grid; gap: 6px; place-items: center; text-align: center;
  padding: clamp(1.6rem, 5vw, 2.6rem);
  border: 1px dashed var(--paper-edge); border-radius: var(--r-md);
  background: var(--paper-sunk); cursor: pointer;
}
.scan-drop:focus-within { outline: 2px solid var(--signal); outline-offset: 3px; }
.scan-drop input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.scan-drop-label { font-weight: 600; }
.scan-drop-hint { font-family: var(--mono); font-size: .72rem; color: var(--ink-3); }

.scanout { margin-top: var(--s5); }
.scan-status { display: flex; align-items: center; gap: 10px; font-family: var(--mono); font-size: .72rem;
  letter-spacing: .1em; text-transform: uppercase; color: var(--ink-3); }
.scan-pulse { width: 8px; height: 8px; border-radius: 50%; background: var(--signal); animation: scanpulse 1.1s ease-in-out infinite; }
.scanout.is-done .scan-pulse { animation: none; opacity: .35; }
@keyframes scanpulse { 0%,100% { opacity: .25; transform: scale(.8) } 50% { opacity: 1; transform: scale(1.15) } }
@media (prefers-reduced-motion: reduce) { .scan-pulse { animation: none } }

.scanlines { margin-top: var(--s4); display: grid; gap: var(--s3); }
.scanline {
  display: grid; gap: 4px; padding: var(--s4);
  border: 1px solid var(--paper-edge); border-left: 3px solid var(--signal);
  border-radius: var(--r-md); background: var(--paper-raised);
  opacity: 0; transform: translateY(6px);
  transition: opacity .32s ease, transform .32s cubic-bezier(.22,1,.36,1);
}
.scanline.is-in { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) { .scanline { opacity: 1; transform: none; transition: none } }
.scanline-focus { font-family: var(--mono); font-size: .66rem; letter-spacing: .14em; color: var(--signal); }
.scanline-note { margin: 0; line-height: 1.5; }
.scanline-action { margin: 0; color: var(--ink-3); font-size: .92rem; line-height: 1.5; }
.scan-summary { margin: var(--s3) 0 0; font-size: 1.05rem; line-height: 1.55; }
.scan-abort { margin: var(--s3) 0 0; color: var(--clay); line-height: 1.55; }

.shotgrid { display: grid; gap: var(--s4); grid-template-columns: repeat(auto-fill, minmax(9rem, 1fr)); }
.shot { display: grid; gap: 6px; justify-items: start; }
.shot img { width: 100%; aspect-ratio: 3/4; object-fit: cover; border-radius: var(--r-md); border: 1px solid var(--paper-edge); }

/* ============================================================
   THE READOUT
   Four facts at the top of Today. Instrument, not dashboard: mono labels,
   display numerals, a hairline grid, no colour used decoratively. Every
   number here is one the member earned and none of them can go down, which
   is why it can be shown this plainly without ever feeling like a score.
   ============================================================ */
.readout {
  display: grid; grid-template-columns: repeat(2, 1fr);
  margin: var(--s5) 0 var(--s6); padding: 0;
  border: 1px solid var(--paper-edge); border-radius: var(--r-md);
  overflow: hidden; background: var(--paper-raised);
}
@media (min-width: 640px) { .readout { grid-template-columns: repeat(4, 1fr); } }
.readout > div {
  padding: var(--s4) var(--s4) calc(var(--s4) + 2px);
  border-right: 1px solid var(--paper-edge);
  border-bottom: 1px solid var(--paper-edge);
  min-width: 0;
}
/* close the grid: no trailing rules on the last column or row */
@media (min-width: 640px) { .readout > div:nth-child(4n) { border-right: 0 } .readout > div { border-bottom: 0 } }
@media (max-width: 639px) { .readout > div:nth-child(2n) { border-right: 0 } .readout > div:nth-last-child(-n+2) { border-bottom: 0 } }
.readout dt {
  font-family: var(--mono); font-size: .64rem; letter-spacing: .16em;
  text-transform: uppercase; color: var(--ink-3);
}
.readout dd {
  margin: 6px 0 0; font-family: var(--disp); font-weight: 700;
  font-size: clamp(1.5rem, 4.5vw, 2rem); line-height: 1; letter-spacing: -0.02em;
  display: flex; align-items: baseline; gap: 6px;
}
.readout dd span {
  font-family: var(--mono); font-size: .66rem; font-weight: 500;
  letter-spacing: .1em; color: var(--ink-3);
}
/* the habit is words, so it drops to body scale and wraps instead of clipping */
.readout dd.readout-word {
  font-family: var(--body); font-weight: 600; font-size: .95rem;
  line-height: 1.3; letter-spacing: 0; display: block;
}

/* the cadence line under the Next session head: a fact, not a chip */
.cadence {
  margin: 0 0 var(--s3); font-family: var(--mono); font-size: .72rem;
  letter-spacing: .06em; color: var(--ink-3);
}

/* ---------- the scan field ----------
   A reading surface, not a picture of anyone. The canvas is aria-hidden
   because every mark it makes is also spoken as text in the list below. */
.scanfield {
  position: relative; margin-top: var(--s5);
  border: 1px solid var(--paper-edge); border-radius: var(--r-md);
  background: var(--paper-sunk); overflow: hidden;
  aspect-ratio: 16 / 7;
}
.scanfield canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
/* the status rides on the field, bottom left, like a readout on an instrument */
.scanfield .scan-status {
  position: absolute; left: var(--s4); bottom: var(--s4); margin: 0;
  display: flex; align-items: center; gap: 8px;
  font-family: var(--mono); font-size: .66rem; letter-spacing: .14em;
  text-transform: uppercase; color: var(--ink-2);
  background: color-mix(in srgb, var(--paper) 78%, transparent);
  padding: 6px 10px; border-radius: var(--r-full);
  backdrop-filter: blur(6px);
}
@media (max-width: 520px) { .scanfield { aspect-ratio: 4 / 3 } }

/* ---------- dictation ----------
   The mic sits inside the field's own box so it reads as part of the control
   rather than a separate action. Created by JS only when the browser supports
   it, so this styling never applies to a field that cannot use it. */
.dictate { position: relative; display: block; }
.dictate > textarea, .dictate > input { width: 100%; padding-right: 48px; }
.dictate-btn {
  position: absolute; top: 8px; right: 8px;
  display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; padding: 0;
  border: 1px solid var(--paper-edge); border-radius: var(--r-full);
  background: var(--paper-raised); color: var(--ink-3); cursor: pointer;
  transition: color .18s ease, border-color .18s ease, background-color .18s ease;
}
.dictate-btn:hover { color: var(--ink); border-color: var(--ink-4); }
.dictate-btn:focus-visible { outline: 2px solid var(--signal); outline-offset: 2px; }
.dictate.is-listening .dictate-btn { color: var(--on-signal); background: var(--signal); border-color: var(--signal); }
/* a slow pulse while live, because a hot mic must never be ambiguous */
.dictate.is-listening .dictate-btn::after {
  content: ""; position: absolute; inset: -4px; border-radius: inherit;
  border: 2px solid var(--signal); opacity: .5; animation: dictate-pulse 1.6s ease-out infinite;
}
@keyframes dictate-pulse { to { transform: scale(1.35); opacity: 0 } }
@media (prefers-reduced-motion: reduce) {
  .dictate.is-listening .dictate-btn::after { animation: none; opacity: .6 }
}
.dictate-status {
  margin: var(--s2) 0 0; font-size: .82rem; line-height: 1.4; color: var(--ink-3);
  min-height: 1.1em;
}

/* ============================================================
   PLATFORM LAYER
   The details that decide whether a web app reads as an app or as a website
   in a browser. None of it is decorative; each rule fixes a specific tell.
   ============================================================ */

/* 1. The grey flash on tap is the loudest "this is a web page" signal there
      is. Removing it without replacing the feedback is worse, so every
      interactive thing gets a real pressed state below. */
a, button, [role="button"], label, summary, .choice, .floor-item, .ck-opt, .tiercard, .skucard {
  -webkit-tap-highlight-color: transparent;
}
/* 2. touch-action: manipulation kills the 300ms double-tap-zoom wait on
      controls, which is what makes taps feel laggy rather than instant. */
a, button, [role="button"], input, select, textarea, label, summary {
  touch-action: manipulation;
}
/* 3. Pressed states, since the highlight is gone. Scale is deliberately tiny:
      enough to feel, not enough to look like a toy. */
@media (hover: none) {
  button:active, .btn:active, [role="button"]:active,
  .choice:active, .floor-item:active, .ck-opt:active, .skucard:active, .tiercard:active {
    transform: scale(.985);
  }
  .btn, button, .choice, .floor-item, .ck-opt, .skucard, .tiercard { transition: transform .08s ease-out; }
}
@media (prefers-reduced-motion: reduce) {
  button:active, .btn:active, [role="button"]:active,
  .choice:active, .floor-item:active, .ck-opt:active, .skucard:active, .tiercard:active { transform: none; }
}

/* 4. Scroll chaining. Without this, scrolling past the end of a panel drags
      the page behind it, which no native app does. */
html { overscroll-behavior-y: none; }
body { overscroll-behavior: none; }

/* 5. iOS silently inflates text in landscape unless told not to. */
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }

/* 6. Any control under 16px makes iOS zoom the whole page on focus, and the
      page never zooms back. This is a floor, not a style. */
input, select, textarea { font-size: max(16px, 1rem); }

/* 7. Chrome, not content, should not be selectable: long-pressing a nav label
      and getting a text-selection popover is a browser behaviour, not an app
      one. Body copy stays selectable on purpose. */
.appbar, .tabbar, .xheader, .xnav, .dictate-btn, .readout dt { -webkit-user-select: none; user-select: none; }

/* 8. Fixed chrome has to clear the notch in landscape too, not just the home
      indicator at the bottom. */
.appbar, .xheader { padding-top: env(safe-area-inset-top); }
.appbar, .xheader, .tabbar, main, .wrap {
  padding-left: max(var(--edge, 0px), env(safe-area-inset-left));
  padding-right: max(var(--edge, 0px), env(safe-area-inset-right));
}

/* 9. Touch targets. WCAG 2.2 asks 24px; native guidance asks 44. Chrome takes
      the larger number because a mistap in a nav is more costly than one in a
      list. */
.tabbar a, .appbar a, .appbar button, .dictate-btn { min-height: 44px; min-width: 44px; }

/* 10. In an installed app there is no browser chrome to fall back on, so the
       standalone class (set by app.js) gets a little more room at the top and
       loses anything that only makes sense in a tab. */
.is-standalone .appbar { padding-top: max(env(safe-area-inset-top), 12px); }

/* the standalone back control: only ever inserted when there is somewhere to go */
.appbar-back {
  display: inline-flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; margin-right: 4px; padding: 0;
  background: none; border: 0; color: var(--ink-2); cursor: pointer;
  border-radius: var(--r-full);
}
.appbar-back:active { background: var(--paper-sunk); }
.appbar-back:focus-visible { outline: 2px solid var(--signal); outline-offset: 2px; }

/* a saved copy must never read as a live one */
.offline-note {
  position: sticky; top: 0; z-index: 60;
  padding: 10px max(var(--s4), env(safe-area-inset-left)) 10px max(var(--s4), env(safe-area-inset-right));
  padding-top: calc(10px + env(safe-area-inset-top));
  background: var(--caution-soft); color: var(--caution);
  font-size: .84rem; line-height: 1.4; text-align: center;
}

/* Invitation link row. The field is readonly and full width so the link is
   legible on a phone before anyone presses anything. */
.copyrow { display: flex; gap: var(--s2); align-items: center; flex-wrap: wrap; }
.copyfield {
  flex: 1 1 16rem; min-width: 0; padding: .7rem .9rem;
  font: 500 .92rem/1.2 var(--font-mono, ui-monospace, monospace);
  color: var(--ink); background: var(--surface-2, transparent);
  border: 1px solid var(--line); border-radius: var(--r2, 10px);
}
.copyfield:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* ---- the buy line -------------------------------------------------------
   Deliberately quieter than the protocol above it and visually separated, so
   the advice never reads as an advert. The cost per day leads because it is
   the number that makes an honest comparison possible. */
.buyline { margin-top: var(--s4); padding-top: var(--s4); border-top: 1px solid var(--line); }
.buyline-head { display: flex; align-items: baseline; gap: var(--s3); flex-wrap: wrap; }
.buyline-price { font: 600 1.35rem/1 var(--font-display, inherit); color: var(--ink); }
.buyline-price em { font: 400 .85rem/1 inherit; color: var(--ink-3); font-style: normal; }
.buyline-sub { font-size: .85rem; color: var(--ink-3); }
.buyline-note { margin: var(--s3) 0 var(--s4); font-size: .88rem; line-height: 1.6; color: var(--ink-2); }
.buyline-none { margin: var(--s4) 0 0; padding-top: var(--s4); border-top: 1px solid var(--line);
  font-size: .88rem; color: var(--ink-3); }

/* ---- the Sunday Reset ---------------------------------------------------
   Four buttons, each a submit, so it works with no JavaScript at all. Sized
   for a thumb because it is answered on a phone on a Sunday. */
.weekgrid { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--s3); margin-top: var(--s4); }
@media (max-width: 30rem) { .weekgrid { grid-template-columns: 1fr; } }
.weekopt {
  display: flex; flex-direction: column; gap: 4px; text-align: left;
  padding: var(--s4); min-height: 4.5rem; cursor: pointer;
  background: var(--surface-2, transparent); color: var(--ink);
  border: 1px solid var(--line); border-radius: var(--r2, 10px);
  transition: border-color .16s ease, transform .16s ease;
}
.weekopt:hover { border-color: var(--accent); }
.weekopt:active { transform: translateY(1px); }
.weekopt:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.weekopt-label { font-weight: 600; font-size: 1rem; }
.weekopt-hint { font-size: .84rem; line-height: 1.45; color: var(--ink-3); }
@media (prefers-reduced-motion: reduce) { .weekopt { transition: none; } }
