/* ==========================================================================
   Vitals — design system

   Light-first, drawn from a soft pastoral palette: parchment, sage meadow,
   muted gold and twilight lavender. Dark mode is a deep forest-night variant
   rather than pure black, so the character survives the switch.

   Every colour is a token. Nothing below hard-codes a colour.
   ========================================================================== */

:root {
  /* --- Parchment and meadow --------------------------------------------- */
  --bg:        #F6F2E8;  /* aged paper */
  --bg-tint:   #EDF0E2;  /* faint meadow wash at the foot of the page */
  --surface:   #FFFDF7;  /* fresh vellum */
  --surface-2: #F1EDE1;
  --surface-3: #E4DECE;
  --border:    #DDD5C2;

  --text:      #33302A;  /* warm ink, never pure black */
  --text-dim:  #6B655A;
  --text-faint:#9A9284;

  /* --- Metric accents. Muted, natural, never neon. ----------------------- */
  --sleep:     #8B82B0;  /* twilight lavender */
  --recovery:  #7C9A68;  /* sage */
  --strain:    #C08552;  /* terracotta */
  --nutrition: #C2A257;  /* wheat gold */
  --stress:    #B4737E;  /* dusty rose */
  --info:      #6F94B5;  /* distant sky */
  --sound:     #7E8CA8;  /* slate blue — hearing and noise */
  --energy:    #C99A4E;  /* low amber — subjective energy */

  --protein:   #6F94B5;
  --carbs:     #C2A257;
  --fat:       #C08552;

  --good:      #7C9A68;
  --warn:      #C2A257;
  --bad:       #B4737E;

  /* Ink used on top of a filled accent button. */
  --on-accent: #FFFDF7;

  --shadow-sm: 0 1px 2px rgba(74, 66, 48, .06);
  --shadow-md: 0 2px 10px rgba(74, 66, 48, .07);
  --shadow-lg: 0 -6px 32px rgba(74, 66, 48, .16);

  --r-sm: 10px;
  --r-md: 16px;
  --r-lg: 22px;

  --sp-1: 4px;  --sp-2: 8px;  --sp-3: 12px;
  --sp-4: 16px; --sp-5: 24px; --sp-6: 32px;

  --safe-top:    env(safe-area-inset-top, 0px);
  --safe-bottom: env(safe-area-inset-bottom, 0px);

  --tabbar-h: 56px;

  --font-body: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Segoe UI", Roboto, sans-serif;
  /* Headings take a serif so the app reads like a storybook rather than a dashboard. */
  --font-display: "Iowan Old Style", "Palatino Linotype", Palatino, "Book Antiqua", Georgia, serif;
}

/* --- Dark: forest at night, not a black void ----------------------------- */
:root[data-theme="dark"] {
  --bg:        #191D19;
  --bg-tint:   #141814;
  --surface:   #222722;
  --surface-2: #2B322B;
  --surface-3: #363E36;
  --border:    #333B33;

  --text:      #E9E7DC;
  --text-dim:  #A8A798;
  --text-faint:#7C7C6F;

  --sleep:     #A79DCB;
  --recovery:  #97B683;
  --strain:    #D9A06C;
  --nutrition: #D8B96C;
  --stress:    #CC8B96;
  --info:      #8AAFCE;
  --sound:     #9AA8C4;
  --energy:    #DDB36A;

  --protein:   #8AAFCE;
  --carbs:     #D8B96C;
  --fat:       #D9A06C;

  --good:      #97B683;
  --warn:      #D8B96C;
  --bad:       #CC8B96;

  --on-accent: #191D19;

  --shadow-sm: 0 1px 2px rgba(0, 0, 0, .3);
  --shadow-md: 0 2px 10px rgba(0, 0, 0, .32);
  --shadow-lg: 0 -6px 32px rgba(0, 0, 0, .5);
}

/* Only when the user picked "Auto" — an explicit choice always wins. */
@media (prefers-color-scheme: dark) {
  :root[data-theme="auto"] {
    --bg:#191D19; --bg-tint:#141814; --surface:#222722; --surface-2:#2B322B;
    --surface-3:#363E36; --border:#333B33;
    --text:#E9E7DC; --text-dim:#A8A798; --text-faint:#7C7C6F;
    --sleep:#A79DCB; --recovery:#97B683; --strain:#D9A06C; --nutrition:#D8B96C;
    --stress:#CC8B96; --info:#8AAFCE; --sound:#9AA8C4; --energy:#DDB36A;
    --protein:#8AAFCE; --carbs:#D8B96C; --fat:#D9A06C;
    --good:#97B683; --warn:#D8B96C; --bad:#CC8B96;
    --on-accent:#191D19;
    --shadow-sm:0 1px 2px rgba(0,0,0,.3); --shadow-md:0 2px 10px rgba(0,0,0,.32);
    --shadow-lg:0 -6px 32px rgba(0,0,0,.5);
  }
}

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }

html, body {
  margin: 0; padding: 0;
  color: var(--text);
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.45;
  overscroll-behavior: none;
}

/*
 * A very soft meadow wash: warm sky at the top settling into green at the foot.
 * Fixed attachment so it behaves like a horizon rather than scrolling wallpaper.
 */
body {
  padding-top: var(--safe-top);
  background:
    linear-gradient(to bottom, var(--bg) 0%, var(--bg) 55%, var(--bg-tint) 100%)
    fixed;
  min-height: 100vh;
}

.num, .stat-value, .ring-value { font-variant-numeric: tabular-nums; }

h1, h2, h3, .card-title, .date-main, .stat-value, .ring-value, .timer-big {
  font-family: var(--font-display);
  font-weight: 600;
  letter-spacing: -0.005em;
}

