/* ── Host reset ───────────────────────────────────────────────────
   The claude.ai artifact runtime wraps the page in this; the standalone
   build supplies it so dev and the published artifact render the same. */
:root{
  padding-top: env(safe-area-inset-top, 0px);
  padding-bottom: env(safe-area-inset-bottom, 0px);
}
img{ max-width: 100%; }
[hidden]{ display: none !important; }

/* ── Design system ───────────────────────────────────────────────
   Shader glass. Black ground with a live WebGL mesh gradient behind
   everything, content floating on it in frosted panes. Palette, the
   SVG filter set (glass / glow) and the light-black-italic
   type ladder all come from the Paper Shaders hero.

   Committed dark on purpose: every surface paints its own colour so
   the page holds whatever ground the host puts behind it.

   Type: Bricolage Grotesque display (200 → 800, the weight ladder is
   the signature), Anuphan for Thai and UI, DM Mono for figures.     */
:root{
  color-scheme: dark;

  --radius: 1.5rem;
  --radius-sm: calc(var(--radius) - 12px);
  --radius-md: calc(var(--radius) - 6px);
  --gutter: clamp(12px, 3.6vw, 20px);
  /* The content column, read by the shell and by the fixed header that
     has to sit exactly on top of it. */
  --shell-w: 560px;
  /* Replaced with the measured height the moment the header mounts. It
     errs high on purpose: a few spare pixels above the first card are
     invisible, whereas a few too few hide a control behind the bar. */
  --topbar-h: 148px;
  --pad-card: clamp(14px, 4.2vw, 22px);

  --black: #000000;
  --ink: #ffffff;
  --cyan: #06b6d4;
  --cyan-deep: #0891b2;
  --teal: #164e63;
  --orange: #f97316;

  --background: var(--black);
  /* A trace of the theme in the prose, and more of it in the headings. */
  --foreground: color-mix(in oklab, var(--ink) 92%, var(--tone));
  --heading: color-mix(in oklab, var(--ink) 82%, var(--tone));
  --muted-foreground: color-mix(in oklab, rgba(255,255,255,0.74) 92%, var(--tone));
  --faint: rgba(255,255,255,0.56);
  --border: rgba(255,255,255,0.12);
  --border-soft: rgba(255,255,255,0.07);
  --pane: rgba(255,255,255,0.05);
  --pane-2: rgba(255,255,255,0.08);
  --well: rgba(0,0,0,0.35);
  --well-2: rgba(0,0,0,0.42);
  /* Solid-ish surfaces. --card is the small inset block inside a pane;
     --sheet and --bar are the two things that must stay opaque enough
     to read while the shader moves underneath them. */
  --card: rgba(255,255,255,0.055);
  --sheet: rgba(14,14,17,0.97);
  --bar: rgba(9,9,11,0.96);
  --scrim: linear-gradient(180deg, rgba(0,0,0,0.62) 0%, rgba(0,0,0,0.80) 46%, rgba(0,0,0,0.90) 100%);
  --shadow-lg: 0 16px 38px rgba(0,0,0,0.55);
  --toast-bg: rgba(255,255,255,0.96);
  --toast-fg: #000;
  --pane-hi: rgba(255,255,255,0.075);
  --pane-lo: rgba(255,255,255,0.045);
  /* The lit top lip of a pane, and the same hairline sunk into a well. */
  --edge: rgba(255,255,255,0.28);
  /* Painted under the shader canvas, and all there is without it. */
  --ground-base: var(--black);
  --inset-hi: rgba(255,255,255,0.05);
  --destructive: #f87171;
  --ring: var(--cyan);

  /* Overridden per person below; defined here so nothing renders tone-less. */
  --tone: var(--cyan);
  --tone-2: var(--cyan-deep);
  --tone-fg: #04212b;
  /* Text in the theme colour. On black the tone already carries; the
     light block below is where it has to be pulled down to read. */
  --tone-ink: var(--tone);

  --font-display: "Bricolage Grotesque", "Anuphan", system-ui, sans-serif;
  --font-sans: "Anuphan", "Bricolage Grotesque", system-ui, sans-serif;
  --font-mono: "DM Mono", ui-monospace, monospace;

  --ease: cubic-bezier(.2,.85,.25,1);
}

/* Each account picks its own theme; the app writes the tokens onto the
   root as inline custom properties, which beat any selector. These are
   only what shows for the frame before that runs. */