/* --------------------------------------------------------------- header -- */

.app-header {
  position: sticky; top: 0; z-index: 20;
  background: color-mix(in srgb, var(--bg) 86%, transparent);
  backdrop-filter: saturate(140%) blur(14px);
  -webkit-backdrop-filter: saturate(140%) blur(14px);
  border-bottom: 1px solid var(--border);
}
.header-row {
  display: flex; align-items: center; justify-content: space-between;
  padding: var(--sp-2) var(--sp-3);
  max-width: 720px; margin: 0 auto;
}
.date-btn {
  flex: 1; background: none; border: 0; color: var(--text);
  display: flex; flex-direction: column; align-items: center; gap: 1px;
  font: inherit; cursor: pointer; padding: var(--sp-1);
}
.date-main { font-family: var(--font-display); font-size: 19px; }
.date-sub  { font-size: 12px; color: var(--text-faint); }

/* ---------------------------------------------------------------- views -- */

#views { max-width: 720px; margin: 0 auto; }
.view { display: none; padding: var(--sp-4) var(--sp-3); padding-bottom: calc(var(--tabbar-h) + var(--safe-bottom) + 32px); }
.view.active { display: block; animation: fade .2s ease; }
@keyframes fade { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }

.section-title {
  font-family: var(--font-display);
  font-size: 12px; font-weight: 600; text-transform: uppercase;
  letter-spacing: .12em; color: var(--text-faint);
  margin: var(--sp-5) 0 var(--sp-2);
}
.section-title:first-child { margin-top: 0; }

/* ---------------------------------------------------------------- cards -- */

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  padding: var(--sp-4);
  margin-bottom: var(--sp-3);
  box-shadow: var(--shadow-sm);
}
.card-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--sp-3); margin-bottom: var(--sp-3); }
.card-title { font-size: 16px; margin: 0; }
.card-sub { font-size: 13px; color: var(--text-dim); }

/* ---- tiles: destinations, as opposed to cards, which hold something ---- */
.tile-grid {
  display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-3);
  margin-bottom: var(--sp-3);
}
.tile {
  display: flex; flex-direction: column; align-items: flex-start; gap: 2px;
  padding: var(--sp-3);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-sm);
  color: var(--text);
  font: inherit; text-align: left; cursor: pointer;
  transition: transform .12s ease, box-shadow .12s ease;
}
.tile:active { transform: scale(.975); box-shadow: none; }
.tile-icon {
  display: flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; margin-bottom: var(--sp-2);
  font-size: 18px; line-height: 1;
  background: var(--surface-2);
  border-radius: 50%;
}
.tile-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.tile-label { font-family: var(--font-display); font-size: 15px; font-weight: 600; }
.tile-sub { font-size: 12px; color: var(--text-faint); line-height: 1.3; }

/* An odd tile out stretches rather than leaving a hole in the grid. */
.tile-grid > .tile:last-child:nth-child(odd) { grid-column: 1 / -1; flex-direction: row; align-items: center; gap: var(--sp-3); }
.tile-grid > .tile:last-child:nth-child(odd) .tile-icon { margin-bottom: 0; }

.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-3); }
.grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--sp-2); }

.stat {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r-md); padding: var(--sp-3); box-shadow: var(--shadow-sm);
}
.stat-label { font-size: 12px; color: var(--text-faint); margin-bottom: 2px; }
.stat-value { font-size: 23px; }
.stat-unit { font-size: 13px; color: var(--text-dim); font-weight: 400; margin-left: 2px; font-family: var(--font-body); }
.stat-delta { font-size: 12px; margin-top: 2px; }
.delta-up   { color: var(--good); }
.delta-down { color: var(--bad); }
.delta-flat { color: var(--text-faint); }

/* ---------------------------------------------------------------- rings -- */

.rings-row { display: flex; align-items: center; justify-content: space-around; gap: var(--sp-3); }
.ring-wrap { display: flex; flex-direction: column; align-items: center; gap: var(--sp-2); }
.ring { position: relative; }
.ring svg { display: block; transform: rotate(-90deg); }
.ring-track { fill: none; stroke: var(--surface-3); }
.ring-fill  { fill: none; stroke-linecap: round; transition: stroke-dashoffset .6s cubic-bezier(.22,1,.36,1); }
.ring-center { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; }
.ring-value { font-size: 21px; }
.ring-unit  { font-size: 10px; color: var(--text-faint); }
.ring-label { font-size: 12px; color: var(--text-dim); }

/* ----------------------------------------------------------------- bars -- */

.bar { height: 6px; border-radius: 999px; background: var(--surface-3); overflow: hidden; }
.bar-fill { height: 100%; border-radius: 999px; transition: width .45s ease; }
.macro-row { display: flex; justify-content: space-between; font-size: 13px; margin-bottom: var(--sp-1); }
.macro-block + .macro-block { margin-top: var(--sp-3); }

/* ---------------------------------------------------------------- lists -- */

.list {
  border: 1px solid var(--border); border-radius: var(--r-md);
  overflow: hidden; background: var(--surface); box-shadow: var(--shadow-sm);
}
.row {
  display: flex; align-items: center; gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  border-bottom: 1px solid var(--border);
  background: none; width: 100%; text-align: left;
  color: var(--text); font: inherit; cursor: pointer;
}
.row:last-child { border-bottom: 0; }
.row:active { background: var(--surface-2); }
.row-main { flex: 1; min-width: 0; }
.row-title { font-size: 15px; font-weight: 550; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.row-sub { font-size: 12px; color: var(--text-faint); }
.row-value { font-size: 15px; font-weight: 600; color: var(--text-dim); white-space: nowrap; }

.empty { text-align: center; color: var(--text-faint); font-size: 14px; padding: var(--sp-6) var(--sp-4); }

/* -------------------------------------------------------------- buttons -- */

button { font-family: inherit; }
.icon-btn {
  background: none; border: 0; color: var(--text-dim);
  width: 36px; height: 36px; border-radius: 50%;
  font-size: 22px; line-height: 1; cursor: pointer; display: grid; place-items: center;
}
.icon-btn:active { background: var(--surface-2); }

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--sp-2);
  padding: 13px var(--sp-4); border-radius: var(--r-sm);
  border: 1px solid var(--border); background: var(--surface-2); color: var(--text);
  font-size: 15px; font-weight: 600; cursor: pointer; width: 100%;
  transition: transform .1s ease;
}
.btn:active { transform: scale(.985); }
.btn-primary { background: var(--info); border-color: var(--info); color: var(--on-accent); }
.btn-good    { background: var(--good); border-color: var(--good); color: var(--on-accent); }
.btn-danger  { background: none; border-color: var(--bad); color: var(--bad); }
.btn-ghost   { background: none; }
.btn-row { display: flex; gap: var(--sp-2); }

.chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 7px 13px; border-radius: 999px;
  border: 1px solid var(--border); background: var(--surface-2);
  font-size: 13px; font-weight: 550; color: var(--text-dim); cursor: pointer;
}
.chip.on { background: var(--info); border-color: var(--info); color: var(--on-accent); }
.chips { display: flex; flex-wrap: wrap; gap: var(--sp-2); }

/* --------------------------------------------------------------- inputs -- */

.field { margin-bottom: var(--sp-3); }
.field label { display: block; font-size: 13px; color: var(--text-dim); margin-bottom: 6px; }
input, select, textarea {
  width: 100%; padding: 12px var(--sp-3);
  background: var(--surface-2); color: var(--text);
  border: 1px solid var(--border); border-radius: var(--r-sm);
  font-size: 16px; /* below 16px iOS Safari zooms on focus */
  font-family: inherit;
}
input:focus, select:focus, textarea:focus { outline: 2px solid var(--info); outline-offset: -1px; }
.input-row { display: flex; gap: var(--sp-2); align-items: center; }
.input-suffix { color: var(--text-faint); font-size: 14px; }

/* ---------------------------------------------------------------- sheet -- */

.sheet-backdrop {
  position: fixed; inset: 0; z-index: 50;
  background: rgba(51, 45, 32, .42);
  display: flex; align-items: flex-end; justify-content: center;
  animation: fade .16s ease;
}
/* An explicit `display` beats the UA stylesheet's `[hidden] { display: none }`,
   so hidden elements that set one must opt back out themselves.

   `.tab` sets display:flex and was missing from this list, which quietly broke the whole
   feature-switch system: applyFeatures() set tab.hidden on a switched-off feature and the
   tab stayed visible and clickable. */
.sheet-backdrop[hidden], .toast[hidden], .tab[hidden] { display: none; }

.sheet {
  background: var(--surface); width: 100%; max-width: 720px;
  border-radius: var(--r-lg) var(--r-lg) 0 0;
  max-height: 92vh; display: flex; flex-direction: column;
  padding-bottom: var(--safe-bottom);
  box-shadow: var(--shadow-lg);
  animation: slideup .26s cubic-bezier(.22,1,.36,1);
}
@keyframes slideup { from { transform: translateY(100%); } to { transform: none; } }
.sheet-grabber { width: 36px; height: 4px; border-radius: 999px; background: var(--surface-3); margin: var(--sp-2) auto 0; }
.sheet-head { display: flex; align-items: center; justify-content: space-between; padding: var(--sp-3) var(--sp-4) var(--sp-2); }
.sheet-head h2 { font-size: 18px; margin: 0; }
.sheet-body { overflow-y: auto; padding: 0 var(--sp-4) var(--sp-5); -webkit-overflow-scrolling: touch; }

/* --------------------------------------------------------------- tabbar -- */

.tabbar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 30;
  display: flex; justify-content: space-around;
  background: color-mix(in srgb, var(--surface) 92%, transparent);
  backdrop-filter: saturate(140%) blur(16px);
  -webkit-backdrop-filter: saturate(140%) blur(16px);
  border-top: 1px solid var(--border);
  padding-bottom: var(--safe-bottom);
}
.tab {
  flex: 1; background: none; border: 0; cursor: pointer;
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  padding: 7px 0 5px; color: var(--text-faint); font-size: 10px; font-weight: 550;
  height: var(--tabbar-h);
}
.tab.active { color: var(--recovery); }
.tab-icon { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }

/* ---------------------------------------------------------------- toast -- */

.toast {
  position: fixed; left: 50%; transform: translateX(-50%);
  bottom: calc(var(--tabbar-h) + var(--safe-bottom) + 16px); z-index: 60;
  background: var(--text); color: var(--surface);
  padding: 11px var(--sp-4); border-radius: 999px;
  font-size: 14px; font-weight: 550; box-shadow: var(--shadow-md);
  animation: fade .18s ease;
}

/* --------------------------------------------------------------- charts -- */