:root{ --tone-3: var(--orange); }
[data-profile="net"]{ --tone: var(--cyan);   --tone-2: var(--cyan-deep); --tone-3: var(--orange); --tone-fg: #04212b; }
[data-profile="mee"]{ --tone: #FFCB56;       --tone-2: #FFA259;          --tone-3: #FF7E7E;       --tone-fg: #31200a; }

/* Light mode. Ink and paper swap, and every translucent white becomes a
   translucent ink so the frosting still reads as frosting. The panes go
   nearly opaque: over a live gradient, a 5% tint that worked on black is
   invisible on white. */
:root[data-mode="light"]{
  color-scheme: light;

  --background: #eceff4;
  --foreground: color-mix(in oklab, #10141b 92%, var(--tone));
  --heading: color-mix(in oklab, #10141b 82%, var(--tone));
  --muted-foreground: color-mix(in oklab, rgba(16,20,27,0.78) 90%, var(--tone));
  /* Same hue, enough weight to sit on paper. */
  --tone-ink: color-mix(in oklab, var(--tone) 58%, #0b0f15);
  --faint: rgba(16,20,27,0.62);
  --border: rgba(16,20,27,0.14);
  --border-soft: rgba(16,20,27,0.075);

  --pane: rgba(255,255,255,0.74);
  --pane-2: rgba(255,255,255,0.88);
  --pane-hi: rgba(255,255,255,0.90);
  --pane-lo: rgba(255,255,255,0.74);

  --well: rgba(16,20,27,0.055);
  --well-2: rgba(16,20,27,0.075);
  --card: rgba(255,255,255,0.78);
  --sheet: rgba(250,251,253,0.98);
  --bar: rgba(250,251,253,0.96);
  --edge: rgba(255,255,255,0.95);
  --ground-base: #e7ebf1;
  --inset-hi: rgba(255,255,255,0.65);
  --scrim: linear-gradient(180deg, rgba(240,243,248,0.66) 0%, rgba(240,243,248,0.84) 46%, rgba(240,243,248,0.93) 100%);
  --shadow-lg: 0 16px 38px rgba(16,20,27,0.16);
  --toast-bg: rgba(16,20,27,0.94);
  --toast-fg: #fff;
  --destructive: #d13b3b;
}

*{ box-sizing: border-box; }

/* A mode or theme change should read as the page turning over, not as a
   hard cut; anything that repaints on that switch eases into it. */
body, .pane, .card, .tabbar, .subnav button, .tabbtn,
.friendrow, .moderow button, .pagepill, .well, .btn{
  transition: background-color .28s var(--ease), border-color .28s var(--ease),
              color .28s var(--ease);
}
/* Taps should feel like they landed, and never fire a 300ms delay or a
   grey flash on the way. */
button, a, [role="button"]{ -webkit-tap-highlight-color: transparent; touch-action: manipulation; }
button:active:not(:disabled):not(.grip):not(.tabbtn){ transform: scale(.975); }
button{ transition: transform .12s var(--ease); }
@media (prefers-reduced-motion: reduce){
  *, *::before, *::after{
    animation-duration: .001ms !important; animation-iteration-count: 1 !important;
    transition-duration: .001ms !important; scroll-behavior: auto !important;
  }
}
html, body{ margin:0; }
html{
  /* iOS enlarges text in landscape unless this says otherwise, which is
     where the header has the least room to give. */
  -webkit-text-size-adjust: 100%; text-size-adjust: 100%;
  /* No rubber-band past the ends, and no pull-to-refresh: dragging a list
     should not expose the page behind it or throw the session away. */
  overscroll-behavior-y: none;
  height: 100%;
}
body{
  overscroll-behavior-y: none;
  min-height: 100%;
  /* A long press on a control is a long press, not a text selection with a
     magnifier and a copy menu. Anything readable opts back in below. */
  -webkit-touch-callout: none;
  -webkit-user-select: none; user-select: none;
}
/* Everything a person might actually want to copy. */
p, h1, h2, h3, li, td, th, .readout, .lead-num, .kcal, .hero-note, .mono,
input, textarea, .en, .dose, .stat, .helpwho, .theme-note, .lede{
  -webkit-user-select: text; user-select: text; -webkit-touch-callout: default;
}
body{
  background: var(--background);
  color: var(--foreground);
  font-family: var(--font-sans);
  font-size: clamp(14.5px, 3.9vw, 15.5px);
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  -webkit-tap-highlight-color: transparent;
}
button, input, select, textarea{ font: inherit; color: inherit; }
h1,h2,h3{ margin:0; text-wrap: balance; font-family: var(--font-display); }
svg#shader-filters{ position:absolute; width:0; height:0; }

/* ── The shader ground ────────────────────────────────────────────
   Two stacked mesh gradients, the second wireframe-ish via blend, as
   in the reference. The CSS gradient underneath is what shows when
   WebGL or the CDN is unavailable, so the page is never bare black. */
.ground{
  position: fixed; inset: 0; z-index: 0; pointer-events: none;
  background:
    radial-gradient(90rem 60rem at 12% -10%, rgba(6,182,212,0.30), transparent 60%),
    radial-gradient(70rem 50rem at 108% 18%, rgba(249,115,22,0.22), transparent 62%),
    radial-gradient(60rem 60rem at 50% 118%, rgba(22,78,99,0.55), transparent 65%),
    var(--ground-base);
}
.ground canvas{ position:absolute; inset:0; width:100%; height:100%; display:block; }
/* The gradient repaints constantly, so it stays on a layer of its own:
   the bars and cards above it are then composited, not repainted. */
.ground{ contain: layout paint; will-change: transform; transform: translateZ(0); }
.ground.dim::after{
  content:''; position:absolute; inset:0;
  background: var(--scrim);
}

/* ── Glass ────────────────────────────────────────────────────────
   One pane recipe, spent by role: a hairline that catches light at
   the top edge, a frosted fill, and nothing else. No shadows — depth
   comes from the gradient burning through. */
.pane{
  background: linear-gradient(180deg, var(--pane-hi), var(--pane-lo));
  border: 1px solid var(--border);
  position: relative;
}
.pane::before{
  content:''; position:absolute; top:0; left:12px; right:12px; height:1px;
  background: linear-gradient(90deg, transparent, var(--edge), transparent);
  pointer-events:none;
}
.well{
  background: var(--well);
  border: 1px solid var(--border-soft);
  box-shadow: inset 0 1px 0 var(--inset-hi);
}
.frost{ filter: url(#glass-effect); }

/* ── Motion ───────────────────────────────────────────────────────── */
@keyframes grow{ from{ transform: scaleX(0); } }
@keyframes panel-in{ from{ opacity:0; transform: translateY(8px); } }
@keyframes pulse-soft{ 50%{ opacity:.55; } }
@keyframes lead-pop{ from{ opacity:0; transform: scale(.72); } }
@keyframes bar-rise{ from{ transform: scaleY(0); } }
@keyframes spin{ to{ transform: rotate(360deg); } }
@keyframes drift{ to{ background-position: 200% 50%; } }
.grow-bar{ animation: grow 800ms var(--ease) both; transform-origin:left; }
.timer-live{ animation: pulse-soft 1s steps(2) infinite; }
.panel > *{ animation: panel-in 210ms var(--ease) both; }
.panel > *:nth-child(2){ animation-delay: 26ms; }
.panel > *:nth-child(3){ animation-delay: 48ms; }
.panel > *:nth-child(4){ animation-delay: 66ms; }
.panel > *:nth-child(n+5){ animation-delay: 80ms; }
/* The sub-navigation is the one thing that does not change when you use
   it, so it should not flinch every time a chip is tapped. */
.panel > .subnav{ animation: none; }
@media (prefers-reduced-motion: reduce){
  .grow-bar, .timer-live, .panel > *, .lead-num, .chart rect, .spin, .rotator, .drifting{ animation: none; }
  *{ transition: none !important; }
}

/* ── Shell ────────────────────────────────────────────────────────── */
.shell{
  position: relative; z-index: 1;
  max-width: var(--shell-w); margin: 0 auto;
  padding-left: var(--gutter); padding-right: var(--gutter); padding-bottom: 136px;
  padding-top: var(--topbar-h);
}
/* A real bar, not a fade. It runs edge to edge, closes with a hairline
   and a rounded lip, and mirrors the tab bar at the other end of the
   screen so the two pieces of chrome read as one frame around the app.
   The old gradient-to-transparent left a visible seam mid-air. */
.topbar{
  position: fixed; top: env(safe-area-inset-top, 0px); z-index: 8;
  left: 50%; transform: translateX(-50%);
  width: 100%; max-width: var(--shell-w);
  padding: 14px var(--gutter) 16px;
  background: var(--bar);
  border-bottom: 1px solid var(--border);
  border-radius: 0 0 var(--radius) var(--radius);
}
/* Scrolled content must not be visible in the gap above a sticky bar, so
   the bar carries its own backing up through the safe area. */
.topbar::before{
  content:''; position:absolute; left:0; right:0; bottom:100%;
  height: calc(env(safe-area-inset-top, 0px) + 24px);
  background: var(--bar);
  pointer-events:none;
}
/* the person's colour, as a light along the closing edge */
.topbar::after{
  content:''; position:absolute; bottom:-1px; height:1px;
  left: var(--gutter); right: var(--gutter);
  background: linear-gradient(90deg, transparent, color-mix(in oklab, var(--tone) 75%, transparent), transparent);
}

/* Identity on one line, page title under it — the chip is no longer a
   loose object floating beside a three-line stack. */
.topline{ display:flex; align-items:center; justify-content:space-between; gap:10px; }
/* The mark is short and fixed, so it holds its width; what gives under
   pressure is the name in the chip, which has an ellipsis for it. */
.mark{ display:flex; align-items:center; gap:9px; min-width:0; flex: 0 0 auto; }
/* The plate is gone from the artwork, so the mark sits directly on the
   bar at its own proportions rather than inside a rounded tile. */
.mark .logo{ height:25px; width:auto; flex-shrink:0; display:block; }
.eyebrow{
  font-family: var(--font-display);
  font-size: 11.5px; font-weight: 700; letter-spacing: .2em; text-transform: uppercase;
  color: var(--muted-foreground); white-space: nowrap;
}
.pagehead{ margin-top: 13px; }
/* Leaving the settings screen is the only thing on it you can get wrong,
   so the way out sits above the title rather than beside it. */
.backbtn{
  display:inline-flex; align-items:center; gap:4px; cursor:pointer;
  background:none; border:none; padding: 0 0 6px; margin:0;
  color: var(--muted-foreground); font: inherit; font-size:13px; font-weight:600;
}
.backbtn svg{ width:17px; height:17px; fill:none; stroke:currentColor; stroke-width:2;
  stroke-linecap:round; stroke-linejoin:round; }
.backbtn:hover{ color: var(--tone-ink); }
.backbtn:focus-visible{ outline:2px solid var(--ring); outline-offset:2px; border-radius:6px; }
.pagehead h1{
  color: var(--heading);
  font-size: clamp(26px, 7.6vw, 36px); font-weight: 800; line-height: 1.0;
  letter-spacing: -.035em; font-variation-settings: "opsz" 40;
}
.pagehead .sub{ color: var(--muted-foreground); font-size: clamp(12px, 3.4vw, 13.5px); margin-top: 5px; }

.me{
  display:flex; align-items:center; gap:8px; min-width:0; flex: 0 1 auto;
  background: var(--card); border: 1px solid var(--border);
  border-radius: 999px; padding: 4px 11px 4px 5px;
  color: inherit; font: inherit; cursor: pointer; max-width: 46vw;
  transition: border-color .25s var(--ease), background .25s var(--ease);
}
.me .nm{ overflow:hidden; text-overflow:ellipsis; min-width:0; }
.me:hover{ border-color: color-mix(in oklab, var(--tone) 50%, transparent); }
.me[aria-pressed="true"]{
  background: color-mix(in oklab, var(--tone) 16%, transparent);
  border-color: color-mix(in oklab, var(--tone) 46%, transparent);
}
.me:focus-visible{ outline:2px solid var(--ring); outline-offset:2px; }
/* No picture yet: the initial keeps the chip the same size either way. */
.me .av.blank{
  display:flex; align-items:center; justify-content:center;
  background: color-mix(in oklab, var(--tone) 22%, transparent);
  color: var(--tone-ink); font-size:12px; font-weight:700; text-transform:uppercase;
}
.me[data-state="saved"]{ border-color: color-mix(in oklab, var(--tone) 38%, transparent); }

/* ── Theme picker ─────────────────────────────────────────────────
   The button wears the theme it will change, so it needs no label. */
.topline-right{ display:flex; align-items:center; gap:8px; min-width:0; flex: 0 1 auto; }
/* The header form of .iconbtn (declared with the list buttons further
   down): a size larger, circular, and carrying its own surface so it
   reads as a control on the bar rather than a floating glyph. */
.iconbtn.round{
  width:34px; height:34px; padding:0; border-radius:999px;
  background: var(--card); border:1px solid var(--border);
  color: var(--muted-foreground);
}
.iconbtn.round svg{ width:19px; height:19px; }
.iconbtn.round:hover{
  color: var(--tone-ink);
  border-color: color-mix(in oklab, var(--tone) 50%, transparent);
}
.iconbtn:focus-visible{ outline:2px solid var(--ring); outline-offset:2px; }

/* ── Dialog ───────────────────────────────────────────────────────
   Centred on a desktop, resting on the bottom edge of a phone where the
   thumb already is. It never scrolls the page behind it away. */
/* The inset lives on the wrapper. On the card it would be added to a
   full-width box and push it past the edge of the screen. */
.modal{
  position: fixed; inset: 0; z-index: 30; display:flex;
  align-items: flex-end; justify-content: center;
  padding: 0 var(--gutter) calc(var(--gutter) + env(safe-area-inset-bottom, 0px));
}
.modal-scrim{
  position:absolute; inset:0;
  background: color-mix(in oklab, var(--background) 62%, transparent);
  animation: fade-in 180ms var(--ease) both;
}
.helpcard{
  position: relative; z-index: 1;
  width: 100%; max-width: 480px; max-height: 84vh; overflow-y: auto;
  margin: 0;
  padding: var(--pad-card);
  border-radius: var(--radius);
  background: var(--sheet);
  box-shadow: var(--shadow-lg);
  animation: sheet-up 240ms var(--ease) both;
}
@keyframes fade-in{ from{ opacity:0; } }
@keyframes sheet-up{ from{ opacity:0; transform: translateY(18px); } }

.helplist{ display:flex; flex-direction:column; gap:2px; margin-top: 14px; }
.helprow{ display:flex; align-items:flex-start; gap:12px; padding: 9px 0; }
.helprow + .helprow{ border-top: 1px solid var(--border-soft); }
.helpicon{
  display:flex; align-items:center; justify-content:center; flex:none;
  width:30px; height:30px; border-radius:9px; margin-top:1px;
  background: color-mix(in oklab, var(--tone) 16%, transparent);
  color: var(--tone-ink);
}
.helpicon svg{ width:17px; height:17px; fill:none; stroke:currentColor; stroke-width:1.9;
  stroke-linecap:round; stroke-linejoin:round; }
.helpwho{ display:flex; flex-direction:column; gap:3px; min-width:0; }
.helpwho b{ font-size:13.5px; font-weight:700; }
.helpwho small{ font-size:12px; color: var(--muted-foreground); line-height:1.5; }

@media (min-width: 560px){ .modal{ align-items: center; padding-bottom: var(--gutter); } }

.theme-grid{ display:grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap:9px; }
.theme-opt{
  display:flex; flex-direction:column; gap:9px; cursor:pointer; text-align:left;
  background: var(--well); border: 1px solid var(--border-soft);
  border-radius: var(--radius-sm); padding: 9px; color: inherit; min-width:0;
  transition: border-color .2s var(--ease), background .2s var(--ease);
}
.theme-opt:hover{ border-color: var(--border); }
.theme-opt[aria-pressed="true"]{
  border-color: color-mix(in oklab, var(--tone) 65%, transparent);
  background: color-mix(in oklab, var(--tone) 13%, transparent);
}
.theme-opt:focus-visible{ outline:2px solid var(--ring); outline-offset:2px; }
/* the four bands of the palette, stacked the way a swatch card reads */
.theme-bands{ display:flex; flex-direction:column; height:44px; border-radius:9px; overflow:hidden; }
.theme-bands i{ flex:1; display:block; }
.theme-name{ font-size:12.5px; font-weight:600; letter-spacing:.01em; }
.theme-note{ font-size:11.5px; color: var(--faint); margin: 12px 0 0; line-height:1.5; }
.me .av{ width:24px; height:24px; border-radius:50%; object-fit:cover; flex-shrink:0; }
.me .nm{ font-size:13px; font-weight:600; white-space:nowrap; }
.me .dot{ width:7px; height:7px; border-radius:50%; background: var(--faint); flex-shrink:0; }
.me[data-state="saved"] .dot{ background: var(--tone); box-shadow: 0 0 10px var(--tone); }
.me[data-state="saving"] .dot{ background: var(--orange); animation: pulse-soft .9s infinite; }
.me[data-state="error"] .dot, .me[data-state="local"] .dot{ background: var(--destructive); }

/* ── Segmented ────────────────────────────────────────────────────── */
.seg{
  position: relative; display:grid; gap:6px; padding:5px;
  background: var(--well-2); border: 1px solid var(--border-soft);
  border-radius: var(--radius-md);
}
.seg .thumb{
  position:absolute; top:5px; bottom:5px; left:5px;
  background: var(--pane-2); border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  transition: transform .34s var(--ease); pointer-events:none;
}
.seg button{
  position: relative; z-index:1; border:none; cursor:pointer; background: transparent;
  color: var(--muted-foreground); font-weight: 600; font-size: clamp(13px, 3.6vw, 14.5px);
  padding: 10px 4px; border-radius: var(--radius-sm); min-height: 44px;
  display:flex; align-items:center; justify-content:center; gap:8px;
  transition: color .22s var(--ease);
}
.seg button[aria-pressed="true"]{ color: var(--foreground); }
.seg button:focus-visible{ outline: 2px solid var(--ring); outline-offset: 2px; }

/* ── Cards ────────────────────────────────────────────────────────── */
.content{ display:flex; flex-direction:column; gap:14px; margin-top: 14px; }
.card{ border-radius: var(--radius); padding: var(--pad-card); min-width: 0; }
.content > *{ min-width: 0; }
.card h2{ color: var(--heading); font-size: clamp(18px, 5.2vw, 23px); font-weight: 700; letter-spacing:-.025em; font-variation-settings: "opsz" 28; }
.card-head{ display:flex; align-items:flex-start; justify-content:space-between; gap:10px; flex-wrap:wrap; }
.label{
  font-family: var(--font-display); font-size: 10px; font-weight: 600;
  letter-spacing: .2em; text-transform: uppercase; color: var(--faint);
  margin-bottom: 11px;
}
.lede{ color: var(--muted-foreground); font-size: 14px; margin: 8px 0 0; }
.kicker{ font-size: 11.5px; font-weight: 600; letter-spacing:.06em; color: var(--tone-ink); }

/* Week strip */
.week{ display:flex; gap:7px; overflow-x:auto; padding: 2px 2px 6px; scrollbar-width:none; }
.week::-webkit-scrollbar{ display:none; }
.week .day{
  min-width: clamp(64px, 19vw, 84px); flex-shrink:0; text-align:center; cursor:pointer;
  background: var(--well); border: 1px solid var(--border-soft);
  border-radius: var(--radius-sm); padding: 10px 7px; color: inherit;
  display:flex; flex-direction:column; gap:5px;
  transition: background .25s var(--ease), border-color .25s var(--ease), color .25s var(--ease);
}
.week .day .d{
  font-family: var(--font-display); font-size:10px; font-weight:700;
  letter-spacing:.14em; text-transform:uppercase; color: var(--faint);
}
.week .day .t{ font-size:11px; line-height:1.3; font-weight:500; }
.week .day.sel{
  background: color-mix(in oklab, var(--tone) 22%, transparent);
  border-color: color-mix(in oklab, var(--tone) 55%, transparent);
  box-shadow: 0 0 22px color-mix(in oklab, var(--tone) 28%, transparent);
}
.week .day.sel .d{ color: var(--tone-ink); }
.week .day.off .t{ color: var(--faint); }
.week .day.now::after{ content:''; display:block; height:2px; width:18px; margin:1px auto 0; border-radius:2px; background: var(--tone); }
.week .day:focus-visible{ outline:2px solid var(--ring); outline-offset:2px; }

/* Exercise rows */
.exlist{ display:flex; flex-direction:column; gap:8px; margin-top:12px; }
.exrow{
  display:flex; align-items:center; justify-content:space-between; gap:12px;
  background: var(--well); border: 1px solid var(--border-soft);
  border-radius: var(--radius-sm); padding: 11px 12px 11px 14px;
}
.exrow .en{ font-size: clamp(13.5px, 3.8vw, 15px); font-weight:600; letter-spacing:-.01em; }
.exrow .dose{ font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-size:12px; color: var(--faint); margin-top:2px; }
.exedit{
  display:flex; gap:8px; align-items:center; padding: 9px 10px;
  background: var(--well); border: 1px solid var(--border-soft); border-radius: var(--radius-sm);
}

/* ── Drag to reorder ──────────────────────────────────────────────
   Rows slide out of the way with a transition; the one under the
   finger has it switched off inline so it tracks exactly.          */
.exrow, .exedit{ transition: transform .18s var(--ease), border-color .2s var(--ease); }
.row-lift{
  position: relative; z-index: 5;
  border-color: color-mix(in oklab, var(--tone) 60%, transparent);
  box-shadow: var(--shadow-lg);
  background: color-mix(in oklab, var(--tone) 10%, var(--well));
}
/* while a drag is live, stop the page selecting text under the finger */
body.reordering{ user-select: none; -webkit-user-select: none; }
body.reordering *{ cursor: grabbing !important; }
.grip{
  flex-shrink:0; width:30px; min-height:38px; padding:0; cursor: grab;
  background: none; border: none; color: var(--faint);
  display:flex; align-items:center; justify-content:center;
  touch-action: none;           /* the handle never scrolls the page */
  border-radius: 9px;
}
.grip svg{ width:18px; height:18px; fill:none; stroke:currentColor; stroke-width:2.4; stroke-linecap:round; }
.grip:hover{ color: var(--foreground); }
.grip:focus-visible{ outline:2px solid var(--ring); outline-offset:1px; color: var(--tone-ink); }
.hint{
  font-size:11.5px; color: var(--faint); margin: 10px 0 0; line-height:1.5;
}
.exedit .grow{ display:flex; flex-direction:column; gap:6px; flex:1; min-width:0; }
.exedit input{
  width:100%; max-width:100%; min-width:0; background: var(--card);
  border:1px solid var(--border-soft); border-radius: 12px; padding: 9px 11px;
  font-size:14px; min-height:40px;
}
.exedit input.mono{ font-family: var(--font-mono); font-size:12.5px; }
.exedit input:focus{ outline:2px solid var(--ring); outline-offset:1px; }

.callout{
  display:flex; gap:10px; margin-top:14px; padding: 12px 14px;
  background: var(--well); border: 1px solid var(--border-soft); border-radius: var(--radius-sm);
  font-size:13px; color: var(--muted-foreground); line-height:1.5;
}
.chips{ display:flex; gap:6px; flex-wrap:wrap; justify-content:flex-end; }
.chip{
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  font-size:11.5px; color: var(--muted-foreground);
  background: var(--well); border: 1px solid var(--border-soft);
  border-radius:999px; padding: 4px 11px; white-space:nowrap;
}

/* ── Buttons ──────────────────────────────────────────────────────── */
.btn{
  border:none; cursor:pointer; font-weight:700; font-size: clamp(13.5px, 3.8vw, 15px);
  font-family: var(--font-sans); border-radius: 999px;
  padding: 13px 24px; min-height:48px;
  transition: transform .14s var(--ease), background .25s var(--ease), border-color .25s var(--ease);
}
.btn:active{ transform: scale(.97); }
.btn:focus-visible{ outline: 2px solid var(--ring); outline-offset: 3px; }
.btn[disabled]{ opacity:.45; cursor:default; }
/* The one loud thing on the page: the accent gradient, spent only on
   the action that commits something. */
.cta{
  background: linear-gradient(100deg, var(--tone), var(--tone-2) 55%, var(--tone-3));
  color: var(--tone-fg); font-weight: 800;
  box-shadow: 0 6px 26px color-mix(in oklab, var(--tone) 38%, transparent);
}
.cta:hover{ filter: brightness(1.08); }
.ghost{
  background: var(--pane-2); color: var(--foreground);
  border: 1px solid var(--border);
}
.ghost:hover{ background: var(--pane-2); border-color: color-mix(in oklab, var(--tone) 45%, transparent); }
.btn-sm{
  font-size:12.5px; font-weight:700; padding: 8px 15px; min-height:38px;
  border-radius: 999px; flex-shrink:0;
  background: var(--pane); border: 1px solid var(--border); color: var(--foreground);
}
.btn-sm:hover{ border-color: color-mix(in oklab, var(--tone) 50%, transparent); color: var(--tone-ink); }
.btn-block{ width:100%; }
.btn-row{ display:flex; gap:10px; flex-wrap:wrap; justify-content:center; }
.btn-pair{ display:grid; grid-template-columns: repeat(auto-fit, minmax(130px, 1fr)); gap:10px; }
.btn-pair > *{ min-width: 0; }

/* ── Forms ────────────────────────────────────────────────────────── */
.stack{ display:flex; flex-direction:column; gap:13px; }
.field{ min-width: 0; }
.field label{
  display:block; font-family: var(--font-display); font-size:10px; font-weight:600;
  letter-spacing:.18em; text-transform:uppercase; color: var(--faint); margin-bottom: 6px;
}
.field input, .field select, .field textarea{
  width:100%; max-width:100%; min-width:0;
  background: var(--well); border: 1px solid var(--border-soft);
  border-radius: var(--radius-sm); padding: 12px 14px; font-size: 15px;
  min-height:46px; resize: vertical; color: var(--foreground);
}
/* Safari gives date/time inputs an intrinsic width of their own; without
   this they refuse to shrink and burst out of a grid track. */
.field input[type="date"], .field input[type="number"]{ -webkit-appearance: none; appearance: none; }
.field input[type="date"]::-webkit-date-and-time-value{ text-align: left; }
.field input[type="date"]::-webkit-calendar-picker-indicator{ filter: invert(1) opacity(.5); }
.field input:focus, .field select:focus, .field textarea:focus{ outline: 2px solid var(--ring); outline-offset: 1px; }
.field input::placeholder, .field textarea::placeholder{ color: var(--faint); }
.row2{ display:grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap:11px; }
.row2 > *{ min-width: 0; }

/* ── Log list ─────────────────────────────────────────────────────── */
.daygroup{
  font-family: var(--font-display); font-size:10px; font-weight:600;
  letter-spacing:.18em; text-transform:uppercase; color: var(--faint); margin: 16px 2px 6px;
}
.daygroup:first-of-type{ margin-top: 4px; }
.entry{ display:flex; align-items:flex-start; justify-content:space-between; gap:8px; padding: 12px 2px; border-bottom: 1px solid var(--border-soft); }
.entry:last-child{ border-bottom:none; }
.entry .name{ font-size: clamp(13.5px, 3.8vw, 15px); font-weight:600; }
.entry .result{
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  color: var(--tone-ink); font-size:13px; margin-top:3px;
}
.entry .note{ color: var(--muted-foreground); font-size:12.5px; margin-top:3px; }
.entry .acts{ display:flex; gap:2px; flex-shrink:0; }
.tag, .srcbadge{
  display:inline-block; margin-left:7px; vertical-align:2px;
  font-family: var(--font-display); font-size:9.5px; font-weight:600;
  letter-spacing:.12em; border-radius:999px; padding:2px 9px;
  background: var(--well); border:1px solid var(--border-soft); color: var(--faint);
}
.srcbadge.db, .srcbadge.added{
  background: color-mix(in oklab, var(--tone) 20%, transparent);
  border-color: color-mix(in oklab, var(--tone) 42%, transparent);
  color: var(--tone-ink);
}
.iconbtn{
  background:none; border:none; cursor:pointer; color: var(--faint);
  padding: 6px; border-radius: 10px; min-height:36px; min-width:36px;
  display:flex; align-items:center; justify-content:center;
  transition: color .2s var(--ease);
}
.iconbtn svg{ width:17px; height:17px; fill:none; stroke:currentColor; stroke-width:1.9; stroke-linecap:round; stroke-linejoin:round; }
.iconbtn:hover, .iconbtn:focus-visible{ color: var(--foreground); }
.iconbtn.danger:hover, .iconbtn.danger:focus-visible{ color: var(--destructive); }
.empty{ color: var(--faint); font-size:13.5px; text-align:center; padding: 24px 0; }

/* ── Timer ────────────────────────────────────────────────────────── */
.face{ display:flex; flex-direction:column; align-items:center; gap:18px; padding: clamp(22px, 6vw, 30px) var(--pad-card) 24px; }
.readout{
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  font-size: clamp(42px, 14.5vw, 66px); font-weight:500; letter-spacing:-.05em; line-height:1;
  text-shadow: 0 0 34px color-mix(in oklab, var(--tone) 45%, transparent);
}
.lead{ display:flex; flex-direction:column; align-items:center; gap:10px; }
.lead-num{
  font-family: var(--font-display); font-variant-numeric: tabular-nums;
  font-size: clamp(66px, 22vw, 108px); font-weight:800; line-height:1; color: var(--tone-ink);
  filter: url(#text-glow); animation: lead-pop 340ms var(--ease);
}
.lead-cap{ font-size:12.5px; color: var(--faint); letter-spacing:.14em; text-transform:uppercase; }
.presets{ display:flex; gap:8px; flex-wrap:wrap; justify-content:center; }
.presets button{
  border:1px solid var(--border-soft); cursor:pointer; background: var(--well); min-height:40px;
  font-family: var(--font-mono); font-variant-numeric: tabular-nums; color: var(--muted-foreground);
  font-size:13px; border-radius: 999px; padding: 9px 16px;
  transition: all .22s var(--ease);
}
.presets button[aria-pressed="true"]{
  background: color-mix(in oklab, var(--tone) 22%, transparent);
  border-color: color-mix(in oklab, var(--tone) 55%, transparent); color: var(--tone-ink);
}
.presets button:focus-visible{ outline:2px solid var(--ring); outline-offset:2px; }
.save-wrap{ width:100%; border-top:1px solid var(--border-soft); padding-top:18px; }

/* ── Progress ─────────────────────────────────────────────────────── */
.bar{ height:10px; background: var(--well); border:1px solid var(--border-soft); border-radius:999px; overflow:hidden; margin: 14px 0 12px; }
.bar i{ display:block; height:100%; border-radius:999px; background: linear-gradient(90deg, var(--tone), var(--tone-2)); box-shadow: 0 0 16px color-mix(in oklab, var(--tone) 55%, transparent); }
.ladder{ display:flex; flex-wrap:wrap; gap:6px; }
.step{
  font-size:11.5px; font-weight:600; padding: 6px 13px; border-radius:999px;
  color: var(--faint); background: var(--well); border:1px solid var(--border-soft);
}
.step.done{ color: var(--muted-foreground); border-color: color-mix(in oklab, var(--tone) 30%, transparent); }
.step.now{
  background: color-mix(in oklab, var(--tone) 24%, transparent);
  border-color: color-mix(in oklab, var(--tone) 60%, transparent);
  color: var(--tone-ink); font-weight:700;
}
.latest{ font-size: clamp(14.5px, 4vw, 16px); font-weight:600; margin-top:16px; }
.latest-note{ font-size:12.5px; color: var(--muted-foreground); margin-top:3px; }
.history{ display:flex; flex-direction:column; gap:8px; margin-top:14px; }
.hist{ display:flex; gap:9px; font-size:12.5px; color: var(--faint); }
.hist time{ flex-shrink:0; font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.hist b{ color: var(--muted-foreground); font-weight:600; }
.inline-form{ margin-top:16px; padding-top:16px; border-top:1px solid var(--border-soft); }

/* ── Charts ───────────────────────────────────────────────────────── */
.chart{ width:100%; height:auto; display:block; margin-top: 4px; overflow: visible; }
.chart rect.v{ animation: bar-rise 620ms var(--ease) both; transform-origin: bottom; transform-box: fill-box; }
.chart text{ font-family: var(--font-mono); font-size: 9px; fill: var(--faint); }
.chart line.grid{ stroke: var(--border-soft); stroke-width: 1; }
.chart line.goal{ stroke: var(--orange); stroke-width:1.5; stroke-dasharray: 4 4; }
.stats{ display:grid; grid-template-columns: repeat(auto-fit, minmax(88px, 1fr)); gap:9px; margin-top:14px; }
.stat{ background: var(--well); border:1px solid var(--border-soft); border-radius: var(--radius-sm); padding: 11px 12px; min-width: 0; }
.stat .k{ font-family: var(--font-display); font-size:9.5px; font-weight:600; letter-spacing:.16em; text-transform:uppercase; color: var(--faint); }
.stat .v{ font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-size: clamp(17px, 5vw, 21px); font-weight:500; margin-top:3px; }
.stat .u{ font-size:11px; color: var(--faint); }

/* ── Food ─────────────────────────────────────────────────────────── */
.hits{ display:flex; flex-direction:column; gap:5px; }
.hit{
  display:flex; align-items:center; justify-content:space-between; gap:10px;
  width:100%; text-align:left; cursor:pointer;
  background: var(--well); border: 1px solid var(--border-soft);
  border-radius: var(--radius-sm); padding: 10px 14px; min-height:44px; color: inherit;
  transition: all .18s var(--ease);
}
.hit:hover, .hit:focus-visible{
  background: color-mix(in oklab, var(--tone) 14%, transparent);
  border-color: color-mix(in oklab, var(--tone) 45%, transparent);
}
.hit:focus-visible{ outline: 2px solid var(--ring); outline-offset: 2px; }
.hit-n{ font-size:13.5px; font-weight:600; min-width:0; overflow-wrap:anywhere; }
.hit-k{ font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-size:12px; color: var(--faint); white-space:nowrap; flex-shrink:0; }
.macros{ display:flex; gap:7px; flex-wrap:wrap; margin-top:7px; }
.macro{ font-family: var(--font-mono); font-size:11px; color: var(--faint); background: var(--well); border:1px solid var(--border-soft); border-radius:999px; padding: 3px 10px; }
.kcal{ font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-size: clamp(14px, 4vw, 16px); font-weight:500; white-space:nowrap; color: var(--tone-ink); }
.guessing{ display:flex; align-items:center; gap:9px; color: var(--muted-foreground); font-size:13px; padding: 10px 0 2px; }
.spin{ width:15px; height:15px; border-radius:50%; border:2px solid var(--border); border-top-color: var(--tone-ink); animation: spin .8s linear infinite; }
.who-note{ text-align:center; font-size:12.5px; color: var(--faint); padding: 2px 8px; }

/* ── Hero gate ────────────────────────────────────────────────────
   The one full-bleed moment in the app, laid out like the shader
   reference: type stack bottom-left, pulsing badge bottom-right.   */
.hero{ position: relative; z-index:1; min-height: 100svh; display:flex; flex-direction:column; }
.hero-top{
  display:flex; align-items:center; justify-content:space-between; gap:12px;
  padding: calc(18px + env(safe-area-inset-top, 0px)) var(--gutter) 0;
}
.hero-mark{ display:flex; align-items:center; gap:10px; }
.hero-mark svg{ width:34px; height:34px; fill: currentColor; color: var(--ink); filter: url(#logo-glow); }
/* Centred: this screen asks one question, so the answer sits in the
   middle of it rather than in a marketing hero corner. */
.hero-body{
  margin: auto;
  width: 100%;
  max-width: 40rem;
  padding: 24px var(--gutter) calc(120px + env(safe-area-inset-bottom, 0px));
  text-align: center;
  display: flex; flex-direction: column; align-items: center;
}
.hero-title, .hero-lede{ text-align: center; }
.hero-actions{ justify-content: center; }
.hero-seats{ align-items: center; }
.hero-badge{
  display:inline-flex; align-items:center; gap:8px; position:relative;
  padding: 9px 16px; border-radius: 999px; margin-bottom: 22px;
  background: var(--card); border: 1px solid var(--border);
  backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
  font-size: 13px; color: var(--foreground); letter-spacing: .02em;
}
.hero-badge::before{
  content:''; position:absolute; top:0; left:12px; right:12px; height:1px;
  background: linear-gradient(90deg, transparent, rgba(6,182,212,0.5), transparent);
}
.hero-title{ margin: 0 0 20px; line-height: .92; letter-spacing: -.045em; }
.hero-title span{ display:block; }
/* The weight ladder is the whole idea: light, black, light italic. */
.hero-title .l1{
  font-weight: 250; font-size: clamp(34px, 11vw, 74px); letter-spacing: .01em;
  background: linear-gradient(120deg, var(--foreground) 0%, var(--cyan) 32%, var(--orange) 68%, var(--foreground) 100%);
  background-size: 200% 100%;
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent; color: transparent;
  padding-bottom: .06em;
}
@media (min-width: 900px) and (prefers-reduced-motion: no-preference){
  .hero-title .l1{ animation: drift 9s linear infinite alternate; }
}
.hero-title .l2{ font-weight: 800; font-size: clamp(50px, 17vw, 108px); color: var(--foreground); }
.hero-title .l3{ font-weight: 250; font-style: italic; font-size: clamp(38px, 12vw, 80px); color: var(--muted-foreground); }
.hero-lede{ color: var(--muted-foreground); font-size: clamp(14px, 3.9vw, 17px); max-width: 34rem; margin: 0 0 26px; line-height:1.6; }
.hero-actions{ display:flex; gap: 12px; flex-wrap:wrap; }
.hero-actions .btn{ flex: 1 1 165px; max-width: 240px; }
.hero-actions .btn{ padding: 15px 30px; }
.hero-seats{ margin-top: 30px; display:flex; flex-direction:column; gap:6px; }
.hero-seat{
  font-family: var(--font-mono); font-size:11.5px; color: var(--faint);
  overflow-wrap:anywhere;
}
/* The address a locked-out visitor has to quote to whoever keeps the list:
   boxed and monospaced so it reads as a value to copy, not as prose. */
.hero-note{
  font-family: var(--font-mono); font-size: 13px; color: var(--foreground);
  background: var(--card); border: 1px solid var(--border); border-radius: 10px;
  padding: 10px 16px; margin: -8px 0 26px; overflow-wrap: anywhere;
  user-select: all;
}
.hero-tail{ margin-top: 20px; display:flex; gap:10px; flex-wrap:wrap; justify-content:center; }
.hero-badge-wrap{
  position: fixed; right: var(--gutter); z-index: 3;
  bottom: calc(26px + env(safe-area-inset-bottom, 0px));
  width: 82px; height: 82px; display:flex; align-items:center; justify-content:center;
  pointer-events:none;
}
.hero-orb{ position:relative; width:60px; height:60px; border-radius:50%; }
.hero-orb canvas{ position:absolute; inset:0; width:100%; height:100%; border-radius:50%; }
.hero-orb::after{
  content:''; position:absolute; inset:0; border-radius:50%;
  border:1px solid var(--edge);
  box-shadow: 0 0 30px rgba(6,182,212,0.35);
}
.hero-orb[data-shader="on"]::after{ border-color: transparent; }
.rotator{
  position:absolute; inset:0; width:100%; height:100%;
  transform: scale(1.62); will-change: transform;
  animation: spin 22s linear infinite;
}
.rotator text{ font-size: 9px; fill: var(--muted-foreground); font-family: var(--font-display); letter-spacing:.08em; }

/* ── Tab bar ──────────────────────────────────────────────────────── */
.tabbar{
  position: fixed; left:50%; transform: translateX(-50%); bottom:0; z-index:9;
  width: 100%; max-width: 560px;
  background: var(--bar);
  border-top: 1px solid var(--border);
  border-radius: var(--radius) var(--radius) 0 0;
  padding: 8px 8px calc(8px + env(safe-area-inset-bottom, 0px));
}
.tabrow{ position:relative; display:grid; grid-template-columns: repeat(var(--tabs, 5), 1fr); }
.tabrow .thumb{
  will-change: transform;
  position:absolute; top:0; bottom:0; left:0; width: calc(100% / var(--tabs, 5));
  background: color-mix(in oklab, var(--tone) 18%, transparent);
  border: 1px solid color-mix(in oklab, var(--tone) 40%, transparent);
  border-radius: var(--radius-sm);
  transition: transform .36s var(--ease), background .3s var(--ease), border-color .3s var(--ease);
  pointer-events:none;
}
.tabbtn{
  position:relative; z-index:1; background:none; border:none; cursor:pointer;
  color: var(--faint); display:flex; flex-direction:column; align-items:center; gap:4px;
  font-size: clamp(9px, 2.6vw, 10.5px); font-weight:600; padding: 9px 0 7px;
  border-radius: var(--radius-sm); min-height:52px;
  transition: color .22s var(--ease);
}
.tabbtn svg{ width:20px; height:20px; fill:none; stroke: currentColor; stroke-width:1.9; stroke-linecap:round; stroke-linejoin:round; transition: transform .3s var(--ease); }
.tabbtn[aria-current="page"]{ color: var(--tone-ink); }
.tabbtn[aria-current="page"] svg{ transform: translateY(-2px) scale(1.06); filter: drop-shadow(0 0 8px currentColor); }
.tabbtn:focus-visible{ outline:2px solid var(--ring); outline-offset:-2px; }

/* Sub-navigation inside the middle zone. Five chips do not fit a phone
   evenly, so they scroll rather than shrink to unreadable. */
.subnav{
  display:flex; gap:7px; overflow-x:auto; scrollbar-width:none;
  padding: 2px 0 4px; margin-bottom: 2px;
  scroll-snap-type: x proximity; -webkit-overflow-scrolling: touch;
}
.subnav::-webkit-scrollbar{ display:none; }
.subnav button{
  flex: 0 0 auto; scroll-snap-align: start; cursor:pointer;
  padding: 8px 15px; border-radius: 999px; font-size: 13px; font-weight: 600;
  color: var(--muted-foreground); background: var(--card);
  border: 1px solid var(--border-soft);
  transition: color .2s var(--ease), background .2s var(--ease), border-color .2s var(--ease);
}
.subnav button[aria-selected="true"]{
  color: var(--tone-ink);
  background: color-mix(in oklab, var(--tone) 16%, transparent);
  border-color: color-mix(in oklab, var(--tone) 42%, transparent);
}
.subnav button:focus-visible{ outline:2px solid var(--ring); outline-offset:2px; }

/* Where am I: three icons cannot spell it out, so the name arrives with
   the page and then leaves. Never both this and a toast at once. */
.pagepill{
  position: fixed; left:50%; z-index: 19;
  bottom: calc(92px + env(safe-area-inset-bottom, 0px));
  padding: 7px 16px; border-radius: 999px;
  background: var(--bar); border: 1px solid var(--border);
  color: var(--tone-ink); font-size: 12px; font-weight: 700; white-space: nowrap;
  animation: pill-in 260ms var(--ease) both;
}
@keyframes pill-in{
  from{ opacity:0; transform: translate(-50%, 8px); }
  to{ opacity:1; transform: translate(-50%, 0); }
}
@media (prefers-reduced-motion: reduce){ .pagepill{ animation:none; transform: translateX(-50%); } }

/* ── Toast ────────────────────────────────────────────────────────── */
.toast{
  position: fixed; left:50%; z-index: 20; bottom: calc(96px + env(safe-area-inset-bottom, 0px));
  background: var(--toast-bg); color: var(--toast-fg); max-width: calc(100vw - 32px);
  padding: 11px 20px; border-radius: 999px; font-size:13.5px; font-weight:700; text-align:center;
  animation: toast-in 280ms var(--ease) both;
}
@keyframes toast-in{ from{ opacity:0; transform: translate(-50%, 10px); } to{ opacity:1; transform: translate(-50%, 0); } }
@media (prefers-reduced-motion: reduce){ .toast{ animation:none; transform: translateX(-50%); } }

/* ── Wide screens ─────────────────────────────────────────────────── */
/* Tablet portrait and large phones in landscape: still one column, but a
 * wider one, and the tab bar lifts off the edge into a floating pill
 * rather than spanning a screen twice as wide as it needs.
 */
@media (min-width: 620px){
  :root{ --shell-w: 680px; }
  .tabbar{
    max-width: 420px; bottom: 16px; padding-bottom: 8px;
    border-radius: var(--radius); border: 1px solid var(--border);
  }
}

/* Wide enough for two columns to each be wider than a phone. */
@media (min-width: 900px){
  :root{ --shell-w: 1040px; }
  .shell{ padding-bottom: 120px; }
  .content{ display:grid; grid-template-columns: 1fr 1fr; align-items:start; gap:16px; }
  .content > .span-2{ grid-column: 1 / -1; }
  .tabbar{ max-width: 520px; }
}

/* Short and wide: a phone on its side, or a keyboard open over one. The
 * vertical rhythm of a portrait screen leaves nothing to read here. */
@media (max-height: 540px) and (orientation: landscape){
  .shell{ padding-bottom: 96px; }
  .topbar{ padding-top: 9px; padding-bottom: 10px; }
  .pagehead{ margin-top: 8px; }
  .pagehead h1{ font-size: clamp(20px, 3.4vh, 26px); }
  .face{ padding-top: 14px; padding-bottom: 16px; gap: 12px; }
  .readout{ font-size: clamp(34px, 11vh, 54px); }
  .tabbtn{ min-height: 44px; padding: 6px 0 5px; }
  .authwrap{ padding-top: 16px; padding-bottom: 16px; }
}

/* ── Plan setup ───────────────────────────────────────────────────
   The screen that turns height, weight and a goal into starting
   weights and a weekly template. Everything here is a list of facts,
   so the rows borrow the exercise-row shapes rather than inventing
   new ones; only the template cards are their own thing.          */
.plangrid{ display:grid; gap:10px; margin-top:12px; }
@media (min-width: 620px){ .plangrid{ grid-template-columns: 1fr 1fr; } }
.planopt{
  background: var(--well); border: 1px solid var(--border-soft);
  border-radius: var(--radius-md); padding: 13px 14px;
  transition: border-color .2s var(--ease), background .2s var(--ease);
}
.planopt.on{
  border-color: color-mix(in oklab, var(--tone) 55%, transparent);
  background: color-mix(in oklab, var(--tone) 9%, var(--well));
}
.po-top{ display:flex; align-items:center; justify-content:space-between; gap:10px; }
.po-name{ font-family: var(--font-display); font-weight:700; font-size:16px; letter-spacing:-.01em; }
.po-sub{ font-size:12px; color: var(--faint); margin-top:5px; line-height:1.5; }
.po-days{ display:flex; flex-wrap:wrap; gap:5px; margin-top:9px; }
.po-day{
  font-size:11px; padding:3px 9px; border-radius:999px; white-space:nowrap;
  background: color-mix(in oklab, var(--tone) 12%, transparent);
  border: 1px solid color-mix(in oklab, var(--tone) 26%, transparent);
}
.exrow .grow{ min-width:0; }
.liftkg{ flex:0 0 auto; font-size:14px; color: var(--tone-ink); white-space:nowrap; }
.exmeta{ display:block; font-size:11px; font-weight:400; color: var(--faint); margin-top:3px; }

/* ── Calorie analysis ─────────────────────────────────────────────
   The macro bar and the read-out beneath it. Protein/carb/fat take the
   three theme tones rather than fixed hues, so the panel still reads as
   one thing when the theme changes. The notes are statements, not
   labels, so they sit at body size with a coloured rule on the left. */
.macrobar{
  display:flex; height:10px; margin-top:14px; border-radius:999px; overflow:hidden;
  background: var(--well); border: 1px solid var(--border-soft);
}
.macrobar .mb{ display:block; height:100%; transition: width .35s var(--ease); }
.mb.p{ background: var(--tone); }
.mb.c{ background: var(--tone-2); }
.mb.f{ background: var(--tone-3); }
.macrolegend{
  display:flex; flex-wrap:wrap; gap:6px 14px; margin-top:9px;
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  font-size:11.5px; color: var(--muted-foreground);
}
.macrolegend .dot{ display:inline-block; width:8px; height:8px; border-radius:50%; margin-right:6px; }
.dot.p{ background: var(--tone); }
.dot.c{ background: var(--tone-2); }
.dot.f{ background: var(--tone-3); }

.notes{ list-style:none; margin: 16px 0 0; padding:0; display:flex; flex-direction:column; gap:7px; }
.note{
  font-size:13px; line-height:1.55; padding: 9px 12px;
  border-radius: var(--radius-sm); background: var(--well);
  border: 1px solid var(--border-soft); border-left-width: 3px;
}
.note.good, .note.ok{ border-left-color: color-mix(in oklab, var(--tone) 70%, transparent); }
.note.warn, .note.over{ border-left-color: color-mix(in oklab, var(--tone-3) 80%, transparent); }
.note.burn{ border-left-color: color-mix(in oklab, var(--tone-2) 70%, transparent); }
.note.info, .note.idle{ color: var(--faint); }

/* ── Category browser ─────────────────────────────────────────────
   Sections scroll sideways instead of wrapping into a wall of chips —
   there are thirteen of them under European. */
.sectrow{
  display:flex; gap:6px; margin-top:11px; padding-bottom:4px;
  overflow-x:auto; scrollbar-width:none; -webkit-overflow-scrolling:touch;
}
.sectrow::-webkit-scrollbar{ display:none; }
.sectchip{
  flex:0 0 auto; cursor:pointer; white-space:nowrap;
  background: var(--well); border:1px solid var(--border-soft); color: var(--faint);
  border-radius:999px; padding: 7px 13px; font-size:12.5px; min-height:34px;
  transition: all .18s var(--ease);
}
.sectchip.on{
  color: var(--tone-ink);
  background: color-mix(in oklab, var(--tone) 15%, transparent);
  border-color: color-mix(in oklab, var(--tone) 45%, transparent);
}
.sectchip:focus-visible{ outline:2px solid var(--ring); outline-offset:2px; }

.check{ display:flex; align-items:flex-start; gap:10px; font-size:13px; line-height:1.5; cursor:pointer; }
.check input{ width:18px; height:18px; flex:0 0 auto; margin-top:1px; accent-color: var(--tone-ink); }

/* Seat switch, under the theme grid in the settings sheet. */
.seatswap{
  margin-top: 16px; padding-top: 15px;
  border-top: 1px solid var(--border-soft);
}

/* Profile editor. The picture leads because it is the part you check by
   looking; the buttons sit beside it so the row stays one line on a phone. */
.card > form.seatswap:first-child{ margin-top:0; padding-top:0; border-top:none; }
.avatarrow{ display:flex; align-items:center; gap:14px; }
.avatar{
  width:64px; height:64px; border-radius:50%; object-fit:cover; flex:none;
  border:1px solid var(--border); background: var(--well);
}
.avatar.blank{
  display:flex; align-items:center; justify-content:center;
  font-family: var(--font-display); font-size:26px; font-weight:700;
  color: var(--tone-ink); text-transform: uppercase;
}
.avatarbtns{ display:flex; flex-direction:column; gap:6px; align-items:flex-start; min-width:0; }

/* Colour mixer. The strip above the swatches is the theme as it would
   look, so the choice is judged before it is applied, not after. */
.mixer{ margin-top: 12px; }
.mixbar{ height: 34px; border-radius: var(--radius-sm); border:1px solid var(--border);
  margin-bottom: 14px; }
.mixrow{ display:flex; align-items:center; gap:12px; padding: 7px 0; cursor:pointer; }
.mixrow input[type="color"]{
  width:44px; height:34px; flex:none; padding:0; cursor:pointer;
  background:none; border:1px solid var(--border); border-radius:9px;
}
.mixrow input[type="color"]::-webkit-color-swatch-wrapper{ padding:3px; }
.mixrow input[type="color"]::-webkit-color-swatch{ border:none; border-radius:6px; }
.mixwho{ display:flex; flex-direction:column; gap:2px; min-width:0; font-size:13px; font-weight:600; }
.mixwho small{ font-size:11px; font-weight:400; color: var(--faint); }

/* Light / dark switch. */
.moderow{ display:flex; gap:8px; margin-bottom: 14px; }
.moderow button{
  flex:1; cursor:pointer; padding: 10px 12px; border-radius: var(--radius-sm);
  font-size: 13px; font-weight: 600; color: var(--muted-foreground);
  background: var(--card); border: 1px solid var(--border-soft);
  transition: color .2s var(--ease), background .2s var(--ease), border-color .2s var(--ease);
}
.moderow button[aria-pressed="true"]{
  color: var(--tone-ink);
  background: color-mix(in oklab, var(--tone) 16%, transparent);
  border-color: color-mix(in oklab, var(--tone) 42%, transparent);
}
.moderow button:focus-visible{ outline:2px solid var(--ring); outline-offset:2px; }

/* Friends: a row is one person and the one or two things you can do
   about them, so the name takes the space and the buttons stay put. */
.friendlist{ display:flex; flex-direction:column; gap:8px; margin-bottom: 14px; }
.friendrow{
  display:flex; align-items:center; gap:10px; justify-content:space-between;
  padding: 9px 12px; border-radius: 10px;
  background: var(--card); border: 1px solid var(--border-soft);
}
.friendwho{ display:flex; flex-direction:column; gap:2px; min-width:0; font-size:13px; }
.friendwho small{ font-size:11px; color: var(--faint); }
.friendacts{ display:flex; gap:6px; flex:none; }
.friendadd{ margin-top: 4px; }
.friendadd .btn{ margin-top: 8px; }
.btn.xs{ padding: 6px 12px; font-size: 12px; border-radius: 8px; }

/* Read-only mode has to announce itself, or a tap that saves nothing
   reads as a broken app rather than as someone else's data. */
.guestbar{
  display:flex; align-items:center; justify-content:space-between; gap:10px;
  margin: 10px 0 2px; padding: 8px 12px; border-radius: 10px;
  background: var(--card); border: 1px dashed var(--border);
  font-size: 12px; color: var(--muted-foreground);
}


/* ── Sign in ──────────────────────────────────────────────────────
   A card, not a hero: two fields and one action do not need the full
   screen. Inputs are placeholder-only by design, so each carries a
   visually hidden label rather than none at all. */
.authwrap{
  min-height: 100dvh; display: grid; place-items: center;
  padding: 28px var(--gutter);
}
.authcard{
  width: 100%; max-width: 380px;
  border-radius: var(--radius); padding: clamp(22px, 6vw, 30px);
}
.authcard .brand{
  font-family: var(--font-display); font-weight: 800;
  font-size: clamp(24px, 7vw, 30px); letter-spacing: -.03em;
  text-align: center; line-height: 1;
}
.authcard .brandsub{
  text-align: center; font-size: 12.5px; color: var(--faint);
  margin: 9px 0 0; line-height: 1.5;
}
.authfield{ margin-top: 11px; }
.authfield:first-of-type{ margin-top: 22px; }
.authfield input{
  width: 100%; min-width: 0;
  background: var(--well); border: 1px solid var(--border-soft);
  border-radius: var(--radius-sm); padding: 13px 15px;
  font-size: 15px; min-height: 48px; color: var(--foreground);
}
.authfield input::placeholder{ color: var(--faint); }
.authfield input:focus{ outline: 2px solid var(--ring); outline-offset: 1px; }
.authbtn{ margin-top: 16px; min-height: 48px; }
.authmsg{
  margin-top: 12px; padding: 10px 13px; font-size: 12.5px; line-height: 1.5;
  border-radius: var(--radius-sm); background: var(--well);
  border: 1px solid var(--border-soft);
  border-left: 3px solid color-mix(in oklab, var(--tone-3) 80%, transparent);
}
.authfoot{ text-align: center; font-size: 12.5px; color: var(--faint); margin: 17px 0 0; }
.authfoot button{
  background: none; border: none; padding: 0; font: inherit; cursor: pointer;
  color: var(--tone-ink); text-decoration: underline; text-underline-offset: 2px;
}
.authfoot button:focus-visible{ outline: 2px solid var(--ring); outline-offset: 2px; }
.sr{
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