.chart { width: 100%; display: block; overflow: visible; }
.chart-line { fill: none; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.chart-area { stroke: none; opacity: .16; }
.chart-dot  { stroke: var(--surface); stroke-width: 2; }
.chart-grid { stroke: var(--border); stroke-width: 1; stroke-dasharray: 2 4; }
.chart-proj { fill: none; stroke-width: 2; stroke-dasharray: 3 4; opacity: .7; }
.chart-label { font-size: 10px; fill: var(--text-faint); }
.chart-bar { rx: 3; }

/* ------------------------------------------------------------- training -- */

.timer-big { font-size: 58px; font-weight: 400; letter-spacing: -0.02em; text-align: center; font-variant-numeric: tabular-nums; }

.set-grid { display: grid; grid-template-columns: 28px 1fr 1fr 44px 34px; gap: var(--sp-2); align-items: center; margin-bottom: var(--sp-2); }
.set-grid input { padding: 9px var(--sp-2); text-align: center; }
.set-head { font-size: 11px; color: var(--text-faint); text-align: center; text-transform: uppercase; letter-spacing: .06em; }
.set-idx { text-align: center; font-size: 13px; color: var(--text-faint); font-weight: 600; cursor: pointer; }
.set-done { width: 34px; height: 34px; border-radius: var(--r-sm); border: 1px solid var(--border); background: var(--surface-2); color: var(--text-faint); cursor: pointer; display: grid; place-items: center; }
.set-done.on { background: var(--good); border-color: var(--good); color: var(--on-accent); }
.set-warmup input { opacity: .6; }

/* ----------------------------------------------------------------- misc -- */

.hint { font-size: 12px; color: var(--text-faint); margin-top: var(--sp-2); line-height: 1.5; }

/* A reading with its interpretation band. Colour comes from the band, inline. */
.band-line {
  font-size: 15px; font-weight: 600; line-height: 1.4;
  margin-bottom: var(--sp-3);
}

.warn-box {
  background: color-mix(in srgb, var(--warn) 14%, var(--surface));
  border: 1px solid color-mix(in srgb, var(--warn) 40%, transparent);
  border-radius: var(--r-sm); padding: var(--sp-3);
  font-size: 13px; color: var(--text-dim); line-height: 1.5;
}

/* Reserved for genuine safety warnings — weight cutting, not UI validation. */
.danger-box {
  background: color-mix(in srgb, var(--bad) 13%, var(--surface));
  border: 1px solid color-mix(in srgb, var(--bad) 50%, transparent);
  border-left-width: 3px;
  border-radius: var(--r-sm); padding: var(--sp-3);
  font-size: 13px; color: var(--text); line-height: 1.5;
  margin-bottom: var(--sp-3);
}
.danger-box strong { color: var(--bad); }

.good-box {
  background: color-mix(in srgb, var(--good) 13%, var(--surface));
  border: 1px solid color-mix(in srgb, var(--good) 38%, transparent);
  border-radius: var(--r-sm); padding: var(--sp-3);
  font-size: 13px; color: var(--text-dim); line-height: 1.5;
}

/* ----------------------------------------------------------- flashcards -- */

.fc-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-md);
  min-height: 150px;
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  gap: var(--sp-2);
  padding: var(--sp-5) var(--sp-4);
  margin-bottom: var(--sp-4);
  cursor: pointer;
  text-align: center;
  animation: fc-in .2s ease;
}
@keyframes fc-in { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }

.fc-face {
  font-family: var(--font-display);
  font-size: 21px; line-height: 1.35; color: var(--text);
}
.fc-front-small {
  font-size: 13px; color: var(--text-faint);
  padding-bottom: var(--sp-2); border-bottom: 1px solid var(--border);
  width: 100%;
}

.fc-option {
  margin-bottom: var(--sp-2);
  text-align: left; justify-content: flex-start;
  white-space: normal; line-height: 1.35;
}
.fc-right { background: var(--good); border-color: var(--good); color: var(--on-accent); }
.fc-wrong { background: var(--bad); border-color: var(--bad); color: var(--on-accent); }

/* Photo problem help */
.solve-preview {
  width: 100%; max-height: 320px; object-fit: contain;
  border-radius: var(--r-md); border: 1px solid var(--border);
  background: var(--surface-2); margin-top: var(--sp-3); display: block;
}
.solve-answer {
  white-space: pre-wrap;
  font-size: 14px; line-height: 1.65;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r-md); padding: var(--sp-4); margin-top: var(--sp-3);
  box-shadow: var(--shadow-sm);
}

/* ============================================================== calendar == */

.cal-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: var(--sp-3); }
.cal-title { font-family: var(--font-display); font-size: 17px; font-weight: 600; }

.cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 4px; }
.cal-dow { margin-bottom: 6px; }
.cal-dow-cell {
  text-align: center; font-size: 11px; font-weight: 600;
  color: var(--text-faint); letter-spacing: .06em;
}

.cal-cell {
  aspect-ratio: 1; border-radius: 10px;
  border: 1px solid transparent; background: var(--surface-2);
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px;
  cursor: pointer; padding: 2px; color: var(--text);
  font: inherit;
  transition: background .15s ease, transform .1s ease, border-color .15s ease;
}
.cal-cell:active { transform: scale(.93); }
.cal-cell.is-empty { background: none; color: var(--text-faint); }
.cal-cell.is-today { border-color: var(--recovery); font-weight: 700; }
.cal-cell.is-selected { background: var(--recovery); color: var(--on-accent); }
.cal-cell.is-future { opacity: .35; cursor: default; }
.cal-cell.cal-pad { background: none; border: 0; cursor: default; }

.cal-num { font-size: 13px; font-variant-numeric: tabular-nums; line-height: 1; }
.cal-dots { display: flex; gap: 2px; min-height: 5px; }
.cal-dot { width: 5px; height: 5px; border-radius: 50%; display: inline-block; }

.cal-legend {
  display: flex; flex-wrap: wrap; gap: 10px;
  margin-top: var(--sp-4); font-size: 11px; color: var(--text-faint);
}
.cal-legend-item { display: inline-flex; align-items: center; gap: 5px; }

/* ============================================================== timeline == */

.tl { position: relative; padding-left: 4px; }
.tl-row { display: grid; grid-template-columns: 62px 14px 1fr; gap: var(--sp-2); padding-bottom: var(--sp-4); position: relative; }
.tl-row:last-child { padding-bottom: 0; }

/* The connecting spine, drawn behind the markers. */
.tl-row:not(:last-child):after {
  content: ''; position: absolute;
  left: calc(62px + var(--sp-2) + 5px); top: 16px; bottom: -2px;
  width: 1px; background: var(--border);
}

.tl-time {
  font-size: 11px; color: var(--text-faint); text-align: right;
  font-variant-numeric: tabular-nums; padding-top: 3px; white-space: nowrap;
}
.tl-marker {
  width: 11px; height: 11px; border-radius: 50%; margin-top: 4px;
  box-shadow: 0 0 0 3px var(--surface); z-index: 1;
}
.tl-body { min-width: 0; }
.tl-title { font-size: 14px; font-weight: 600; display: flex; justify-content: space-between; gap: var(--sp-2); }
.tl-value { font-weight: 500; color: var(--text-dim); font-variant-numeric: tabular-nums; white-space: nowrap; }
.tl-detail { font-size: 12px; color: var(--text-faint); margin-top: 2px; line-height: 1.45; }

/* Study photo help */
.solve-preview {
  width: 100%; max-height: 320px; object-fit: contain;
  border-radius: var(--r-md); border: 1px solid var(--border);
  background: var(--surface-2); margin-top: var(--sp-3);
}
/* (.solve-answer is defined once, further up — a second copy here differed only by
   omitting the shadow, so the cascade silently merged the two.) */

/* ================================================================== chat == */

.chat-log {
  max-height: 46vh; overflow-y: auto;
  display: flex; flex-direction: column; gap: var(--sp-2);
  padding: var(--sp-2) 0;
}
.chat-msg {
  max-width: 88%; padding: 10px var(--sp-3); border-radius: var(--r-md);
  font-size: 14px; line-height: 1.55; white-space: pre-wrap; overflow-wrap: anywhere;
}
.chat-user { align-self: flex-end; background: var(--info); color: var(--on-accent); border-bottom-right-radius: 4px; }
.chat-bot { align-self: flex-start; background: var(--surface-2); border: 1px solid var(--border); border-bottom-left-radius: 4px; }

/* ================================================================ polish == */

/*
 * Interaction feedback. Everything tappable should acknowledge the tap — without it the
 * app feels unresponsive on a phone even when it is fast.
 */
.row, .cal-cell, .lock-key, .chip, .btn, .set-done, .checkin-dot, .urine-swatch {
  -webkit-user-select: none; user-select: none;
}
.row { transition: background .14s ease; }
.chip { transition: background .14s ease, border-color .14s ease, color .14s ease, transform .1s ease; }
.chip:active { transform: scale(.95); }
.card { transition: box-shadow .2s ease; }

/* Visible keyboard focus, without a permanent ring for mouse users. */
:focus-visible {
  outline: 2px solid var(--info);
  outline-offset: 2px;
  border-radius: 4px;
}
.btn:focus-visible, .row:focus-visible, .cal-cell:focus-visible { outline-offset: -2px; }

/* Momentum scrolling and a settled scrollbar inside sheets. */
.sheet-body { scrollbar-width: thin; scrollbar-color: var(--surface-3) transparent; }
.sheet-body::-webkit-scrollbar { width: 6px; }
.sheet-body::-webkit-scrollbar-thumb { background: var(--surface-3); border-radius: 999px; }
.sheet-body::-webkit-scrollbar-track { background: transparent; }

/* Long words and pasted URLs must not force the layout sideways. */
.row-title, .row-sub, .card-sub, .tl-detail, .insight-body { overflow-wrap: anywhere; }

/* Wide content scrolls inside itself rather than pushing the page. */
.formula, .solve-answer { max-width: 100%; }

/*
 * Respect the OS setting. Vestibular disorders are a real accessibility concern and this
 * app animates a lot of sheets.
 */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
}

/* Card builder rows — the Quizlet-style list editor */
.fc-row {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  padding: var(--sp-3);
  margin-bottom: var(--sp-3);
  box-shadow: var(--shadow-sm);
}
.fc-row-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: var(--sp-2); }
.fc-row-num { font-size: 12px; color: var(--text-faint); font-weight: 600; }
.fc-input {
  width: 100%; resize: vertical; min-height: 40px;
  margin-bottom: var(--sp-2);
}
.fc-input:last-child { margin-bottom: 0; }

.fc-match {
  display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-2);
  margin-bottom: var(--sp-4);
}
.fc-tile {
  min-height: 78px; padding: var(--sp-2);
  border: 1px solid var(--border); border-radius: var(--r-sm);
  background: var(--surface); color: var(--text);
  font-size: 13px; line-height: 1.3; cursor: pointer;
  display: grid; place-items: center; text-align: center;
  box-shadow: var(--shadow-sm);
  transition: transform .1s ease, opacity .25s ease, background .15s ease;
}
.fc-tile.sel { background: var(--info); border-color: var(--info); color: var(--on-accent); transform: scale(.97); }
.fc-tile.bad { background: var(--bad); border-color: var(--bad); color: var(--on-accent); }
.fc-tile.gone { opacity: 0; pointer-events: none; transform: scale(.9); }

/* ---------------------------------------------------------- lock screen -- */

#lock-screen {
  position: fixed; inset: 0; z-index: 100;
  background: var(--bg);
  display: flex; align-items: center; justify-content: center;
  padding: var(--safe-top) var(--sp-4) calc(var(--safe-bottom) + var(--sp-4));
}
#lock-screen[hidden] { display: none; }

/* Backgrounded with a passcode set: hide everything before the OS photographs the screen
   for the app-switcher card, which is readable without unlocking. `visibility` rather than
   `display` so nothing reflows and the app comes back exactly as it was left.
   See the visibilitychange handler in js/app.js. */
:root[data-redacted] .app-header,
:root[data-redacted] #views,
:root[data-redacted] .tabbar,
:root[data-redacted] .sheet-backdrop { visibility: hidden; }

.lock-panel {
  width: 100%; max-width: 340px;
  display: flex; flex-direction: column; align-items: center;
}
.lock-panel.shake { animation: shake .4s cubic-bezier(.36,.07,.19,.97); }
@keyframes shake {
  10%, 90% { transform: translateX(-2px); }
  20%, 80% { transform: translateX(4px); }
  30%, 50%, 70% { transform: translateX(-7px); }
  40%, 60% { transform: translateX(7px); }
}

.lock-mark { color: var(--recovery); margin-bottom: var(--sp-3); }
.lock-title { font-family: var(--font-display); font-size: 26px; margin: 0 0 4px; }
.lock-subtitle { font-size: 14px; color: var(--text-dim); margin-bottom: var(--sp-5); }

.lock-dots { display: flex; gap: 12px; margin-bottom: var(--sp-3); min-height: 14px; }
.lock-dot {
  width: 13px; height: 13px; border-radius: 50%;
  border: 1.5px solid var(--text-faint); background: none;
  transition: background .12s ease, border-color .12s ease, transform .12s ease;
}
.lock-dot.on { background: var(--recovery); border-color: var(--recovery); transform: scale(1.12); }

.lock-message { font-size: 13px; min-height: 20px; color: var(--text-dim); text-align: center; margin-bottom: var(--sp-3); }
.lock-message.error { color: var(--bad); }

.lock-keypad {
  display: grid; grid-template-columns: repeat(3, 1fr);
  gap: var(--sp-3); width: 100%; margin-bottom: var(--sp-4);
}
.lock-key {
  aspect-ratio: 1; border-radius: 50%;
  border: 1px solid var(--border); background: var(--surface);
  color: var(--text); font-family: var(--font-display); font-size: 24px;
  cursor: pointer; display: grid; place-items: center;
  box-shadow: var(--shadow-sm);
  transition: transform .08s ease, background .12s ease;
}
.lock-key:active { transform: scale(.94); background: var(--surface-2); }
.lock-key-alt { font-family: var(--font-body); font-size: 14px; color: var(--text-dim); background: none; border-color: transparent; box-shadow: none; }
.lock-confirm { max-width: 340px; }

/* Weight-cut phase timeline */
.phase { position: relative; padding-left: var(--sp-5); padding-bottom: var(--sp-4); }
.phase:before {
  content: ''; position: absolute; left: 5px; top: 6px;
  width: 9px; height: 9px; border-radius: 50%;
  background: var(--recovery); box-shadow: 0 0 0 3px color-mix(in srgb, var(--recovery) 22%, transparent);
}
.phase.danger:before { background: var(--bad); box-shadow: 0 0 0 3px color-mix(in srgb, var(--bad) 22%, transparent); }
.phase:after {
  content: ''; position: absolute; left: 9px; top: 18px; bottom: 0; width: 1px; background: var(--border);
}
.phase:last-child:after { display: none; }
.phase-day { font-size: 11px; text-transform: uppercase; letter-spacing: .1em; color: var(--text-faint); }
.phase-title { font-family: var(--font-display); font-size: 15px; font-weight: 600; margin: 2px 0 6px; }
.phase-actions { margin: 0; padding-left: var(--sp-4); font-size: 13px; color: var(--text-dim); }
.phase-actions li { margin-bottom: 3px; }
.phase-why { font-size: 12px; color: var(--text-faint); font-style: italic; margin-top: 6px; }

/* Urine hydration scale */
.urine-scale { display: flex; gap: 4px; margin: var(--sp-2) 0; }
.urine-swatch { flex: 1; height: 34px; border-radius: 5px; border: 1px solid var(--border); cursor: pointer; position: relative; }
.urine-swatch.on { outline: 2px solid var(--text); outline-offset: 2px; }

/* Map */
.map-wrap {
  position: relative; width: 100%; height: 300px;
  border-radius: var(--r-md); overflow: hidden;
  border: 1px solid var(--border); background: var(--surface-2);
  touch-action: none;
}
.map-tiles { position: absolute; inset: 0; }
.map-tile { position: absolute; width: 256px; height: 256px; }
.map-pin {
  position: absolute; width: 14px; height: 14px; margin: -7px 0 0 -7px;
  border-radius: 50% 50% 50% 0; transform: rotate(-45deg);
  background: var(--bad); border: 2px solid var(--surface); cursor: pointer;
  box-shadow: var(--shadow-sm);
}
.map-pin.me { background: var(--info); border-radius: 50%; transform: none; }
.map-attrib {
  position: absolute; right: 4px; bottom: 3px;
  font-size: 9px; color: var(--text-dim);
  background: color-mix(in srgb, var(--surface) 80%, transparent);
  padding: 1px 5px; border-radius: 4px;
}
.map-controls { position: absolute; right: 8px; top: 8px; display: flex; flex-direction: column; gap: 4px; }
.map-btn {
  width: 32px; height: 32px; border-radius: 8px; border: 1px solid var(--border);
  background: var(--surface); color: var(--text); font-size: 18px; cursor: pointer;
  display: grid; place-items: center; box-shadow: var(--shadow-sm);
}

/* Study */
.pill { display: inline-block; padding: 2px 9px; border-radius: 999px; font-size: 11px; font-weight: 600; }
.subject-dot { width: 10px; height: 10px; border-radius: 50%; flex: 0 0 10px; }

/* --- Notebooks and whiteboards ------------------------------------------- */

.nb-pagenav {
  display: flex; align-items: center; gap: var(--sp-2);
  margin-bottom: var(--sp-3);
}
.nb-pagelabel {
  flex: 1; text-align: center;
  font-size: 13px; color: var(--text-dim);
}

/* Lined paper, so a notebook page reads as one. */
.nb-text {
  width: 100%; min-height: 320px; resize: vertical;
  line-height: 28px;
  background:
    repeating-linear-gradient(
      var(--surface), var(--surface) 27px,
      color-mix(in srgb, var(--border) 60%, transparent) 27px,
      color-mix(in srgb, var(--border) 60%, transparent) 28px
    );
  /* Align the first line of text with the first rule. */
  padding-top: 4px;
}

/* Toolbar: fixed rows, so the canvas never shifts under the user's hand when the
   tool changes. */
.nb-toolbar {
  display: flex; flex-direction: column; gap: var(--sp-2);
  margin-bottom: var(--sp-3);
  padding: var(--sp-2);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
}
.nb-row { display: flex; align-items: center; gap: var(--sp-2); }
.nb-spacer { flex: 1 1 auto; }

/* Scroll rather than wrap: a toolbar that gains a row on a narrow phone pushes the
   drawing surface down while you are using it. */
.nb-actions { overflow-x: auto; scrollbar-width: none; }
.nb-actions::-webkit-scrollbar { display: none; }

/* ---- asking about a boxed region ---- */
.nb-hint { font-size: 13px; color: var(--text-faint); }

/* A compact button so the toolbar keeps its fixed height with an action row in it. */
.btn-sm {
  padding: 6px var(--sp-3);
  font-size: 13px;
  width: auto;
}

/* The board is drawn on white before sending, so the preview is framed rather than
   blended — on a dark theme an unframed white image looks like a rendering fault. */
.nb-region-preview {
  display: block;
  width: 100%;
  max-height: 240px;
  object-fit: contain;
  background: #fff;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  margin-bottom: var(--sp-3);
}

.nb-vars { display: flex; flex-wrap: wrap; gap: var(--sp-2); }
.nb-var {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 13px;
  padding: 4px var(--sp-2);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  color: var(--text);
}
.nb-group {
  display: flex; gap: 2px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  padding: 2px;
}

.nb-tool {
  min-width: 38px; height: 34px;
  display: grid; place-items: center;
  border: 0; border-radius: 8px;
  background: transparent; color: var(--text);
  font: inherit; font-size: 15px; line-height: 1;
  cursor: pointer;
  transition: background .14s ease;
}
.nb-tool:hover:not(:disabled) { background: var(--surface-2); }
.nb-tool.on { background: var(--surface-3); }
.nb-tool:disabled { opacity: .3; cursor: default; }

.nb-sizebtn { min-width: 34px; }
.nb-sizedot { display: block; border-radius: 50%; background: var(--text); }

/* Current nib, previewed at its real size and colour. */
.nb-nibwrap {
  width: 30px; height: 30px;
  display: grid; place-items: center;
  flex: 0 0 auto;
}
.nb-nib { display: block; border-radius: 50%; }

.nb-swatches { display: flex; gap: 4px; flex-wrap: wrap; justify-content: flex-end; }
.nb-swatch {
  width: 26px; height: 26px; padding: 0;
  border-radius: 50%;
  border: 2px solid transparent;
  box-shadow: 0 0 0 1px var(--border) inset;
  cursor: pointer;
}
.nb-swatch.on { border-color: var(--text); }

/* The wheel swatch wraps a native colour input, which is what opens the OS picker.
   The input itself is invisible but still fills the swatch, so the whole circle is
   the hit target and it stays keyboard-reachable. */
.nb-wheel { position: relative; overflow: hidden; }
.nb-wheel::after {
  content: '＋'; position: absolute; inset: 0;
  display: grid; place-items: center;
  font-size: 13px; color: var(--on-accent);
  text-shadow: 0 0 2px rgba(0, 0, 0, .5);
  pointer-events: none;
}
.nb-colorinput {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  opacity: 0; border: 0; padding: 0;
  cursor: pointer;
}

.nb-canvas {
  /* Starting value only — fitCanvasHeight() replaces it with the room actually left in
     the sheet, which depends on how many rows the toolbar is currently showing. */
  display: block; width: 100%; height: 40vh;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  cursor: crosshair;
  /* Without this every stroke scrolls the sheet instead of drawing. */
  touch-action: none;
  /* A long-press on the canvas must not raise the text selection callout. */
  -webkit-user-select: none; user-select: none;
}

/* --- Scan to deck --------------------------------------------------------- */

.scan-gallery {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(84px, 1fr));
  gap: var(--sp-2);
}
.scan-thumb {
  position: relative; aspect-ratio: 3 / 4;
  border-radius: var(--r-sm); overflow: hidden;
  border: 1px solid var(--border); background: var(--surface-2);
}
.scan-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.scan-remove {
  position: absolute; top: 4px; right: 4px;
  width: 24px; height: 24px; border-radius: 50%;
  border: 0; cursor: pointer;
  background: rgba(0, 0, 0, .6); color: #fff;
  font-size: 15px; line-height: 1;
  display: grid; place-items: center;
}

.scan-card {
  border: 1px solid var(--border); border-radius: var(--r-sm);
  padding: var(--sp-3); margin-bottom: var(--sp-2);
  background: var(--surface);
}
/* A dropped card stays visible and editable — it is excluded, not deleted, so the
   choice can be reversed without re-running the whole extraction. */
.scan-card.dropped { opacity: .45; }
.scan-card-head {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: var(--sp-2);
}
.scan-card-n { font-size: 12px; color: var(--text-faint); font-weight: 600; }

/* --- Question of the day -------------------------------------------------- */

.daily-question {
  font-family: var(--font-display);
  font-size: 19px; line-height: 1.45;
  margin: var(--sp-3) 0 var(--sp-4);
}

.daily-choices { display: flex; flex-direction: column; gap: var(--sp-2); }

.daily-choice {
  width: 100%; text-align: left;
  padding: var(--sp-3);
  border: 1px solid var(--border); border-radius: var(--r-sm);
  background: var(--surface); color: var(--text);
  font: inherit; font-size: 15px; line-height: 1.4;
  cursor: pointer;
}
.daily-choice:disabled { cursor: default; }
.daily-choice.correct {
  background: color-mix(in srgb, var(--good) 16%, var(--surface));
  border-color: var(--good);
}
.daily-choice.wrong {
  background: color-mix(in srgb, var(--bad) 14%, var(--surface));
  border-color: var(--bad);
}

.daily-fact { font-size: 14px; line-height: 1.6; color: var(--text-dim); }

/* --- On/off switch -------------------------------------------------------- */

.toggle { display: inline-flex; align-items: center; cursor: pointer; flex: 0 0 auto; }
.toggle-input {
  /* Kept in the layout and focusable, just not painted — the track is the visual. */
  position: absolute; opacity: 0; width: 0; height: 0; margin: 0;
}
.toggle-track {
  position: relative; display: block;
  width: 46px; height: 28px; border-radius: 999px;
  background: var(--surface-3);
  border: 1px solid var(--border);
  transition: background .18s ease, border-color .18s ease;
}
.toggle-track::after {
  content: ''; position: absolute; top: 3px; left: 3px;
  width: 20px; height: 20px; border-radius: 50%;
  background: var(--surface);
  box-shadow: var(--shadow-sm);
  transition: transform .18s ease;
}
.toggle-input:checked + .toggle-track {
  background: var(--recovery);
  border-color: var(--recovery);
}
.toggle-input:checked + .toggle-track::after { transform: translateX(18px); }
.toggle-input:focus-visible + .toggle-track { outline: 2px solid var(--info); outline-offset: 2px; }
.toggle-input:disabled + .toggle-track { opacity: .45; cursor: not-allowed; }

.feature-row { align-items: flex-start; }
.feature-blurb { font-size: 12px; color: var(--text-faint); line-height: 1.5; margin-top: 2px; }

/* --- Boot failure ---------------------------------------------------------
   Replaces the whole app when storage cannot be opened, so it has to stand on
   its own and still look like Ygeia rather than a browser error page. */
.boot-error {
  max-width: 520px; margin: 0 auto;
  padding: calc(var(--sp-6) + var(--safe-top)) var(--sp-4) var(--sp-6);
  color: var(--text);
}
.boot-error h2 { font-family: var(--font-display); font-weight: 500; margin: 0 0 var(--sp-3); }
.boot-error p { line-height: 1.6; margin: 0 0 var(--sp-4); }
.boot-error-detail { font-size: 13px; color: var(--text-faint); }

/* "How is this calculated?" affordance */
.explain-btn {
  background: none; border: 0; cursor: pointer;
  color: var(--text-faint); font-size: 16px; line-height: 1;
  padding: 2px 4px; border-radius: 50%;
}
.explain-btn:active { background: var(--surface-2); }

.formula {
  background: var(--surface-2); border: 1px solid var(--border);
  border-radius: var(--r-sm); padding: var(--sp-3);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 12px; line-height: 1.6; color: var(--text-dim);
  overflow-x: auto; white-space: pre; margin: 0;
}

/* Check-in */
.checkin-scale { display: flex; gap: 6px; }
.checkin-dot {
  flex: 1; aspect-ratio: 1; max-width: 46px; border-radius: 50%;
  border: 1px solid var(--border); background: var(--surface-2);
  cursor: pointer; display: grid; place-items: center;
  font-size: 13px; font-weight: 600; color: var(--text-faint);
}
.checkin-dot.on { background: var(--recovery); border-color: var(--recovery); color: var(--on-accent); }

/* Insight cards */
.insight { border-left: 3px solid var(--info); padding-left: var(--sp-3); margin-bottom: var(--sp-4); }
.insight.strong { border-left-color: var(--good); }
.insight.weak { border-left-color: var(--text-faint); }
.insight-title { font-family: var(--font-display); font-size: 15px; font-weight: 600; margin-bottom: 2px; }
.insight-body { font-size: 13px; color: var(--text-dim); line-height: 1.5; }
.insight-stat { font-size: 11px; color: var(--text-faint); margin-top: 4px; font-variant-numeric: tabular-nums; }

/* Meal / program cards */
.tag-row { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 6px; }
.tag {
  font-size: 11px; padding: 2px 8px; border-radius: 999px;
  background: var(--surface-2); border: 1px solid var(--border); color: var(--text-faint);
}
