/* Plus Jakarta Sans, variable weight, self-hosted from @fontsource-variable
   (SIL Open Font License 1.1, fonts/OFL.txt). Latin and Latin Extended
   upright, Latin italic; anything else falls back to the system face. */
@font-face {
  font-family: "Plus Jakarta Sans"; font-style: normal; font-weight: 200 800; font-display: swap;
  src: url(fonts/plus-jakarta-sans-latin.woff2) format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Plus Jakarta Sans"; font-style: normal; font-weight: 200 800; font-display: swap;
  src: url(fonts/plus-jakarta-sans-latin-ext.woff2) format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Plus Jakarta Sans"; font-style: italic; font-weight: 200 800; font-display: swap;
  src: url(fonts/plus-jakarta-sans-latin-italic.woff2) format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* Design tokens: the asklepios UI kit (Figma, Community, by Strangehelix),
   mapped onto Provita. Therapeia Blue is the primary, the Asklepios grays the
   neutrals, and Hygieia Red / Panacea Teal / Aceso Purple the accents.
   Semantic tokens only; components never use raw hex.
   The primary also appears as literals in favicon.svg, manifest.json, sw.js's
   offline page, privacy.html and index.html's theme-color meta, which cannot
   read CSS variables: keep them in sync. */
:root {
  --color-primary: #0f67fe;          /* Therapeia Blue 60 */
  --color-primary-strong: #0b52cc;   /* hover: one step darker */
  --color-on-primary: #ffffff;
  --color-accent: #08b4bd;           /* Panacea Teal 40 */
  --color-background: #f2f5f9;       /* Asklepios Gray 10 */
  --color-surface: #ffffff;
  --color-foreground: #090e1d;       /* Asklepios Gray 100 */
  --color-text-secondary: #5d6a85;   /* Asklepios Gray 60: 5.4:1 on white */
  --color-muted: #f2f5f9;
  --color-border: #d0e4ff;           /* Therapeia Blue 20 */
  --color-border-neutral: #dce1e8;   /* Asklepios Gray 20 */
  --color-destructive: #da1e2e;      /* Hygieia Red 60 */
  --color-ring: #0f67fe;
  /* main's refined components also read these; kit values */
  --color-highlight: #0f67fe;        /* progress, active, focus: Therapeia Blue */
  --color-highlight-soft: #edf5ff;   /* Therapeia Blue 10 */
  --color-surface-2: #f5f7fb;

  /* chart series: blue against amber stays apart for every common colour
     deficiency (blue against red would not, for protanopes); both >= 3:1 */
  --chart-systolic: #0f67fe;
  --chart-diastolic: #b45309;
  --chart-tertiary: #8a3ffc;          /* Aceso Purple 60 */
  --chart-grid: #e6ebf2;

  /* dose-status markers (shape carries meaning; color is reinforcement) */
  --dose-taken: #3d4966;
  --dose-late: #f9ab00;
  --dose-missed: #da1e2e;

  /* shape scale: the kit's big soft corners, still varied by hierarchy */
  --radius-lg: 28px;
  --radius: 24px;
  --radius-sm: 14px;
  --radius-pill: 999px;

  /* Safe areas: the notch, status bar and home indicator. Only non-zero with
     viewport-fit=cover (index.html), which the native shell draws under. A
     screenshot script can override these to preview the notch in a desktop
     browser, which is why rules read the variables rather than env(). */
  --safe-top: env(safe-area-inset-top, 0px);
  --safe-right: env(safe-area-inset-right, 0px);
  --safe-bottom: env(safe-area-inset-bottom, 0px);
  --safe-left: env(safe-area-inset-left, 0px);

  /* 4/8 spacing rhythm */
  --space-1: 4px; --space-2: 8px; --space-3: 12px;
  --space-4: 16px; --space-5: 24px; --space-6: 32px;

  /* Motion, by context rather than one duration for everything: a press
     answers in a tenth of a second, a panel in under two, a sheet in about a
     quarter. Transform and opacity only. */
  --dur-press: 100ms;
  --dur-ui: 180ms;
  --dur-sheet: 260ms;
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);

  --shadow-card: 0 1px 2px rgba(9, 14, 29, 0.04), 0 8px 24px rgba(9, 14, 29, 0.06);
  --shadow-raised: 0 2px 6px rgba(9, 14, 29, 0.06), 0 16px 40px rgba(9, 14, 29, 0.12);

  --font-heading: "Plus Jakarta Sans", system-ui, sans-serif;
  --font-body: "Plus Jakarta Sans", system-ui, sans-serif;
}

/* Dark theme. data-theme is resolved before first paint (index.html head
   script): explicit toggle choice wins, else the OS preference. Charts read
   these tokens at render time, so they adapt on re-render too. The kit's dark
   screens are navy; the primary lightens to Therapeia Blue 40 so it can be
   both a fill (with dark text on it) and a link colour on navy. */
[data-theme="dark"] {
  --color-primary: #78aeff;          /* Therapeia Blue 40 */
  --color-primary-strong: #a3c8ff;
  --color-on-primary: #090e1d;
  --color-accent: #3dd6db;
  --color-background: #090e1d;
  --color-surface: #131a2e;
  --color-foreground: #f2f5f9;
  --color-text-secondary: #9ea7b8;   /* Asklepios Gray 40 */
  --color-muted: #1b2438;
  --color-border: #2a3f66;
  --color-border-neutral: #26304a;
  --color-destructive: #ff8391;
  --color-ring: #78aeff;
  --color-highlight: #78aeff;
  --color-highlight-soft: #16264a;
  --color-surface-2: #1b2438;

  --chart-systolic: #78aeff;
  --chart-diastolic: #e8993c;
  --chart-tertiary: #bc95ff;
  --chart-grid: #1e2740;

  --dose-taken: #9ea7b8;
  --dose-late: #f9ab00;
  --dose-missed: #ff8391;

  --shadow-card: 0 1px 2px rgba(0, 0, 0, 0.5), 0 8px 24px rgba(0, 0, 0, 0.3);
  --shadow-raised: 0 2px 6px rgba(0, 0, 0, 0.4), 0 16px 40px rgba(0, 0, 0, 0.45);
}

/* Components whose light styling uses raw status hues, re-derived for dark. */
[data-theme="dark"] .chip-normal   { color: #7ee2a8; border-color: #1d5b38; background: rgba(34, 101, 60, 0.22); }
[data-theme="dark"] .chip-elevated { color: #fbd571; border-color: #6b5410; background: rgba(133, 101, 14, 0.2); }
[data-theme="dark"] .chip-stage_1  { color: #ffb37e; border-color: #7c3d12; background: rgba(154, 68, 18, 0.2); }
[data-theme="dark"] .chip-stage_2  { color: #ff9b9b; border-color: #7f2b2b; background: rgba(153, 27, 27, 0.25); }
[data-theme="dark"] .chip-crisis   { color: #ffffff; border-color: #b91c1c; background: #7f1d1d; }
[data-theme="dark"] .dose-chip-taken  { color: #7ee2a8; border-color: #1d5b38; background: rgba(34, 101, 60, 0.22); }
[data-theme="dark"] .dose-chip-late   { color: #fbd571; border-color: #6b5410; background: rgba(133, 101, 14, 0.2); }
[data-theme="dark"] .dose-chip-missed { color: #ff9b9b; border-color: #7f2b2b; background: rgba(153, 27, 27, 0.25); }
[data-theme="dark"] .form-error { background: rgba(153, 27, 27, 0.16); border-color: #7f2b2b; }
[data-theme="dark"] .med-streak { color: #ff9b9b; background: rgba(153, 27, 27, 0.2); border-color: #7f2b2b; }
[data-theme="dark"] .icon-btn-danger:hover { background: rgba(153, 27, 27, 0.2); }
[data-theme="dark"] .plausibility-box,
[data-theme="dark"] .offline-banner { background: rgba(133, 101, 14, 0.16); border-color: #6b5410; color: #fbd571; }
[data-theme="dark"] .modal-backdrop::backdrop { background: rgba(0, 0, 0, 0.6); }
[data-theme="dark"] .toast-action { border-color: rgba(0, 0, 0, 0.4); }
[data-theme="dark"] .toast-action:hover { background: rgba(0, 0, 0, 0.08); }

* { box-sizing: border-box; }

/* author display rules (flex/grid) must not defeat the hidden attribute */
[hidden] { display: none !important; }

/* remove the 300ms double-tap delay on all controls */
button, input, select, textarea, a { touch-action: manipulation; }

.visually-hidden {
  position: absolute; width: 1px; height: 1px; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap;
}

html {
  -webkit-text-size-adjust: 100%;
  /* What shows in the rubber-band overscroll and behind the status bar before
     the header paints: the page colour, not white. */
  background-color: var(--color-background);
  -webkit-tap-highlight-color: transparent;
}

body {
  margin: 0;
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.6;
  color: var(--color-foreground);
  background: var(--color-background);
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
}

h1, h2, h3 { font-family: var(--font-heading); line-height: 1.25; margin: 0 0 0.5rem; }
h2 { font-size: 1.125rem; font-weight: 600; }

.container {
  width: 100%; max-width: 1100px; margin: 0 auto;
  padding-left: max(20px, var(--safe-left)); padding-right: max(20px, var(--safe-right));
}

main.container { flex: 1; padding-top: 24px; padding-bottom: 48px; }

/* -------- accessibility -------- */
.skip-link {
  position: absolute; left: -9999px; top: 0;
  background: var(--color-surface); color: var(--color-foreground);
  padding: 10px 16px; z-index: 100; border-radius: 0 0 8px 0;
}
.skip-link:focus { left: 0; }

:focus-visible {
  outline: 3px solid var(--color-ring);
  outline-offset: 2px;
  border-radius: 4px;
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition: none !important; animation: none !important; }
}

/* -------- header / footer -------- */
.site-header {
  background: var(--color-surface);
  border-bottom: 1px solid var(--color-border-neutral);
}
.header-row { display: flex; align-items: center; justify-content: space-between; min-height: 60px; }
.brand { display: flex; align-items: center; gap: 10px; text-decoration: none; color: inherit; }
.brand-tile { width: 28px; height: 28px; }
.brand-name { font-family: var(--font-heading); font-weight: 700; font-size: 1.2rem; }
.header-user { display: flex; align-items: center; gap: 12px; }
.header-actions { display: flex; align-items: center; gap: 12px; }

.offline-banner {
  background: #fefce8;
  border-bottom: 1px solid #fde68a;
  color: #854d0e;
  text-align: center;
  padding: 8px 16px;
  font-size: 0.9rem;
}

.site-footer {
  border-top: 1px solid var(--color-border-neutral);
  background: var(--color-surface);
  padding: 14px 0;
  font-size: 0.8rem;
  color: var(--color-text-secondary);
  font-style: italic;
  text-align: center;
}
.site-footer p { margin: 0; }

/* -------- cards -------- */
.card {
  background: var(--color-surface);
  border: 1px solid var(--color-border-neutral);
  border-radius: var(--radius);
  box-shadow: var(--shadow-card);
  padding: 20px;
}

/* -------- buttons -------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  font: 500 1rem var(--font-body);
  min-height: 44px;
  padding: 0 18px;
  border-radius: 8px;
  border: 1px solid transparent;
  cursor: pointer;
  transition: background-color 180ms ease-out, border-color 180ms ease-out, color 180ms ease-out;
}
.btn svg { width: 18px; height: 18px; }
.btn-primary { background: var(--color-primary); color: var(--color-on-primary); }
.btn-primary:hover { background: var(--color-primary-strong); }
.btn-secondary {
  background: var(--color-surface); color: var(--color-primary-strong);
  border-color: var(--color-border-neutral);
}
.btn-secondary:hover { background: var(--color-muted); }
.btn-ghost { background: transparent; color: var(--color-text-secondary); }
.btn-ghost:hover { background: var(--color-muted); color: var(--color-foreground); }
.btn-block { width: 100%; }
.btn[disabled] { opacity: 0.5; cursor: not-allowed; }

/* -------- auth -------- */
#auth-view { display: flex; justify-content: center; padding-top: 4vh; }

/* Landing: hero + feature list beside the sign-in card. */
.landing {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 420px;
  gap: 56px;
  align-items: start;
  width: 100%;
  max-width: 1040px;
}
.landing-hero { padding-top: 10px; }
.hero-title { font-size: 2.1rem; line-height: 1.15; margin: 0 0 14px; max-width: 22ch; }
.hero-sub {
  color: var(--color-text-secondary);
  font-size: 1.05rem;
  margin: 0 0 22px;
  max-width: 54ch;
}
.hero-ctas { display: flex; gap: 12px; flex-wrap: wrap; }
.hero-demo-hint { margin: 10px 0 0; }
.feature-list { list-style: none; margin: 32px 0 0; padding: 0; display: grid; gap: 18px; }
.feature-list li { display: flex; gap: 12px; align-items: flex-start; }
.feature-list svg { width: 22px; height: 22px; flex: none; color: var(--color-primary); margin-top: 2px; }
.feature-list strong { display: block; font-family: var(--font-heading); font-weight: 600; }
.feature-list span { color: var(--color-text-secondary); font-size: 0.92rem; }

@media (max-width: 900px) {
  .landing { grid-template-columns: 1fr; gap: 32px; }
  .hero-title { font-size: 1.7rem; }
}

.auth-card { width: 100%; max-width: 440px; padding: 28px; }
.auth-title { font-size: 1.3rem; margin-bottom: 16px; }

.tabs { display: flex; gap: 4px; background: var(--color-muted); padding: 4px; border-radius: 10px; margin-bottom: 20px; }
.tab {
  flex: 1; min-height: 40px; border: 0; border-radius: 7px; background: transparent;
  font: 500 0.95rem var(--font-body); color: var(--color-text-secondary); cursor: pointer;
  transition: background-color 150ms ease-out, color 150ms ease-out;
}
.tab.is-active { background: var(--color-surface); color: var(--color-foreground); box-shadow: var(--shadow-card); }

/* -------- forms -------- */
.field { margin-bottom: 14px; flex: 1; min-width: 0; }
.field label { display: block; font-weight: 500; font-size: 0.9rem; margin-bottom: 4px; }
.field-row { display: flex; gap: 12px; }
.req { color: var(--color-destructive); }

input, select, textarea {
  width: 100%;
  min-height: 44px;
  padding: 8px 12px;
  font: 400 1rem var(--font-body);
  color: var(--color-foreground);
  background: var(--color-surface);
  border: 1px solid var(--color-border-neutral);
  border-radius: 8px;
}
textarea { resize: vertical; min-height: 60px; }

/* The block above is written for text fields: full width, and a 44px min-height
   so a finger can hit them. Applied to a checkbox or radio it does the opposite
   of what it looks like — the control still *paints* at its natural size, but
   occupies a 44px-tall, full-width box, which silently inflated every row it
   sat in (the condition cards opened a ~30px hole between each name and its
   description). The touch target is the surrounding label, which is the whole
   card, so nothing is lost by reverting these to their intrinsic size. */
input[type="checkbox"], input[type="radio"] {
  width: auto; min-height: 0; padding: 0;
}
input:focus, select:focus, textarea:focus {
  outline: 3px solid var(--color-ring); outline-offset: 0; border-color: var(--color-primary);
}
input[aria-invalid="true"] { border-color: var(--color-destructive); }

.helper { font-size: 0.8rem; color: var(--color-text-secondary); margin: 4px 0 0; }
.field-error { font-size: 0.85rem; color: var(--color-destructive); margin: 4px 0 0; }
.form-error {
  font-size: 0.9rem; color: var(--color-destructive);
  background: #fef2f2; border: 1px solid #fecaca; border-radius: 8px;
  padding: 10px 12px; margin: 0 0 14px;
}

.password-wrap { position: relative; }
.password-wrap input { padding-right: 48px; }
.password-toggle {
  position: absolute; right: 4px; top: 50%; transform: translateY(-50%);
  width: 40px; height: 40px; border: 0; background: transparent; cursor: pointer;
  color: var(--color-text-secondary); display: flex; align-items: center; justify-content: center;
  border-radius: 6px;
}
.password-toggle svg { width: 20px; height: 20px; }
.password-toggle:hover { color: var(--color-foreground); }

/* refetch keeps the frame: dim stale content instead of blanking it */
#dash-view.is-loading .card,
#dash-view.is-loading .stat-tile { opacity: 0.6; transition: opacity 200ms ease-out; }

/* -------- dashboard layout -------- */
.toolbar { display: flex; justify-content: space-between; align-items: center; gap: 16px; flex-wrap: wrap; margin-bottom: 18px; }
.toolbar-actions { display: flex; gap: 10px; flex-wrap: wrap; }

.range-picker { display: inline-flex; flex-wrap: wrap; background: var(--color-surface); border: 1px solid var(--color-border-neutral); border-radius: 10px; padding: 4px; gap: 2px; }
.range-btn {
  border: 0; background: transparent; min-height: 38px; padding: 0 14px;
  border-radius: 7px; font: 500 0.9rem var(--font-body); color: var(--color-text-secondary);
  cursor: pointer; transition: background-color 150ms ease-out, color 150ms ease-out;
}
.range-btn:hover { background: var(--color-muted); }
.range-btn.is-active { background: var(--color-primary); color: var(--color-on-primary); }

/* As many columns as there are tiles (up to the width): a fixed four left
   the fifth tile alone on a row of its own. */
.stat-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 14px; margin-bottom: 18px; }
.stat-tile {
  background: var(--color-surface); border: 1px solid var(--color-border-neutral);
  border-radius: var(--radius); box-shadow: var(--shadow-card); padding: 14px 18px;
  display: flex; flex-direction: column; gap: 2px;
}
.stat-label { font-size: 0.82rem; color: var(--color-text-secondary); }
.stat-value { font: 600 1.6rem var(--font-heading); }
.stat-unit { font-size: 0.9rem; font-weight: 400; color: var(--color-text-secondary); }

.dash-grid { display: grid; grid-template-columns: 1fr 360px; gap: 18px; margin-bottom: 18px; align-items: start; }

.card-head { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; flex-wrap: wrap; }
.legend { display: flex; gap: 16px; font-size: 0.85rem; color: var(--color-text-secondary); flex-wrap: wrap; }
.legend-item { display: inline-flex; align-items: center; gap: 6px; }
.legend-line { display: inline-block; width: 18px; height: 0; border-top: 3px solid; border-radius: 2px; }
.legend-dot { display: inline-block; width: 9px; height: 9px; border-radius: 50%; }
.legend-x { font-size: 0.85rem; font-weight: 700; line-height: 1; }
.legend-x::before { content: "\2715"; }
.chart-wrap svg { cursor: pointer; }
.tt-hint { margin-top: 4px; font-size: 0.72rem; color: var(--color-text-secondary); }
.legend-triangle {
  display: inline-block; width: 0; height: 0;
  border-left: 5px solid transparent; border-right: 5px solid transparent;
  border-bottom: 9px solid; /* color set inline per status */
}

/* -------- chart -------- */
.chart-card { position: relative; }
.chart-wrap { width: 100%; min-height: 300px; }
.chart-wrap svg { display: block; width: 100%; height: auto; }
/* Set by chart.js when the canvas is wider than the card, which only happens
   where the readings would otherwise overlap. */
.chart-wrap.is-scrollable {
  overflow-x: auto; -webkit-overflow-scrolling: touch;
  scrollbar-width: thin;
}
.chart-wrap.is-scrollable svg { width: auto; max-width: none; }
.chart-tooltip {
  position: absolute; z-index: 20; pointer-events: none;
  background: var(--color-surface); border: 1px solid var(--color-border-neutral);
  border-radius: 8px; box-shadow: 0 4px 12px rgba(9, 14, 29, 0.12);
  padding: 8px 12px; font-size: 0.85rem; min-width: 150px;
}
.tt-time { color: var(--color-text-secondary); font-size: 0.78rem; margin-bottom: 4px; }
.tt-row { display: flex; align-items: center; gap: 8px; }
.tt-key { display: inline-block; width: 14px; border-top: 3px solid; border-radius: 2px; }
.tt-value { font-weight: 700; font-variant-numeric: tabular-nums; }
.tt-series { color: var(--color-text-secondary); }
.tt-cat { margin-top: 4px; font-size: 0.78rem; color: var(--color-text-secondary); }

/* -------- table -------- */
.table-card h2 { margin-bottom: 10px; }
.table-scroll { overflow-x: auto; }
table { border-collapse: collapse; width: 100%; font-size: 0.92rem; }
th, td { text-align: left; padding: 9px 12px; border-bottom: 1px solid var(--color-border-neutral); }
th { font-family: var(--font-heading); font-weight: 600; font-size: 0.82rem; color: var(--color-text-secondary); }
td.num { font-variant-numeric: tabular-nums; }
tbody tr:hover { background: var(--color-muted); }

.chip {
  display: inline-block; padding: 2px 10px; border-radius: 999px;
  font-size: 0.78rem; font-weight: 500; border: 1px solid;
}
.chip-normal   { color: #166534; border-color: #bbf7d0; background: #f0fdf4; }
.chip-elevated { color: #854d0e; border-color: #fde68a; background: #fefce8; }
.chip-stage_1  { color: #9a3412; border-color: #fed7aa; background: #fff7ed; }
.chip-stage_2  { color: #991b1b; border-color: #fecaca; background: #fef2f2; }
.chip-crisis   { color: #ffffff; border-color: #7f1d1d; background: #991b1b; }

.empty-state { color: var(--color-text-secondary); text-align: center; padding: 28px 12px; margin: 0; }

.row-actions { text-align: right; width: 52px; }
.icon-btn {
  width: 44px; height: 44px; margin: -8px 0;   /* full touch target without inflating the row */
  border: 0; background: transparent; border-radius: 8px; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--color-text-secondary);
  transition: background-color 150ms ease-out, color 150ms ease-out;
}
.icon-btn svg { width: 18px; height: 18px; }
/* The "i" that opens an explanation. The glyph is small and the hit area is
   the full 44pt; the negative margins stop it adding height or width to the
   row it sits in. */
.info-btn { margin: -14px -10px; }
.info-btn svg { width: 16px; height: 16px; }
.card-head .info-btn { margin: -8px 0; }
/* A heading with its "i" beside it. The heading keeps the margin the card
   gave it, so the row under it sits where it always did. */
.head-title { display: flex; align-items: center; gap: 6px; min-width: 0; margin-bottom: 0.6rem; }
.head-title h2, .card-head .head-title h2 { margin: 0; }
.head-title .info-btn, .card-head .head-title .info-btn { margin: -8px 0 -8px -4px; }
.card-head .head-title { margin-bottom: 0; }
.label-row { display: flex; align-items: center; justify-content: space-between; gap: 6px; }
.label-row .info-btn { margin: -14px -10px -14px 0; }
legend .info-btn { vertical-align: middle; margin: -14px 0 -14px -4px; }
.info-text { margin: 0; white-space: pre-line; line-height: 1.5; }
/* Opened over another dialog (Goals & conditions), two backdrops would
   otherwise stack into a near-black screen. */
#info-modal::backdrop { background: rgba(9, 14, 29, 0.25); }
.icon-btn-danger:hover { background: #fef2f2; color: var(--color-destructive); }
.icon-btn[disabled] { opacity: 0.4; cursor: not-allowed; }

/* -------- medications -------- */
.meds-card { margin-top: 18px; }
.meds-card .card-head { margin-bottom: 10px; }

/* -------- patterns card -------- */
.patterns-list { list-style: none; margin: 0 0 10px; padding: 0; display: grid; gap: 8px; }
.patterns-list li { padding-left: 18px; position: relative; }
.patterns-list li::before {
  content: ""; position: absolute; left: 2px; top: 0.55em;
  width: 7px; height: 7px; border-radius: 50%; background: var(--color-primary);
}

/* -------- plausibility ("did you mean?") -------- */
.plausibility-box {
  margin: 10px 0; padding: 12px 14px;
  border: 1px solid #fde68a; background: #fefce8; color: #854d0e;
  border-radius: 8px; font-size: 0.92rem;
}
.plausibility-box p { margin: 0 0 10px; }
.plausibility-actions { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 4px; }
.suggestion-btn {
  display: inline-flex; align-items: center;
  min-height: 40px; padding: 4px 14px; margin-top: 4px;
  border: 1px solid var(--color-primary); border-radius: 999px;
  background: var(--color-surface); color: var(--color-primary);
  font: 600 0.85rem var(--font-body); cursor: pointer;
}
.suggestion-btn:hover { background: var(--color-muted); }

/* -------- questions for my doctor -------- */
.q-form { display: flex; gap: 10px; margin: 10px 0 6px; }
.q-form input { flex: 1; min-width: 0; }
.q-list { list-style: none; margin: 6px 0 0; padding: 0; }
.q-list li {
  display: flex; align-items: flex-start; gap: 10px;
  padding: 8px 0; border-bottom: 1px solid var(--color-border-neutral);
}
.q-list li:last-child { border-bottom: none; }
.q-text { flex: 1; }

/* -------- today's doses -------- */
.med-title { display: inline-flex; align-items: baseline; gap: 8px; }
.med-dosage { color: var(--color-text-secondary); font-size: 0.88rem; white-space: nowrap; }
.dose-time { font-variant-numeric: tabular-nums; margin-right: 2px; }
.time-row { display: flex; align-items: center; gap: 6px; margin-bottom: 8px; }
.time-row input[type="time"] { max-width: 180px; }
.med-today-title { font-size: 0.95rem; margin: 0 0 4px; }
#med-today { margin-bottom: 14px; padding-bottom: 10px; border-bottom: 1px solid var(--color-border-neutral); }
/* What and when on the left, the status or the Taken / Missed pair on the
   right. A grid rather than a wrapping flex row: the flex version let
   "Missed" fall onto a line of its own once the name got long. */
.dose-row {
  display: grid; grid-template-columns: minmax(0, 1fr) auto;
  align-items: center; gap: 8px 12px; padding: 8px 0;
}
.dose-row + .dose-row { border-top: 1px solid var(--color-border-neutral); }
.dose-label { min-width: 0; overflow-wrap: anywhere; }
.dose-actions { display: flex; gap: 8px; justify-content: flex-end; }
.dose-chip {
  font-size: 0.78rem; font-weight: 600; padding: 2px 10px; border-radius: 999px;
  border: 1px solid var(--color-border-neutral); text-transform: capitalize;
}
.dose-chip-taken { color: #166534; border-color: #bbf7d0; background: #f0fdf4; }
.dose-chip-late { color: #854d0e; border-color: #fde68a; background: #fefce8; }
.dose-chip-missed { color: #991b1b; border-color: #fecaca; background: #fef2f2; }
.dose-chip-upcoming { color: var(--color-text-secondary); background: var(--color-muted); }

/* -------- guided reading modal -------- */
/* A native <dialog>, opened with showModal(). The browser supplies the top
   layer, the backdrop, focus containment, Escape, and inertness of the page
   behind -- all of which this used to hand-roll. What is left here is undoing
   the UA's default box (border, padding, size caps) so the dialog can go on
   being the full-viewport flex centerer the layout already expects. */
.modal-backdrop {
  /* position/inset stated rather than inherited from the UA's `dialog:modal`
     rule, which differs between engines. box-sizing is border-box globally
     (line 86), so the 20px padding sits inside the viewport box. */
  position: fixed; inset: 0;
  border: 0; margin: 0; background: transparent;
  /* Clear of the notch and home indicator in landscape and portrait. */
  padding: max(20px, var(--safe-top)) max(20px, var(--safe-right))
           max(20px, var(--safe-bottom)) max(20px, var(--safe-left));
  width: 100%; height: 100%; max-width: 100%; max-height: 100%;
  overflow: visible;
}
.modal-backdrop:not([open]) { display: none; }
.modal-backdrop[open] { display: flex; align-items: center; justify-content: center; }
.modal-backdrop::backdrop { background: rgba(9, 14, 29, 0.45); }
.modal { max-width: 500px; width: 100%; max-height: 90dvh; overflow: auto;
  /* The UA resets a dialog's color to the system canvas text colour, which is
     white when the OS is dark even if the app is in light mode — leaving any
     un-coloured text (a bare heading) invisible. Pin it to the theme. */
  color: var(--color-foreground); }
.guided-intro { margin: 0 0 8px; }
.guided-checklist { margin: 0 0 10px; padding-left: 22px; color: var(--color-text-secondary); }
.guided-checklist li { margin: 5px 0; }
.guided-timer { text-align: center; margin: 14px 0 6px; }
.guided-count {
  font-family: var(--font-heading); font-weight: 700; font-size: 2.6rem;
  font-variant-numeric: tabular-nums; line-height: 1.1;
}
.guided-timer-actions { display: flex; gap: 12px; justify-content: center; flex-wrap: wrap; margin-top: 10px; }
.guided-ready { text-align: center; font-weight: 600; color: var(--color-primary); margin: 10px 0; }
.guided-step-title { margin: 0 0 10px; font-size: 1.05rem; }
.badge {
  display: inline-block; padding: 1px 8px; border-radius: 6px;
  font-size: 0.72rem; font-weight: 600; white-space: nowrap;
}
.badge-guided {
  color: var(--color-primary); border: 1px solid var(--color-border);
  background: var(--color-muted);
}

/* -------- crisis + category education dialogs -------- */
.crisis-lead { font-weight: 600; margin: 0 0 10px; }
.crisis-steps { margin: 0 0 10px; padding-left: 20px; }
.crisis-steps li { margin: 8px 0; }
.crisis-actions { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 12px; }
#crisis-modal .modal { border-top: 4px solid #991b1b; }
/* Category chips are buttons when an explainer exists: same pill, plus a
   focus ring and pointer so it reads as actionable (not color alone). */
.chip-button {
  cursor: pointer; font: inherit; font-size: 0.78rem; font-weight: 500;
}
.chip-button:hover { filter: brightness(0.97); }
.chip-button:focus-visible { outline: 2px solid var(--color-ring); outline-offset: 2px; }

/* -------- context tags (multi-select) -------- */
.tag-fieldset { border: 1px solid var(--color-border-neutral); border-radius: 10px; padding: 10px 12px; margin: 4px 0 2px; }
.tag-fieldset legend { font-size: 0.85rem; font-weight: 600; color: var(--color-text-secondary); padding: 0 6px; }
.tag-options { display: flex; flex-wrap: wrap; gap: 8px 14px; }
.tag-check { display: inline-flex; align-items: center; gap: 6px; min-height: 44px; cursor: pointer; font-size: 0.9rem; }
.tag-check input { width: 18px; height: 18px; accent-color: var(--color-primary); }

/* -------- target range card -------- */
.target-current { font-weight: 600; margin: 4px 0 0; }
.target-actions { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 6px; }

/* -------- measurement habit + reminders -------- */
.habit-today { font-weight: 600; font-size: 1.05rem; margin: 4px 0 2px; }
.habit-streak { margin: 0 0 10px; color: var(--color-text-secondary); }
.reminder-form { border-top: 1px solid var(--color-border-neutral); padding-top: 10px; }
.reminder-toggle { display: inline-flex; align-items: center; gap: 8px; min-height: 44px; cursor: pointer; }
.reminder-toggle input { width: 18px; height: 18px; accent-color: var(--color-primary); }
.reminder-next { margin: 6px 0 0; font-weight: 600; color: var(--color-primary); }

/* -------- caregiver summary -------- */
.caregiver-form { border-top: 1px solid var(--color-border-neutral); padding-top: 10px; margin-top: 12px; }
.caregiver-row { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; }
.caregiver-row input { flex: 1 1 220px; }
.btn-small { min-height: 44px; padding: 0 14px; font-size: 0.88rem; }
#med-form { border-bottom: 1px solid var(--color-border-neutral); padding-bottom: 14px; margin-bottom: 10px; }

.med-row {
  display: flex; align-items: center; gap: 16px; flex-wrap: wrap;
  padding: 12px 4px; border-bottom: 1px solid var(--color-border-neutral);
}
.med-row:last-child { border-bottom: 0; }
.med-info { display: flex; flex-direction: column; min-width: 200px; flex: 1; }
.med-detail { font-size: 0.82rem; color: var(--color-text-secondary); }
.med-stats { display: flex; flex-direction: column; align-items: flex-end; min-width: 220px; }
.med-rate { font: 600 1.15rem var(--font-heading); }
.med-streak {
  font-size: 0.78rem; font-weight: 500; color: #991b1b;
  background: #fef2f2; border: 1px solid #fecaca; border-radius: 999px;
  padding: 1px 10px; margin-top: 3px;
}
.med-actions { display: flex; gap: 8px; }

@media (max-width: 640px) {
  .med-stats { align-items: flex-start; }
}

/* -------- toast -------- */
.toast {
  position: fixed; bottom: 24px; left: 50%; transform: translateX(-50%);
  background: var(--color-foreground); color: var(--color-background);
  padding: 12px 20px; border-radius: 10px; font-size: 0.95rem;
  box-shadow: 0 6px 20px rgba(9, 14, 29, 0.3); z-index: 1000;
}
.toast.toast-error { background: var(--color-destructive); }
.toast { display: flex; align-items: center; gap: 14px; }
.toast-action {
  border: 1px solid rgba(255, 255, 255, 0.5); background: transparent;
  color: #ffffff; font: 600 0.9rem var(--font-body);
  min-height: 36px; padding: 0 14px; border-radius: 8px; cursor: pointer;
}
.toast-action:hover { background: rgba(255, 255, 255, 0.15); }

/* ============================ DIET TRACKER ========================== */

/* primary nav (Blood pressure | Diet) */
.primary-nav {
  display: inline-flex; gap: 4px; margin-bottom: 18px;
  background: var(--color-surface); border: 1px solid var(--color-border-neutral);
  border-radius: 12px; padding: 5px;
}
.primary-tab {
  display: inline-flex; align-items: center; gap: 8px;
  font: 600 0.98rem var(--font-heading);
  min-height: 42px; padding: 0 20px; border-radius: 8px;
  border: 1px solid transparent; background: transparent;
  color: var(--color-text-secondary); cursor: pointer;
  transition: background-color 160ms ease-out, color 160ms ease-out;
}
.primary-tab svg { width: 18px; height: 18px; }
.primary-tab:hover { color: var(--color-foreground); }
.primary-tab.is-active {
  background: var(--color-primary); color: var(--color-on-primary);
}
.primary-tab:focus-visible { outline: 2px solid var(--color-ring); outline-offset: 2px; }

.diet-toolbar { align-items: flex-end; }
.diet-date { display: flex; align-items: center; gap: 10px; }
.diet-date label { font-weight: 600; color: var(--color-text-secondary); }
.diet-date input[type="date"] {
  min-height: 42px; padding: 0 12px; border-radius: 8px;
  border: 1px solid var(--color-border-neutral);
  background: var(--color-surface); color: var(--color-foreground);
  font: 500 1rem var(--font-body);
}
.diet-grid { grid-template-columns: 380px 1fr; }

/* daily rings */
.rings-card { margin-bottom: 18px; }
.rings-row {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px;
  justify-items: center;
}
.ring-fig { margin: 0; display: flex; flex-direction: column; align-items: center; gap: 8px; }
.ring { width: 108px; height: 108px; }
.ring-track { stroke: var(--color-muted); }
.ring-value { transition: stroke-dashoffset 500ms ease-out; }
.ring-calories .ring-value { stroke: var(--color-primary); }
.ring-protein  .ring-value { stroke: #8a3ffc; }   /* Aceso Purple: calories own the blue */
.ring-carbs    .ring-value { stroke: #d97706; }
.ring-fat      .ring-value { stroke: #0797a0; }   /* Panacea Teal, darkened to 3.3:1 */
[data-theme="dark"] .ring-protein .ring-value { stroke: #bc95ff; }
[data-theme="dark"] .ring-carbs   .ring-value { stroke: #fbbf24; }
[data-theme="dark"] .ring-fat     .ring-value { stroke: #3dd6db; }
.ring-center-top {
  font: 700 1.05rem var(--font-heading); fill: var(--color-foreground);
}
.ring-center-bottom { font: 500 0.7rem var(--font-body); fill: var(--color-text-secondary); }
.ring-fig figcaption { text-align: center; display: flex; flex-direction: column; }
.ring-name { font-weight: 600; font-size: 0.9rem; color: var(--color-foreground); }
.ring-detail { font-size: 0.78rem; color: var(--color-text-secondary); }

/* assessment (warnings / kudos / shortfalls) */
.assess-group { margin-top: 14px; }
.assess-title {
  display: flex; align-items: center; gap: 8px;
  font: 600 0.98rem var(--font-heading); margin: 0 0 8px;
}
.assess-icon { font-size: 1.05rem; line-height: 1; }
.assess-title-warn { color: #9a3412; }
.assess-title-ok   { color: #166534; }
.assess-title-low  { color: #854d0e; }
[data-theme="dark"] .assess-title-warn { color: #ffb37e; }
[data-theme="dark"] .assess-title-ok   { color: #7ee2a8; }
[data-theme="dark"] .assess-title-low  { color: #fbd571; }
.assess-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.assess-item {
  display: flex; flex-direction: column; gap: 2px;
  padding: 10px 12px; border-radius: 8px;
  background: var(--color-muted); border-left: 3px solid var(--color-border);
}
.assess-warnings .assess-item, #assess-warnings .assess-item { border-left-color: #d97706; }
#assess-kudos .assess-item { border-left-color: #16a34a; }
#assess-shortfalls .assess-item { border-left-color: #ca8a04; }
.assess-item-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.assess-item-label { font-weight: 600; font-size: 0.9rem; }
.assess-item-msg { font-size: 0.86rem; color: var(--color-text-secondary); }
.diet-disclaimer { margin-top: 16px; font-style: italic; }

/* food search + log */
.diet-log-card { position: relative; }
.food-results {
  list-style: none; margin: 4px 0 0; padding: 4px;
  border: 1px solid var(--color-border-neutral); border-radius: 8px;
  background: var(--color-surface); box-shadow: var(--shadow-card);
  max-height: 320px; overflow-y: auto;
}
.food-result {
  display: flex; flex-direction: column; gap: 2px;
  padding: 8px 10px; border-radius: 6px; cursor: pointer;
}
.food-result:hover, .food-result:focus { background: var(--color-muted); outline: none; }
.food-result-name { font-weight: 600; font-size: 0.92rem; }
.food-result-brand { font-weight: 400; color: var(--color-text-secondary); }
.food-result-meta { font-size: 0.78rem; color: var(--color-text-secondary); }
.food-src {
  align-self: flex-start; font-size: 0.68rem; font-weight: 700; letter-spacing: 0.04em;
  color: var(--color-primary-strong); border: 1px solid var(--color-border);
  border-radius: 4px; padding: 1px 5px; margin-top: 2px;
}
.food-result-empty { padding: 10px; color: var(--color-text-secondary); font-size: 0.88rem; }
.food-picked { font-size: 0.95rem; margin: 4px 0 10px; }
.food-preview { font-size: 0.84rem; color: var(--color-text-secondary); min-height: 1.2em; margin: 6px 0; }
.food-log-actions, .target-actions { display: flex; gap: 10px; margin-top: 6px; }

/* logged items */
.meal-group { margin-bottom: 16px; }
.meal-title {
  display: flex; justify-content: space-between; align-items: baseline;
  font: 600 0.95rem var(--font-heading); margin: 0 0 6px;
  padding-bottom: 4px; border-bottom: 1px solid var(--color-border-neutral);
}
.meal-kcal { font-weight: 500; font-size: 0.85rem; color: var(--color-text-secondary); }
.food-row {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 8px 0;
}
.food-row-info { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.food-row-name { font-weight: 500; }
.food-row-detail { font-size: 0.82rem; color: var(--color-text-secondary); }
.food-row-tags { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 3px; }
.food-tag {
  font-size: 0.7rem; padding: 1px 7px; border-radius: 10px;
  background: var(--color-muted); color: var(--color-text-secondary);
  border: 1px solid var(--color-border-neutral);
}
.tag-high_sodium, .tag-high_saturated_fat, .tag-added_sugar,
.tag-high_potassium, .tag-high_phosphorus, .tag-processed_meat {
  color: #9a3412; background: #fff7ed; border-color: #fed7aa;
}
.tag-dash_friendly, .tag-soluble_fiber, .tag-whole_grain,
.tag-leafy_green, .tag-fatty_fish, .tag-vitamin_c_rich, .tag-calcium_rich {
  color: #166534; background: #f0fdf4; border-color: #bbf7d0;
}
[data-theme="dark"] .tag-high_sodium, [data-theme="dark"] .tag-high_saturated_fat,
[data-theme="dark"] .tag-added_sugar, [data-theme="dark"] .tag-high_potassium,
[data-theme="dark"] .tag-high_phosphorus, [data-theme="dark"] .tag-processed_meat {
  color: #ffb37e; background: rgba(154, 68, 18, 0.2); border-color: #7c3d12;
}
[data-theme="dark"] .tag-dash_friendly, [data-theme="dark"] .tag-soluble_fiber,
[data-theme="dark"] .tag-whole_grain, [data-theme="dark"] .tag-leafy_green,
[data-theme="dark"] .tag-fatty_fish, [data-theme="dark"] .tag-vitamin_c_rich,
[data-theme="dark"] .tag-calcium_rich {
  color: #7ee2a8; background: rgba(34, 101, 60, 0.22); border-color: #1d5b38;
}

/* micronutrient breakdown */
.micro-group { margin-bottom: 18px; }
.micro-group-title {
  font: 600 0.9rem var(--font-heading); color: var(--color-text-secondary);
  text-transform: uppercase; letter-spacing: 0.04em; margin: 0 0 8px;
}
.micro-row {
  display: grid; grid-template-columns: 150px 100px 1fr 120px; align-items: center;
  gap: 12px; padding: 5px 0; font-size: 0.86rem;
}
.micro-name { font-weight: 500; display: inline-flex; align-items: center; gap: 2px; min-width: 0; }
.micro-amount { color: var(--color-text-secondary); text-align: right; font-variant-numeric: tabular-nums; }
.micro-target { color: var(--color-text-secondary); font-size: 0.8rem; }
.micro-bar-track {
  height: 8px; border-radius: 5px; background: var(--color-muted); overflow: hidden;
}
.micro-bar-fill { height: 100%; border-radius: 5px; transition: width 400ms ease-out; }
.micro-bar-fill.bar-ok   { background: #16a34a; }
.micro-bar-fill.bar-low  { background: #ca8a04; }
.micro-bar-fill.bar-near { background: #ea580c; }
.micro-bar-fill.bar-over { background: var(--color-destructive); }
.micro-bar-fill.bar-none { background: var(--color-border-neutral); }

/* preview-build notice on the landing */
.build-note {
  margin-top: 10px; padding: 8px 12px; border-radius: 8px;
  background: var(--color-muted); border: 1px solid var(--color-border-neutral);
  font-size: 0.85rem;
}

/* rings note — cited source of the day's targets */
.rings-note {
  margin: 14px 0 0; padding-top: 12px; border-top: 1px solid var(--color-border-neutral);
  font-size: .82rem; color: var(--color-text-secondary); line-height: 1.5;
}

/* calorie/macro target method chooser */
.macro-method { border: none; padding: 0; margin: 0 0 18px; }
.macro-method legend { font: 600 1rem var(--font-heading); padding: 0; margin-bottom: 4px; }
.method-tabs { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; margin: 12px 0; }
.method-tab {
  display: flex; flex-direction: column; gap: 2px; align-items: center; text-align: center;
  padding: 12px 8px; border: 1px solid var(--color-border-neutral); border-radius: 10px;
  cursor: pointer; transition: border-color 160ms ease-out, background-color 160ms ease-out;
}
.method-tab:hover { background: var(--color-muted); }
.method-tab.is-active { border-color: var(--color-primary); background: var(--color-muted); }
.method-tab input { position: absolute; opacity: 0; width: 0; height: 0; }
.method-tab:focus-within { outline: 2px solid var(--color-ring); outline-offset: 2px; }
.method-tab-title { font-weight: 600; font-size: .92rem; color: var(--color-foreground); }
.method-tab-sub { font-size: .74rem; color: var(--color-text-secondary); }
.method-panel { margin-top: 6px; }
.method-result {
  margin: 8px 0 0; font-weight: 600; font-size: .95rem; color: var(--color-primary-strong);
  font-variant-numeric: tabular-nums;
}
/* Wraps rather than crushing: a long unit label ("mmol/L") next to a narrow
   field would otherwise squeeze the number box to a few pixels. The select
   drops to its own line instead. */
.input-unit { display: flex; gap: 6px; flex-wrap: wrap; }
.input-unit input { flex: 1 1 7rem; min-width: 0; }
/* Sized to its content, not pinned: 68px fit "kg" and clipped "mmol/L" to
   "mmo". width:auto is needed to escape the global `select { width: 100% }`,
   which otherwise resolves against the flex row and re-pins it. min-width
   keeps the short labels a comfortable tap target. */
.input-unit select { flex: 0 0 auto; width: auto; min-width: 5.5rem; }
.estimate-box {
  margin: 10px 0; padding: 12px 14px; border-radius: 10px;
  background: var(--color-muted); border: 1px solid var(--color-border);
  font-size: .95rem; display: flex; flex-direction: column; gap: 4px;
}
.estimate-box strong { color: var(--color-primary-strong); font-size: 1.05rem; }
.estimate-src { font-size: .8rem; color: var(--color-text-secondary); font-weight: 400; }

/* recipe builder */
.modal-wide { max-width: 620px; }
.recipe-name-field { flex: 2; }
.recipe-subhead { font: 600 1rem var(--font-heading); margin: 16px 0 8px; }
.ingredient-add { position: relative; }
.ingredient-search-field { position: relative; }
.ingredient-list { list-style: none; margin: 10px 0 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.ingredient-row {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 10px; border: 1px solid var(--color-border-neutral); border-radius: 8px;
}
.ingredient-info { flex: 1; display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.ingredient-name { font-weight: 500; font-size: 0.92rem; }
.ingredient-detail { font-size: 0.78rem; color: var(--color-text-secondary); }
.ingredient-grams {
  width: 84px; min-height: 44px; padding: 0 8px; text-align: right;
  border: 1px solid var(--color-border-neutral); border-radius: 10px;
  background: var(--color-surface); color: var(--color-foreground);
  font: 500 1rem var(--font-body);   /* 16px: smaller makes iOS zoom in */
}
.ingredient-unit { font-size: 0.85rem; color: var(--color-text-secondary); }
.recipe-summary {
  margin: 14px 0; padding: 12px 14px; border-radius: 10px;
  background: var(--color-muted); border: 1px solid var(--color-border);
  display: flex; flex-direction: column; gap: 4px; font-size: 0.95rem;
}
.recipe-summary strong { color: var(--color-primary-strong); font-size: 1.05rem; }
.recipe-yield { font-size: 0.82rem; color: var(--color-text-secondary); }
.food-src-recipe {
  align-self: flex-start; font-size: 0.68rem; font-weight: 700; letter-spacing: 0.04em;
  color: #7c3aed; border: 1px solid #c4b5fd; border-radius: 4px; padding: 1px 5px; margin-top: 2px;
}
[data-theme="dark"] .food-src-recipe { color: #c4b5fd; border-color: #5b21b6; }

/* conditions in settings modal */
.diet-conditions { border: none; padding: 0; margin: 0 0 16px; }
.diet-conditions legend { font: 600 1rem var(--font-heading); padding: 0; margin-bottom: 4px; }
.condition-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-top: 10px; }
.condition-option {
  display: grid; grid-template-columns: auto 1fr; gap: 4px 10px; align-items: start;
  padding: 10px 12px; border: 1px solid var(--color-border-neutral); border-radius: 8px;
  cursor: pointer; transition: border-color .12s ease, box-shadow .12s ease, background .12s ease;
}
.condition-option:hover { background: var(--color-muted); }
.condition-option input {
  /* Spans every row rather than a fixed two: the card now carries a third
     child (the applied-targets list), and `span 2` left it stranded in the
     checkbox column. */
  margin-top: 2px; grid-row: 1 / -1; width: 18px; height: 18px;
  accent-color: var(--color-primary); cursor: pointer;
}
/* Whole card highlights when its condition is selected (JS adds .is-selected;
   :has() is the progressive-enhancement fallback for browsers that support it). */
.condition-option.is-selected,
.condition-option:has(input:checked) {
  border-color: var(--color-primary);
  background: var(--color-muted);
  box-shadow: inset 0 0 0 1px var(--color-primary);
}
.condition-name { font-weight: 600; font-size: 0.9rem; }
.condition-item { position: relative; }
.condition-item .condition-option { height: 100%; padding-right: 40px; }
.condition-item .info-btn { position: absolute; top: 2px; right: 0; margin: 0; }

/* The figures this condition actually applies. Outlined rather than filled:
   the card's own background changes when it is selected, so a filled chip
   would disappear into it in one of the two states. */
.condition-changes {
  grid-column: 2; margin: 6px 0 0; padding: 0; list-style: none;
  display: flex; flex-wrap: wrap; gap: 5px;
}
.condition-changes li {
  font: 500 0.72rem var(--font-body); color: var(--color-text-secondary);
  border: 1px solid var(--color-border-neutral); border-radius: 999px;
  padding: 2px 9px; white-space: nowrap;
}
.condition-option.is-selected .condition-changes li,
.condition-option:has(input:checked) .condition-changes li {
  border-color: var(--color-primary); color: var(--color-foreground);
}

/* -------- BP + diet observation -------- */
/* Neutral on purpose. This is two of the patient's own logs shown together,
   not a warning: red would assert a severity the app has no standing to
   judge, and would read as blame for the readings. */
.observations { margin-bottom: 18px; }
.observation-card { border-left: 4px solid var(--color-primary); }
.observation-title {
  font: 600 1rem var(--font-heading); margin: 0 0 8px;
}
.observation-facts {
  margin: 0 0 10px; padding-left: 20px;
  display: flex; flex-direction: column; gap: 6px;
}
.observation-facts li { font-size: 0.92rem; }
.observation-intakes {
  margin: 6px 0 0; padding-left: 18px;
  display: flex; flex-direction: column; gap: 5px;
}
.observation-intakes li { font-size: 0.9rem; }
.observation-next {
  margin: 0; font-size: 0.82rem; color: var(--color-text-secondary);
  padding-top: 9px; border-top: 1px solid var(--color-border-neutral);
}

/* -------- per-nutrient target overrides -------- */
.custom-target-list { display: flex; flex-direction: column; gap: 6px; }
.custom-target-row {
  display: grid; grid-template-columns: 1fr auto 96px; gap: 10px;
  align-items: center; padding: 7px 10px;
  border: 1px solid var(--color-border-neutral); border-radius: 8px;
}
.custom-target-name { font-weight: 500; font-size: 0.88rem; margin: 0; }
.custom-target-published {
  font-size: 0.76rem; color: var(--color-text-secondary);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.custom-target-input { min-height: 38px; text-align: right; }
.custom-target-row.is-invalid .custom-target-input { border-color: var(--color-destructive); }
/* A row carrying a number the patient supplied reads differently from one
   still on its published figure — the whole point of the section is knowing
   which of your targets are yours. */
.custom-target-row.is-overridden {
  border-color: var(--color-primary);
  background: var(--color-muted);
}
.custom-target-row.is-overridden .custom-target-published { text-decoration: line-through; }
@media (max-width: 640px) {
  /* Three columns will not fit a phone without shrinking the input to a box
     you cannot type a four-digit sodium figure into. */
  .custom-target-row {
    grid-template-columns: 1fr 96px;
    grid-template-areas: "name input" "published input";
    row-gap: 2px;
  }
  .custom-target-name { grid-area: name; }
  .custom-target-published { grid-area: published; }
  .custom-target-input { grid-area: input; align-self: center; }
}

/* -------- barcode scanner -------- */
.scan-btn { width: 100%; margin-top: 8px; }
.scan-btn svg { width: 18px; height: 18px; }
.scan-viewport {
  position: relative; width: 100%; aspect-ratio: 4 / 3;
  background: #000; border-radius: 10px; overflow: hidden;
}
.scan-viewport video { width: 100%; height: 100%; object-fit: cover; display: block; }
/* Dim everything outside a central "aim here" window. */
.scan-reticle {
  position: absolute; left: 10%; right: 10%; top: 32%; bottom: 32%;
  border: 2px solid rgba(255, 255, 255, .9); border-radius: 8px;
  box-shadow: 0 0 0 100vmax rgba(0, 0, 0, .38);
}
/* A red line sweeping up and down inside the square while the scanner
   waits, so it reads as working rather than frozen. The span is as tall as
   the square and carries the line on its top edge, so translateY(100%) moves
   the line exactly one square-height: transform only, no layout per frame. */
.scan-line {
  position: absolute; left: 6px; right: 6px; top: 0; height: 100%;
  animation: scan-sweep 2.2s ease-in-out infinite alternate;
  pointer-events: none;
}
.scan-line::before {
  content: ""; position: absolute; left: 0; right: 0; top: 0; height: 2px;
  border-radius: 2px; background: #ff2d2d;
  box-shadow: 0 0 8px 1px rgba(255, 45, 45, .75);
}
@keyframes scan-sweep {
  from { transform: translateY(4px); }
  to { transform: translateY(calc(100% - 6px)); }
}
/* Without motion the line holds still across the middle of the square. */
@media (prefers-reduced-motion: reduce) {
  .scan-line { animation: none; transform: translateY(50%); }
}
.scan-status { text-align: center; margin: 10px 0 4px; }

/* The phone app's live scanner. The camera is drawn by ML Kit behind the
   web view, so while it runs the page goes see-through: the page background
   is cleared and everything but this dialog is hidden. */
html.live-scanning, html.live-scanning body { background: transparent !important; }
html.live-scanning body > :not(#live-scan-modal) { visibility: hidden; }
/* Specific enough to beat the dark theme's and the later blurred backdrop. */
html .modal-backdrop.live-scan::backdrop {
  background: transparent; -webkit-backdrop-filter: none; backdrop-filter: none;
}
.live-scan[open] {
  flex-direction: column; align-items: center; justify-content: space-between;
  color: #fff; overflow: hidden;
}
.live-scan-head, .live-scan-foot {
  position: relative; z-index: 1;   /* above the reticle's dimming shadow */
  width: 100%; max-width: 420px;
}
.live-scan-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.live-scan-head h2 { margin: 0; color: #fff; font-size: 1.15rem; }
.live-scan-close { color: #fff; background: rgba(0, 0, 0, .35); width: 44px; height: 44px; }
.live-scan-reticle {
  position: relative; inset: auto;
  width: min(80vw, 340px); aspect-ratio: 16 / 9;
  box-shadow: 0 0 0 100vmax rgba(0, 0, 0, .5);
}
.live-scan-status { text-align: center; margin: 0 0 12px; color: #fff; }
.scan-manual { margin-top: 4px; }
.scan-source { margin-top: 12px; font-size: .76rem; }

/* -------- Good/Watch/Limit rating badges (spec 5.4) --------
   Filled pills with white text on fixed, dark-enough colours, so contrast
   holds in both themes without a per-theme override. The rating word is
   spelled out — colour is never the only signal. */
.rate-good  { --rate-color: #15803d; }
.rate-watch { --rate-color: #b45309; }
.rate-limit { --rate-color: #b91c1c; }

/* -------- Snap & Predict card (spec 5.3) -------- */
.food-prediction {
  margin-top: 10px; padding: 10px 12px;
  border: 1px solid var(--color-border-neutral); border-radius: var(--radius);
  background: var(--color-muted);
}
.predict-title {
  margin: 0 0 6px; font: 600 0.76rem var(--font-heading);
  color: var(--color-text-secondary); text-transform: uppercase; letter-spacing: .04em;
}
.predict-row { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; padding: 3px 0; }
.predict-metric { font-weight: 600; color: var(--color-foreground); }
.predict-delta { font-weight: 700; font-variant-numeric: tabular-nums; color: var(--color-foreground); }
.predict-range { margin-left: auto; font-size: 0.8rem; color: var(--color-text-secondary); }
.predict-note { margin: 6px 0 0; font-size: 0.76rem; color: var(--color-text-secondary); }

/* -------- Grocery Scanner result card (spec 5.4) -------- */
#scan-result { margin-top: 6px; }
.scan-rating {
  display: flex; align-items: center; gap: 10px; padding: 8px 0 4px;
  border-left: 4px solid var(--rate-color, var(--color-primary)); padding-left: 10px;
}
.scan-rating-badge {
  font: 700 0.76rem var(--font-heading); text-transform: uppercase; letter-spacing: .04em;
  color: #fff; background: var(--rate-color, var(--color-primary));
  padding: 4px 10px; border-radius: 999px; flex: none;
}
.scan-food-name { font-weight: 600; color: var(--color-foreground); }
.scan-reason { margin: 8px 0; color: var(--color-text-secondary); font-size: 0.88rem; }
.scan-swaps-title {
  margin: 10px 0 6px; font: 600 0.8rem var(--font-heading);
  color: var(--color-text-secondary); text-transform: uppercase; letter-spacing: .03em;
}
.scan-swaps { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.scan-swap { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.swap-badge {
  font: 700 0.66rem var(--font-heading); text-transform: uppercase; letter-spacing: .03em;
  color: #fff; background: var(--rate-color, var(--color-primary));
  padding: 2px 7px; border-radius: 999px; flex: none;
}
.swap-name { font-weight: 600; color: var(--color-foreground); }
.swap-reason { width: 100%; padding-left: 2px; font-size: 0.8rem; color: var(--color-text-secondary); }
.scan-actions { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 14px; }
.scan-actions .btn { flex: 1 1 auto; }

/* -------- My Triggers card (spec 5.6) -------- */
.triggers-title { margin: 0 0 10px; font: 700 1.05rem var(--font-heading); color: var(--color-foreground); }
.triggers-metric + .triggers-metric {
  margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--color-border-neutral);
}
.triggers-metric-title { margin: 0 0 2px; font: 600 0.98rem var(--font-heading); color: var(--color-foreground); }
.triggers-accuracy { margin: 0 0 8px; font-size: 0.8rem; color: var(--color-text-secondary); }
.triggers-sub {
  margin: 8px 0 4px; font: 600 0.78rem var(--font-heading);
  color: var(--color-text-secondary); text-transform: uppercase; letter-spacing: .03em;
}
.triggers-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 4px; }
.trigger-item {
  display: flex; align-items: baseline; gap: 10px; padding: 5px 8px;
  border-radius: 8px; background: var(--color-muted); border-left: 3px solid transparent;
}
.trigger-up   { border-left-color: #b91c1c; }
.trigger-down { border-left-color: #15803d; }
.trigger-cat { font-weight: 600; color: var(--color-foreground); }
.trigger-effect { font-weight: 700; font-variant-numeric: tabular-nums; color: var(--color-foreground); }
.trigger-meta { margin-left: auto; font-size: 0.78rem; color: var(--color-text-secondary); }
.triggers-foot { margin-top: 12px; }

/* -------- Home dashboard (spec 5.2) -------- */
.btn-sm { min-height: 36px; padding: 0 14px; font-size: 0.85rem; }

.budget + .budget { margin-top: 14px; }
.budget-head { display: flex; justify-content: space-between; align-items: baseline; gap: 8px; }
.budget-name { font-weight: 600; color: var(--color-foreground); }
.budget-figure { font-variant-numeric: tabular-nums; color: var(--color-text-secondary); font-size: 0.9rem; }
.budget-track { height: 10px; border-radius: 999px; background: var(--color-muted); overflow: hidden; margin: 6px 0 4px; }
.budget-fill { height: 100%; border-radius: 999px; }
.budget-goal  { background: #15803d; }
.budget-limit { background: var(--color-primary); }
.budget-over  { background: var(--color-destructive); }


/* -------- first-run safety notice (spec FR-1.6) -------- */
.safety-points { margin: 10px 0 4px; padding-left: 20px; color: var(--color-text-secondary); }
.safety-points li { margin-bottom: 6px; line-height: 1.5; }

/* -------- responsive -------- */
@media (max-width: 900px) {
  .dash-grid { grid-template-columns: 1fr; }
  .diet-grid { grid-template-columns: 1fr; }
  .stat-row { grid-template-columns: repeat(2, 1fr); }
  .rings-row { grid-template-columns: repeat(2, 1fr); }
  .condition-grid { grid-template-columns: 1fr; }
  .micro-row { grid-template-columns: 120px 80px 1fr; }
}
@media (max-width: 640px) {
  .field-row { flex-direction: column; gap: 0; }
  .toolbar { flex-direction: column; align-items: stretch; }
  .range-picker { justify-content: space-between; }
  /* "14 days" wrapped onto a second line while "7 days" did not, so the four
     buttons rendered at two different heights inside one control. */
  .range-btn { flex: 1; padding: 0 6px; white-space: nowrap; font-size: 0.85rem; }
  /* Same for the action row: "Doctor report PDF" wrapped while "BP log book"
     stayed on one line, leaving a pair of mismatched buttons side by side. */
  .toolbar-actions .btn {
    flex: 1 1 calc(50% - 5px); min-width: 0;
    padding: 0 10px; font-size: 0.92rem; text-align: center;
  }

  /* ---- phone navigation: a bottom tab bar ----
     Desktop keeps the tabs inline at the top; on a phone they move into thumb
     reach, which is where the platform conventions put primary navigation and
     where a hand actually rests on a 6-inch screen. Fixed rather than sticky so
     it survives the long scroll down the diet log. */
  /* The bar's height is a token, so the padding that clears it is derived
     rather than guessed: the bar is (--tabbar-h - 1px) plus the home indicator. */
  :root { --tabbar-h: 66px; }
  /* Accessibility mode makes the bar taller (bigger labels, bigger targets). */
  :root[data-a11y-text] { --tabbar-h: 96px; }
  :root[data-a11y-targets] { --tabbar-h: 80px; }
  :root[data-a11y-text][data-a11y-targets] { --tabbar-h: 104px; }
  .primary-nav {
    display: flex; position: fixed; left: 0; right: 0; bottom: 0; z-index: 900;
    margin: 0; border-radius: 0; padding: 4px 6px;
    border: 0; border-top: 1px solid var(--color-border-neutral);
    background: var(--color-surface);
    /* Clear the iPhone home indicator; resolves to 0 everywhere else. */
    padding-bottom: calc(4px + var(--safe-bottom));
    padding-left: max(6px, var(--safe-left)); padding-right: max(6px, var(--safe-right));
    box-shadow: 0 -2px 12px rgba(9, 14, 29, 0.08);
  }
  .primary-tab {
    flex: 1; flex-direction: column; gap: 2px; justify-content: center;
    min-height: calc(var(--tabbar-h) - 10px); padding: 4px 6px;
    white-space: nowrap; font-size: 0.72rem; letter-spacing: 0.01em;
  }
  .primary-tab svg { width: 22px; height: 22px; }
  /* The active tab reads as selected through weight and colour rather than a
     filled pill, which at this size swallows the label. */
  .primary-tab.is-active { background: transparent; color: var(--color-primary); }
  .primary-tab.is-active .ring-name, .primary-tab.is-active { font-weight: 700; }
  [data-theme="dark"] .primary-nav { box-shadow: 0 -2px 12px rgba(0, 0, 0, 0.4); }
  /* Reserve the bar's height so the last card is never trapped underneath. */
  main.container { padding-bottom: calc(var(--tabbar-h) + 28px + var(--safe-bottom)); }

  /* ---- the day toolbar on one row ----
     Day picker and Goals were stacking into 104px of chrome before any
     content. */
  .diet-toolbar { flex-direction: row; align-items: center; gap: 8px; }
  .diet-date { flex: 1; min-width: 0; gap: 6px; }
  .diet-date label { font-size: 0.85rem; }
  /* 16px, not less: iOS zooms the whole page into any smaller field. */
  .diet-date input[type="date"] { min-width: 0; flex: 1; font-size: 1rem; padding: 0 8px; }
  .diet-toolbar .toolbar-actions { flex: 0 0 auto; }
  .diet-toolbar .toolbar-actions .btn { flex: 0 0 auto; padding: 0 12px; }
  /* The gear alone is unambiguous next to a day picker, and the full label
     costs half the row. */
  .diet-toolbar #diet-settings-toggle { font-size: 0; gap: 0; padding: 0 14px; }
  .diet-toolbar #diet-settings-toggle svg { width: 20px; height: 20px; }

  /* A grid item defaults to min-width:auto, which refuses to shrink below its
     content -- so the widened chart canvas dragged its whole card out to
     911px inside a 335px column and the page scrolled sideways instead of the
     chart doing so. This is the standard release valve. */
  .dash-grid > *, .diet-grid > * { min-width: 0; }

  /* ---- readings as cards, not a squeezed table ----
     Seven columns in 313px cannot be a table. `table { width: 100% }` made
     each row wrap to 113px of unlabelled fragments -- four visual lines per
     reading, 57 of them, 6,600px of it -- and once wrapped there was no
     telling which number was systolic. Horizontal scrolling would have been
     the other option, but a reading is a record, not a spreadsheet row, and
     scanning it sideways is worse than reading it as a block.

     Each row becomes a small card: when and category on the first line, the
     values with their labels beside them, notes and the delete action below. */
  #readings-table, #readings-table tbody, #readings-table tr, #readings-table td {
    display: block;
  }
  #readings-thead { display: none; }
  .table-scroll { overflow-x: visible; }
  /* An explicit grid, not flex-wrap. Left to wrap on its own the cells broke
     wherever they happened to run out of room -- the category landing beside
     the pulse, four ragged lines per reading -- which was the original
     complaint in a new form. Three deliberate rows instead:

         Aug 20, 8:17 PM                         [Stage 1]
         Systolic 133   Diastolic 84   Pulse 70
         (left, sitting)                            [bin]

     Only `when` and `category` are pinned; the value cells auto-flow into the
     second row, so a metric with two fields or four still lays out sensibly. */
  #readings-table tr {
    display: grid; grid-template-columns: repeat(3, auto) 1fr;
    align-items: baseline; gap: 3px 10px;
    border: 1px solid var(--color-border-neutral); border-radius: 10px;
    padding: 10px 12px; margin-bottom: 8px;
  }
  #readings-table tr:hover { background: transparent; }
  #readings-table td { border-bottom: 0; padding: 0; }
  /* Both pinned to the first row. Without the row, auto-placement put the
     first value cell in the slot beside the date and pushed the category
     down, so "Systolic 127" read as part of the date line. The values, notes
     and actions then flow into the rows below on their own. */
  .cell-when { grid-row: 1; grid-column: 1 / -2; font-weight: 600; font-size: 0.9rem; }
  .cell-category { grid-row: 1; grid-column: -2 / -1; justify-self: end; }
  /* The header is gone on a phone, so each figure carries its own label. */
  .cell-value::before {
    content: attr(data-label) " ";
    font-weight: 400; font-size: 0.72rem; color: var(--color-text-secondary);
  }
  .cell-value { font-weight: 600; }
  .cell-notes {
    grid-column: 1 / -2; font-size: 0.8rem; color: var(--color-text-secondary);
  }
  #readings-table .row-actions { grid-column: -2 / -1; justify-self: end; }
  /* The numeric range repeats identically on every row and costs half the
     card; tapping the chip still opens the full explanation. */
  .cat-range { display: none; }

  /* ---- phone reading order ----
     The desktop layout is two columns, so the food search sits beside the
     summary and both are visible at once. Stacked into one column that
     hierarchy inverts: 460px of observation and 200px of rings landed on top
     of the search box, putting the thing you opened the app to do more than a
     screen down.

     Reordered rather than collapsed, so no health information is hidden
     behind a tap — a glanceable summary first, then the action, then the
     longer reading. Desktop keeps its own order untouched. */
  #diet-panel { display: flex; flex-direction: column; }
  #diet-panel > .diet-toolbar { order: 1; }
  #diet-panel > .rings-card { order: 2; }
  #diet-panel > .diet-grid { order: 3; }
  #diet-panel > #diet-observations { order: 4; }
  /* Unordered, this sat at order 0, above the date toolbar. */
  #diet-panel > #diet-triggers { order: 4; }
  #diet-panel > .diet-log-list-card { order: 5; }
  #diet-panel > .micro-card { order: 6; }

  /* ---- rings as a swipeable strip ----
     Four rings in a 2x2 block cost 361px — nearly half the viewport — to say
     four numbers. One scroll-snapping row shows calories immediately and lets
     the rest be flicked through, which is how a phone wants to read a set of
     peers. */
  .rings-row {
    display: flex; grid-template-columns: none;
    gap: 14px; overflow-x: auto; scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    padding-bottom: 4px; margin: 0 -4px; padding-left: 4px; padding-right: 4px;
    scrollbar-width: none;
  }
  .rings-row::-webkit-scrollbar { display: none; }
  .ring-fig { flex: 0 0 auto; scroll-snap-align: start; gap: 4px; width: 96px; }
  .ring { width: 78px; height: 78px; }
  .ring-center-top { font-size: 0.9rem; }
  .rings-card { margin-bottom: 12px; padding: 14px; }
  .rings-note { font-size: 0.75rem; }

  .micro-row {
    grid-template-columns: 1fr auto;
    grid-template-areas: "name amount" "target target" "bar bar";
    row-gap: 3px;
  }
  .micro-name { grid-area: name; }
  .micro-amount { grid-area: amount; white-space: nowrap; }
  .micro-bar-track { grid-area: bar; }
  /* Deliberately NOT hidden on phones, which is what this used to do. The
     target is the number the amount is meant to be read against — "1,102 mg"
     alone says nothing about whether the day went well — and a phone is where
     this app is actually used. Given its own row so it never competes with the
     amount for width. */
  .micro-target { grid-area: target; display: block; font-size: 0.72rem; }
}

/* ---- v2: large text (FR-1.5), onboarding, portions, meal tray, shopping ----
   Large text is an explicit per-device choice, so it applies at every width;
   the rest follows the existing card and button styles. */
/* ---- Accessibility mode ----
   Four independent switches (accessibility.js), all off by default, set as
   data-a11y-* attributes on <html>. They apply at every width: they are a
   per-device choice about how the screen should look. */

/* Larger text. Nearly every size in this sheet is in rem, so the root is what
   makes the choice visible. */
:root[data-a11y-text] { font-size: 200%; }
:root[data-a11y-text] body { font-size: 1rem; }

/* High contrast: the same tokens, pushed apart. */
:root[data-a11y-contrast] {
  --color-foreground: #000000;
  --color-text-secondary: #2f394f;
  --color-border-neutral: #5f6b86;
  --color-border: #4d6ba6;
  --color-hairline: #5f6b86;
  --color-primary: #0a47b8;
  --color-primary-strong: #062f80;
  --chart-grid: #98a2b6;
}
:root[data-a11y-contrast][data-theme="dark"] {
  --color-foreground: #ffffff;
  --color-text-secondary: #dde3ef;
  --color-border-neutral: #8b98b8;
  --color-border: #8aa6dd;
  --color-hairline: #8b98b8;
  --color-primary: #a3c8ff;
  --color-primary-strong: #cfe1ff;
  --chart-grid: #5a6a8f;
}
:root[data-a11y-contrast] .card { border: 1px solid var(--color-border-neutral); }
:root[data-a11y-contrast] :is(a, .link-btn) { text-decoration: underline; }
:root[data-a11y-contrast] :focus-visible { outline-width: 3px; outline-offset: 2px; }

/* Not colour alone: the words are always in the page (.cue) and shown here,
   and the bars gain patterns, so red, orange and green are never the only
   signal. */
.cue { display: none; }
:root[data-a11y-cues] .cue { display: inline; font-weight: 700; }
:root[data-a11y-cues] :is(.bar-over, .budget-over) {
  background-image: repeating-linear-gradient(135deg, rgba(255, 255, 255, .6) 0 4px, transparent 4px 8px);
}
:root[data-a11y-cues] .bar-near {
  background-image: repeating-linear-gradient(90deg, rgba(255, 255, 255, .6) 0 3px, transparent 3px 7px);
}
:root[data-a11y-cues] .bar-low {
  background-image: radial-gradient(circle, rgba(255, 255, 255, .7) 1.2px, transparent 1.6px);
  background-size: 7px 7px;
}

/* Bigger buttons: taller targets and more air between things. */
:root[data-a11y-targets] :is(.btn, select, textarea, input:not([type="checkbox"], [type="radio"], .stepper-input)) { min-height: 56px; }
:root[data-a11y-targets] :is(.check-row, .settings-row, .range-btn, .segment) { min-height: 56px; }
:root[data-a11y-targets] .icon-btn { width: 56px; height: 56px; }
:root[data-a11y-targets] .info-btn { margin: -20px -14px; }
:root[data-a11y-targets] .primary-tab { min-height: calc(var(--tabbar-h) - 10px); }
:root[data-a11y-targets] .micro-row { padding-top: 10px; padding-bottom: 10px; }
:root[data-a11y-targets] :is(#diet-panel, #bp-panel) { gap: 24px; }

/* At twice the size some fixed layouts need to give: the three tab labels, the
   big reading number, and the four-way Readings switcher. */
:root[data-a11y-text] .primary-tab { font-size: 0.56rem; padding-left: 2px; padding-right: 2px; }
:root[data-a11y-text] :is(.home-hero, #home-reading) .home-reading-value { font-size: 2rem; }
:root[data-a11y-text] .home-actions { grid-template-columns: 1fr; }
:root[data-a11y-text] .home-tile { min-height: 0; flex-direction: row; justify-content: flex-start; gap: 12px; text-align: left; }
:root[data-a11y-text] #bp-sections { display: grid; grid-template-columns: 1fr 1fr; }
:root[data-a11y-text] .bp-sections .segment span { font-size: 0.8rem; }

/* The Accessibility row in Settings: a disclosure holding the four switches. */
.settings-a11y > summary { list-style: none; cursor: pointer; }
.settings-a11y > summary::-webkit-details-marker { display: none; }
.settings-a11y > summary .row-chevron { transition: transform 180ms ease-out; }
.settings-a11y[open] > summary .row-chevron { transform: rotate(180deg); }
.settings-a11y [data-a11y-list] { border-top: 1px solid var(--color-hairline); }
@media (prefers-reduced-motion: reduce) { .settings-a11y > summary .row-chevron { transition: none; } }
.a11y-welcome { display: block; margin: 12px auto 0; }


.check-row { display: flex; gap: 10px; align-items: flex-start; min-height: 44px;
  padding: 8px 0; cursor: pointer; }
.check-row input { width: 20px; height: 20px; margin-top: 3px; flex: none; }
.radio-row { display: flex; gap: 20px; flex-wrap: wrap; }
.field-label { display: block; font-weight: 500; font-size: 0.9rem; margin-bottom: 4px; }

.onboarding-step { border: 0; padding: 0; margin: 0 0 12px; }
.onboarding-step legend { font-weight: 600; font-size: 1.05rem; margin-bottom: 6px; padding: 0; }
.onboarding-actions { display: flex; gap: 10px; justify-content: flex-end; }
.onboarding-actions .btn { min-height: 44px; min-width: 96px; }
.potassium-restrict { margin-top: 12px; }

.portion-presets { display: flex; gap: 6px; margin: 4px 0 10px; }
.portion-presets .range-btn { flex: 1; min-height: 44px; }

.meal-tray { margin-top: 16px; padding-top: 12px; border-top: 1px solid var(--color-border); }
.meal-tray h3 { font-size: 1rem; margin: 0 0 6px; }
.meal-tray-list, .shopping-items { list-style: none; margin: 0 0 8px; padding: 0; }
.meal-tray-item, .shopping-item { display: flex; flex-wrap: wrap; align-items: center;
  justify-content: space-between; gap: 6px 10px; padding: 6px 0;
  border-bottom: 1px solid var(--color-border); }

.shopping-item-main { display: flex; align-items: center; gap: 8px; flex: 1 1 60%; }
.shopping-item-name { font-weight: 500; }
.shopping-item-meta { flex-basis: 100%; order: 3; font-size: 0.82rem;
  color: var(--color-text-secondary); }
#shopping-modal h3 { font-size: 1rem; margin: 14px 0 4px; }

/* Snap results: a short list of full-width rows, one food per row, so a long
   name wraps inside its own row rather than scattering pills across lines. */
.snap-choices {
  display: flex; flex-direction: column; gap: 4px;
  margin: 12px 0; padding: 6px;
  background: var(--color-muted); border-radius: var(--radius);
}
.snap-choices-title {
  margin: 4px 8px 4px; font: 600 0.82rem var(--font-heading);
  color: var(--color-text-secondary); letter-spacing: 0.01em;
}
.snap-choice {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  width: 100%; min-height: 48px; padding: 10px 14px;
  border: 0; border-radius: var(--radius-sm);
  background: var(--color-surface); color: var(--color-foreground);
  font: 500 0.95rem var(--font-body); text-align: left; cursor: pointer;
  box-shadow: 0 1px 2px rgba(9, 14, 29, 0.05);
  transition: background-color 150ms ease-out, transform 120ms ease-out;
}
.snap-choice::after {
  content: ""; flex: none; width: 8px; height: 8px;
  border-right: 2px solid var(--color-text-secondary);
  border-top: 2px solid var(--color-text-secondary);
  transform: rotate(45deg); margin-right: 4px;
}
.snap-choice:hover { background: var(--color-surface-hover); }
.snap-choice:active { transform: scale(0.99); }
.snap-choice-name { min-width: 0; }
.snap-choice-none {
  background: transparent; box-shadow: none;
  color: var(--color-primary); font-weight: 600;
}
.snap-choice-none:hover { background: var(--color-surface); }

/* ======================= asklepios look ======================
   The kit's shape language: big rounded cards on a cool gray field, soft
   shadows instead of outlines, tinted secondary actions, a dark navy pill
   for the selected segment, and very large bold numerals. Presentation only:
   no layout order, element, or wording changes live here. */
:root {
  --color-hairline: rgba(9, 14, 29, 0.06);
  --color-surface-hover: #f7f9fc;
  --color-tint: #edf5ff;             /* Therapeia Blue 10 */
}
[data-theme="dark"] {
  --color-hairline: rgba(255, 255, 255, 0.06);
  --color-surface-hover: #182137;
  --color-tint: #16264a;
}

body { -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }
h1, h2, h3 { letter-spacing: -0.015em; }
h2 { font-size: 1.2rem; font-weight: 600; }

/* Metric numbers are the personality of the app: heavy, tight, with
   tabular figures so digits line up as they change. */
.stat-value, .home-reading-value, .ring-center-top, .guided-count,
.med-rate, .trigger-effect, .predict-delta {
  font-family: var(--font-heading);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
}
.stat-value { font-size: 1.9rem; font-weight: 600; }
.home-reading-value { font-size: 2.4rem; letter-spacing: -0.03em; }

/* header: sticky and translucent, so it stays put without a hard slab */
.site-header {
  position: sticky; top: 0; z-index: 800;
  background: var(--color-surface);  /* iOS < 16.2 has no color-mix */
  background: color-mix(in srgb, var(--color-surface) 82%, transparent);
  -webkit-backdrop-filter: saturate(180%) blur(14px);
  backdrop-filter: saturate(180%) blur(14px);
  border-bottom: 1px solid var(--color-hairline);
  padding-top: var(--safe-top);
}
.brand-tile { border-radius: 8px; }

/* cards: a hairline plus a soft shadow instead of a drawn outline */
.card, .stat-tile {
  border-color: var(--color-hairline);
  border-radius: var(--radius);
}
.card { padding: 22px; }

/* Space between a panel's cards comes from the panel, as one gap, rather
   than from a margin on each card class. Spacing used to be a margin-bottom
   per card, and every card added without one (Logged today, Nutrient
   breakdown, Targets, Habit, Questions, Caregiver, Recent readings) sat flush
   against the next with their borders touching. A new card now gets the gap
   without anyone having to remember it. */
#diet-panel, #bp-panel { display: flex; flex-direction: column; gap: 18px; }
#diet-panel > *, #bp-panel > * { margin-top: 0; margin-bottom: 0; }
@media (max-width: 640px) {
  #diet-panel, #bp-panel { gap: 14px; }
}

/* buttons */
.btn { border-radius: var(--radius-sm); font-weight: 600; letter-spacing: 0.005em; }
.btn:active:not([disabled]) { transform: scale(0.98); }
.btn { transition: background-color 180ms ease-out, border-color 180ms ease-out,
  color 180ms ease-out, transform 120ms ease-out, box-shadow 180ms ease-out; }
.btn-primary { box-shadow: 0 1px 2px rgba(9, 14, 29, 0.12), 0 6px 16px rgba(15, 103, 254, 0.24); }
[data-theme="dark"] .btn-primary { box-shadow: none; }
.btn-secondary {
  background: var(--color-tint); border-color: transparent;
  color: var(--color-primary-strong);
}
.btn-secondary:hover { background: var(--color-muted); border-color: var(--color-border); }

/* fields */
input, select, textarea { border-radius: var(--radius-sm); }
input:focus, select:focus, textarea:focus {
  outline: 0; border-color: var(--color-primary);
  box-shadow: 0 0 0 3px var(--color-tint);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--color-ring) 22%, transparent);
}
input[type="search"] {
  padding-left: 40px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%235d6a85' stroke-width='2' stroke-linecap='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='m20 20-3.5-3.5'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: 14px center; background-size: 18px;
}
.diet-date input[type="date"] { border-radius: var(--radius-sm); }

/* segmented controls */
.tabs, .range-picker { border-radius: var(--radius-sm); }
.range-picker { border-color: var(--color-hairline); }
.tab, .range-btn { border-radius: 9px; }

/* desktop tabs: a floating segmented pill */
.primary-nav {
  border-color: var(--color-hairline); border-radius: 14px;
  box-shadow: var(--shadow-card);
}
.primary-tab { border-radius: 10px; }

/* results, dialogs, toasts */
.food-results { border-color: var(--color-hairline); border-radius: var(--radius-sm); box-shadow: var(--shadow-raised); }
.food-result { border-radius: 8px; }
.modal { border-radius: 20px; box-shadow: var(--shadow-raised); }
.modal-backdrop::backdrop {
  background: rgba(9, 14, 29, 0.4);
  -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px);
}
.toast { border-radius: 14px; box-shadow: var(--shadow-raised); max-width: calc(100vw - 32px); }

/* chips and bars a touch softer */
.budget-track { height: 8px; }
.assess-item, .trigger-item { border-radius: 10px; }

/* Scan and Snap side by side; one fills the row when the other is hidden. */
.food-actions { display: flex; gap: 8px; margin-top: 8px; }
.food-actions .scan-btn {
  flex: 1 1 0; margin-top: 0; min-width: 0;
  flex-direction: column; gap: 4px; min-height: 72px;
  padding: 8px; font-size: 0.88rem; line-height: 1.2; text-align: center;
}
.food-actions .scan-btn svg { width: 22px; height: 22px; }

/* --- premium touches --- */

/* Primary action: Therapeia Blue with a whisper of depth so it reads as
   raised, not a flat block. */
.btn-primary {
  background: linear-gradient(180deg, var(--color-primary) 0%, var(--color-primary-strong) 100%);
}
.btn-primary:hover { background: var(--color-primary-strong); }


/* Progress: a rounded track with a blue fill for a goal being filled. */
.budget-track { height: 9px; }
/* A goal (reach this) and a limit (stay under this) must not share a colour:
   the limit is the primary blue, a goal the kit's Panacea Teal. The words under
   each bar say which is which either way. */
.budget-goal { background: #0797a0; }
[data-theme="dark"] .budget-goal { background: #3dd6db; }

/* A small inline spinner for on-device work ("Finding your food…"). */
.spinner {
  width: 18px; height: 18px; flex: none; border-radius: 50%;
  border: 2px solid var(--color-border);
  border-top-color: var(--color-highlight);
  animation: spin 0.7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
.finding {
  display: flex; align-items: center; gap: 10px;
  padding: 14px 16px; margin: 12px 0;
  background: var(--color-surface); border: 1px solid var(--color-hairline);
  border-radius: var(--radius); box-shadow: var(--shadow-card);
  font: 500 0.95rem var(--font-body); color: var(--color-foreground);
}
@media (prefers-reduced-motion: reduce) { .spinner { animation-duration: 2s; } }

/* Bottom-sheet variant of the native dialog: on a phone it rises from the
   bottom edge (thumb reach); on wider screens it stays a centered card. */
.modal-backdrop.sheet[open] { align-items: center; }
.modal.modal-sheet { max-width: 460px; }
.sheet-grip { display: none; }
.sheet-title { margin: 0 0 4px; font: 600 1.1rem var(--font-heading); }
.sheet-sub { margin: 0 0 14px; color: var(--color-text-secondary); font-size: 0.9rem; }

/* Choice rows inside the meal-photo sheet: stacked, tinted so they lift off
   the sheet surface, with the best match flagged. */
#snap-sheet-body { display: flex; flex-direction: column; gap: 8px; }
#snap-sheet-body .snap-choice { background: var(--color-surface-2); box-shadow: none; }
#snap-sheet-body .snap-choice:hover { background: var(--color-tint); }
#snap-sheet-body .finding { background: var(--color-surface-2); box-shadow: none; margin: 0; }
#snap-sheet-body .snap-choice-name { flex: 1 1 auto; }
.snap-choice-badge {
  flex: none; margin-right: 8px;
  font: 600 0.66rem var(--font-heading); text-transform: uppercase; letter-spacing: 0.04em;
  color: var(--color-primary-strong); background: var(--color-highlight-soft);
  padding: 3px 8px; border-radius: var(--radius-pill);
}

@media (max-width: 640px) {
  .modal-backdrop.sheet[open] { align-items: flex-end; }
  /* A sheet rises from the bottom edge and never climbs under the notch. */
  .modal-backdrop.sheet { padding: var(--safe-top) 0 0; }
  .modal.modal-sheet {
    max-width: 100%; width: 100%;
    max-height: calc(100dvh - var(--safe-top) - 12px);
    border-radius: 22px 22px 0 0;
    padding-bottom: calc(20px + var(--safe-bottom));
    padding-left: max(20px, var(--safe-left)); padding-right: max(20px, var(--safe-right));
    animation: sheet-up var(--dur-sheet) var(--ease-out);
  }
  .sheet-grip {
    display: block; width: 40px; height: 4px; border-radius: 999px;
    background: var(--color-border-neutral); margin: 2px auto 14px;
  }
  @keyframes sheet-up { from { transform: translateY(100%); } to { transform: translateY(0); } }
  @media (prefers-reduced-motion: reduce) { .modal.modal-sheet { animation: none; } }
}

@media (max-width: 640px) {
  .card { padding: 18px; }
  .container { padding-left: max(16px, var(--safe-left)); padding-right: max(16px, var(--safe-right)); }
  main.container { padding-top: 16px; }

  /* bottom tab bar: translucent, with a pill behind the active icon */
  .primary-nav {
    background: var(--color-surface);
    background: color-mix(in srgb, var(--color-surface) 96%, transparent);
    -webkit-backdrop-filter: saturate(180%) blur(16px);
    backdrop-filter: saturate(180%) blur(16px);
    border-top: 1px solid var(--color-hairline);
    box-shadow: none;
    border-radius: 0;
  }
  .primary-tab svg {
    box-sizing: content-box; padding: 4px 16px; border-radius: 999px;
    transition: background-color 180ms ease-out;
  }
  .primary-tab.is-active svg { background: var(--color-tint); }

  /* Toasts drop in from the top on a phone. At the bottom they sat on the
     tab bar, and inside a sheet on top of its Save button. */
  .toast { top: calc(var(--safe-top) + 10px); bottom: auto; width: max-content; }


  /* the footer disclaimer sat under the fixed tab bar */
  .site-footer { padding-bottom: calc(var(--tabbar-h) + 28px + var(--safe-bottom)); }
}

/* ---- asklepios patterns ---- */
h1, h2, h3 { font-weight: 800; letter-spacing: -0.02em; }
h2 { font-size: 1.15rem; }
.brand-name { font-weight: 800; letter-spacing: -0.02em; }
.btn { font-weight: 700; }

/* The selected segment is a navy pill, as in the kit's range pickers. It
   inverts in dark mode (light pill on navy), which keeps the same contrast. */
.range-btn.is-active {
  background: var(--color-foreground); color: var(--color-surface);
}
.range-picker { background: var(--color-surface); border-color: transparent; box-shadow: var(--shadow-card); }

/* Very large, heavy numerals with a quieter unit: the kit's "121", "1,542". */
.home-reading-value { font-weight: 800; font-size: 2.6rem; letter-spacing: -0.03em; line-height: 1.1; }
.stat-value { font-weight: 800; letter-spacing: -0.02em; }
.ring-center-top { font-weight: 800; }
.guided-count { font-weight: 800; }
.med-rate { font-weight: 800; }

/* Status chips: soft tints with no outline. The AHA hues stay, since their
   order means something clinically, and every chip keeps its words. */
.chip, .dose-chip { border-color: transparent; font-weight: 600; }
.chip-crisis { background: #da1e2e; }


/* Cards: the kit's generous padding and a slightly larger title gap. */
.card > h2:first-child, .card-head h2 { margin-bottom: 0.6rem; }
.home-reading-unit {
  font-size: 1rem; font-weight: 600; letter-spacing: 0;
  color: var(--color-text-secondary); white-space: nowrap;
}

/* ============================ native shell ============================
   Rules for being an app rather than a page. .is-native is set on <html> by
   theme-init.js before first paint, only inside the Capacitor shell; the web
   build never matches these. */

/* Only one of each pair shows, so the web and the app can share markup. */
.native-only { display: none; }
html.is-native .native-only { display: revert; }
html.is-native .web-only { display: none; }

html.is-native {
  /* A page rubber-bands; an app screen does not drag its whole frame. */
  overscroll-behavior-y: none;
}
html.is-native body {
  /* Long-press on a button or label selects text and pops a callout menu:
     the fastest giveaway that an "app" is a web page. Text the patient
     wrote, and anything they might copy, stays selectable. */
  -webkit-user-select: none; user-select: none;
  -webkit-touch-callout: none;
}
html.is-native :is(input, textarea, [contenteditable], .q-text, .cell-notes,
                   .settings-disclaimer, .scan-reason) {
  -webkit-user-select: text; user-select: text;
  -webkit-touch-callout: default;
}
/* On a phone the disclaimer lives in Settings, the first-run notice and the
   doctor report, not under every screen. */
html.is-native .site-footer { display: none; }

/* Touch screens have no hover: without this, a tapped button keeps its hover
   tint until the next tap somewhere else. */
@media (hover: none) {
  .btn-secondary:hover { background: var(--color-tint); border-color: transparent; }
  .btn-ghost:hover, .icon-btn:hover, .range-btn:hover { background: transparent; }
  .btn-primary:hover { background: linear-gradient(180deg, var(--color-primary) 0%, var(--color-primary-strong) 100%); }
  .food-result:hover, .snap-choice:hover { background: inherit; }
  .doctor-row:hover { background: var(--color-surface-2); }
}

/* ---- header ---- */
.header-row { gap: var(--space-3); }
.settings-btn { position: relative; margin-right: -6px; }
.settings-btn svg { width: 22px; height: 22px; }
.settings-btn.has-avatar .settings-gear { display: none; }
.avatar {
  display: inline-grid; place-items: center; flex: none;
  width: 34px; height: 34px; border-radius: 50%;
  background: var(--color-tint); color: var(--color-primary-strong);
  font: 800 0.95rem var(--font-heading);
}
[data-theme="dark"] .avatar { color: var(--color-primary); }
.avatar-lg { width: 48px; height: 48px; font-size: 1.2rem; }

/* ---- sheets: a head row with the title and a close button ---- */
.sheet-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--space-3); margin-bottom: var(--space-2);
}
.sheet-head .sheet-title { margin: 0; }
.sheet-head .icon-btn { margin: -8px -10px -8px 0; }

/* ---- Settings ---- */
.settings { display: flex; flex-direction: column; gap: var(--space-4); }
.settings-account {
  display: flex; align-items: center; gap: var(--space-3);
  padding: var(--space-3); border-radius: var(--radius-sm);
  background: var(--color-surface-2);
}
.settings-account-text { display: flex; flex-direction: column; min-width: 0; }
.settings-account-text strong { font-weight: 700; }
.settings-account-text span {
  font-size: 0.88rem; color: var(--color-text-secondary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.settings-label {
  margin: 0 0 calc(-1 * var(--space-2)); font: 700 0.78rem var(--font-heading);
  text-transform: uppercase; letter-spacing: 0.06em; color: var(--color-text-secondary);
}
.settings-group {
  display: flex; flex-direction: column;
  border-radius: var(--radius-sm); background: var(--color-surface-2); overflow: hidden;
}
.settings-row {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-3);
  width: 100%; min-height: 52px; padding: var(--space-3) var(--space-4);
  border: 0; background: transparent; color: var(--color-foreground);
  font: 600 1rem var(--font-body); text-align: left; cursor: pointer;
}
.settings-row + .settings-row { border-top: 1px solid var(--color-hairline); }
.settings-row-text { display: flex; flex-direction: column; min-width: 0; }
.settings-row-sub { font-size: 0.82rem; font-weight: 500; color: var(--color-text-secondary); }
.row-chevron { width: 18px; height: 18px; flex: none; color: var(--color-text-secondary); }
.settings-disclaimer {
  margin: 0; font-size: 0.82rem; line-height: 1.5; color: var(--color-text-secondary);
}
.settings-logout { color: var(--color-destructive); }

/* ---- segmented control: radios dressed as the kit's navy pill ---- */
.segmented {
  display: flex; gap: 2px; padding: 4px;
  border-radius: var(--radius-sm); background: var(--color-surface-2);
}
.segment { flex: 1; position: relative; }
.segment input { position: absolute; inset: 0; opacity: 0; margin: 0; cursor: pointer; width: 100%; height: 100%; }
.segment span {
  display: flex; align-items: center; justify-content: center;
  min-height: 44px; padding: 0 var(--space-3); border-radius: 10px;
  font: 600 0.92rem var(--font-body); color: var(--color-text-secondary);
  transition: background-color var(--dur-ui) ease-out, color var(--dur-ui) ease-out;
}
.segment input:checked + span { background: var(--color-foreground); color: var(--color-surface); }
.segment input:focus-visible + span { outline: 3px solid var(--color-ring); outline-offset: 2px; }

/* ---- switch: a checkbox that looks like iOS's ---- */
/* input[type].switch: the generic checkbox rule (width:auto, no height) is an
   attribute selector, so a bare .switch would lose to it. */
input[type="checkbox"].switch {
  appearance: none; -webkit-appearance: none; flex: none;
  position: relative; width: 51px; height: 31px; min-height: 0; margin: 0; padding: 0;
  border: 0; border-radius: 999px; background: var(--color-border-neutral); cursor: pointer;
  transition: background-color var(--dur-ui) ease-out;
}
input[type="checkbox"].switch::after {
  content: ""; position: absolute; top: 2px; left: 2px;
  width: 27px; height: 27px; border-radius: 50%; background: #fff;
  box-shadow: 0 2px 4px rgba(9, 14, 29, 0.25);
  transition: transform var(--dur-ui) var(--ease-out);
}
input[type="checkbox"].switch:checked { background: var(--color-primary); }
input[type="checkbox"].switch:checked::after { transform: translateX(20px); }
input[type="checkbox"].switch:focus-visible { outline: 3px solid var(--color-ring); outline-offset: 2px; }

/* ---- the app's welcome screen (native, signed out) ---- */
html.is-native[data-session="out"] .site-header { display: none; }
html.is-native #auth-view {
  padding-top: calc(var(--safe-top) + var(--space-6));
  padding-bottom: var(--space-5);
}
html.is-native .landing {
  display: flex; flex-direction: column; align-items: stretch; gap: var(--space-5);
  max-width: 440px; margin: 0 auto;
}
html.is-native .landing-hero { display: contents; }
html.is-native .welcome-brand { order: 1; display: flex; flex-direction: column; align-items: center; text-align: center; gap: var(--space-2); }
html.is-native .auth-card { order: 2; padding: var(--space-5); }
html.is-native .hero-ctas { order: 3; display: flex; }
html.is-native .hero-ctas #demo-btn {
  flex: 1; background: var(--color-surface); color: var(--color-primary-strong);
  box-shadow: var(--shadow-card);
}
[data-theme="dark"] .hero-ctas #demo-btn { color: var(--color-primary); }
html.is-native .build-note { order: 4; text-align: center; margin: 0; }
.welcome-logo { width: 64px; height: 64px; border-radius: 18px; box-shadow: var(--shadow-raised); }
.welcome-name { margin: var(--space-2) 0 0; font: 800 2rem var(--font-heading); letter-spacing: -0.03em; }
.welcome-line { margin: 0; max-width: 30ch; color: var(--color-text-secondary); }

/* ================= formatting pass ================= */
/* A status pill is one word on one line: "Stage 1" broke in two inside the
   reading rows and made every row twice as tall as it needed to be. */
.chip, .dose-chip { white-space: nowrap; }
/* Headings balance their lines and paragraphs avoid a one-word last line,
   so short cards stop ending on an orphan. */
h1, h2, h3 { text-wrap: balance; }
p, li, .helper { text-wrap: pretty; }
/* Patient-typed text (notes, questions, food names) can be one long word. */
.cell-notes, .q-text, .med-title, .dose-name { overflow-wrap: anywhere; }

@media (max-width: 640px) {
  /* Every dose row puts its time on a line of its own, not just the ones
     whose Taken / Missed pair crowds it out, so the list reads as one
     column of times. */
  .dose-time { display: block; }

  /* Two tiles to a row; an odd count left a hole beside the last one. */
  .stat-row .stat-tile:last-child:nth-child(odd) { grid-column: 1 / -1; }
  /* Tiles in a row share a height; the figures sit on one baseline even
     when one label runs to two lines. */
  .stat-tile { justify-content: space-between; }
  .stat-unit { font-size: 0.8rem; }

  .card-head { align-items: center; }
  .card-head h2 { min-width: 0; }

  /* The address takes the full width; the two buttons share the next row
     when their labels fit side by side. At a larger text size "Send summary
     now" used to be squeezed into a half-width box and broke over three
     lines, taller than Save beside it; now it takes a row of its own
     instead. */
  .caregiver-row input { flex: 1 1 100%; }
  .caregiver-row .btn { flex: 1 1 auto; white-space: nowrap; }
}

/* 44 pt targets wherever the pointer is a finger. */
@media (pointer: coarse) {
  .range-btn, .tab, .btn-sm, .toast-action, .suggestion-btn { min-height: 44px; }
  .password-toggle { width: 44px; height: 44px; }
}

/* ================= the Log-a-reading sheet ================= */
/* The chart has the row to itself now the form is not beside it. */
.chart-grid { grid-template-columns: minmax(0, 1fr); }
.chart-card .card-head { align-items: center; }
.chart-card .card-head h2 { margin-bottom: 0; }
.chart-card > .legend { margin: 8px 0 4px; }
.log-reading-btn { flex: none; }
.log-reading-btn svg { width: 16px; height: 16px; }
.chart-empty { display: flex; flex-direction: column; align-items: center; gap: 12px; }
.chart-empty p { margin: 0; }

/* Header and Save stay put; only the middle scrolls. */
.modal.reading-sheet { display: flex; flex-direction: column; overflow: hidden; }
.reading-sheet-form { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }
.reading-sheet-body {
  flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain;
  margin: 0 -4px; padding: 2px 4px 8px;
}
.sheet-actions {
  flex: none; padding-top: var(--space-3);
  border-top: 1px solid var(--color-border-neutral);
}
.reading-last { margin: 0 0 var(--space-3); color: var(--color-text-secondary); font-size: 0.9rem; }
.reading-metric { margin-bottom: var(--space-4); }
.reading-metric .segment span {
  padding: 4px 6px; font-size: 0.85rem; line-height: 1.15; text-align: center;
}
.reading-tools { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: var(--space-4); }
.reading-tools:not(:has(> button:not([hidden]))) { display: none; }
.reading-tools .btn { flex: 1 1 0; min-width: max-content; }

/* ---- stepper rows: label on the left, (-) number (+) on the right ---- */
.stepper-list { display: flex; flex-direction: column; margin-bottom: var(--space-2); }
.stepper-field {
  display: grid; grid-template-columns: minmax(0, 1fr) auto;
  align-items: center; gap: 4px 12px; margin: 0; padding: 8px 0;
}
.stepper-field + .stepper-field { border-top: 1px solid var(--color-border-neutral); }
.stepper-field .field-error { grid-column: 1 / -1; margin: 0; }
.stepper-head { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; min-width: 0; }
.field .stepper-label { margin: 0; font-weight: 600; font-size: 1rem; }
.stepper-unit { display: block; font-weight: 400; color: var(--color-text-secondary); font-size: 0.85rem; }
.stepper-unit-picker { width: auto; min-height: 36px; padding: 0 28px 0 10px; font-size: 16px; }
.stepper { display: grid; grid-template-columns: 48px 92px 48px; align-items: center; gap: 8px; }
.stepper-btn {
  width: 48px; height: 48px; border: 0; border-radius: 14px; padding: 0;
  display: grid; place-items: center; cursor: pointer;
  background: var(--color-surface-2); color: var(--color-primary-strong);
  touch-action: manipulation; -webkit-user-select: none; user-select: none;
  -webkit-touch-callout: none;
  transition: transform var(--dur-press) ease-out, background-color var(--dur-press) ease-out;
}
.stepper-btn svg { width: 20px; height: 20px; }
.stepper-btn:active { transform: scale(0.92); background: var(--color-tint); }
.stepper-btn:focus-visible { outline: 3px solid var(--color-ring); outline-offset: 2px; }
.stepper-btn:disabled { opacity: 0.4; }
input.stepper-input {
  height: 52px; min-height: 0; padding: 0 4px; text-align: center;
  border-radius: 14px; font: 800 1.6rem var(--font-heading);
  font-variant-numeric: tabular-nums; letter-spacing: -0.02em;
  -moz-appearance: textfield; appearance: textfield;
}
input.stepper-input::placeholder { color: var(--color-border-neutral); font-weight: 600; }
input.stepper-input::-webkit-outer-spin-button,
input.stepper-input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

/* ---- choices as chips: one tap, no dropdown ---- */
.choice-row { flex-wrap: wrap; gap: 4px 20px; }
.choice-field { flex: 0 1 auto; }
.choice-label { margin: 0 0 6px; font-weight: 500; font-size: 0.9rem; }
.choice-chips { display: flex; flex-wrap: wrap; gap: 8px; }
.choice-chip, .reading-sheet .tag-check { position: relative; min-height: 0; }
.choice-chip input, .reading-sheet .tag-check input {
  position: absolute; opacity: 0; width: 1px; height: 1px; margin: 0; pointer-events: none;
}
.choice-chip span, .reading-sheet .tag-check span {
  display: inline-flex; align-items: center; gap: 6px;
  min-height: 44px; padding: 0 16px; border-radius: var(--radius-pill, 999px);
  background: var(--color-surface-2); color: var(--color-foreground);
  border: 1.5px solid transparent; font-weight: 600; font-size: 0.92rem; cursor: pointer;
  -webkit-user-select: none; user-select: none;
  transition: background-color var(--dur-ui) ease-out, border-color var(--dur-ui) ease-out,
              transform var(--dur-press) ease-out;
}
.choice-chip span:active, .reading-sheet .tag-check span:active { transform: scale(0.96); }
/* Chosen is a border and a tick as well as a colour. */
.choice-chip input:checked + span, .reading-sheet .tag-check input:checked + span {
  background: var(--color-tint); border-color: var(--color-primary); color: var(--color-primary-strong);
}
.choice-chip input:checked + span::before, .reading-sheet .tag-check input:checked + span::before {
  content: "✓"; font-weight: 800;
}
.choice-chip input:focus-visible + span, .reading-sheet .tag-check input:focus-visible + span {
  outline: 3px solid var(--color-ring); outline-offset: 2px;
}
.reading-sheet .tag-fieldset { border: 0; padding: 0; margin: 4px 0 var(--space-3); }
.reading-sheet .tag-fieldset legend { padding: 0; margin-bottom: 6px; font-size: 0.9rem; font-weight: 500; color: var(--color-foreground); }
.reading-sheet .tag-options { gap: 8px; }

/* ---- the note, folded until wanted ---- */
.reading-note { margin: 0 0 var(--space-2); }
.reading-note summary {
  list-style: none; display: inline-flex; align-items: center; gap: 6px;
  min-height: 44px; cursor: pointer; font-weight: 600; color: var(--color-primary-strong);
}
.reading-note summary::-webkit-details-marker { display: none; }
.reading-note summary::before { content: "+"; font-size: 1.25rem; line-height: 1; width: 1ch; }
.reading-note[open] summary::before { content: "−"; }
.reading-note .field { margin-bottom: var(--space-2); }

@media (max-width: 640px) {
  /* The keyboard takes the bottom of the screen without resizing the page;
     the sheet rises by that much so Save stays in reach. */
  #reading-sheet { padding-bottom: var(--kb-inset, 0px); }
  #reading-sheet .modal.modal-sheet {
    max-height: calc(100dvh - var(--safe-top) - 12px - var(--kb-inset, 0px));
  }
  .choice-row { flex-direction: row; gap: 4px 20px; }
}

/* The spinner a busy() button shows: drawn in the button's own text colour,
   so it reads on a blue primary as well as on a pale secondary. */
.btn-spinner {
  width: 16px; height: 16px; border-width: 2px;
  border-color: currentColor; border-top-color: transparent; opacity: 0.85;
}
.btn[aria-busy="true"] { cursor: progress; }

/* ================= Readings: sections and "For your doctor" ================= */
.bp-sections, .phone-pickers { display: none; }
.caregiver-card .caregiver-form { border-top: 0; padding-top: 0; margin-top: 0; }

.doctor-card { margin-bottom: 18px; }
.doctor-card h2 { margin-bottom: var(--space-3); }
.doctor-rows { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 10px; }
.doctor-row {
  display: flex; align-items: center; gap: 12px; width: 100%; min-height: 64px;
  padding: 12px 14px; border: 0; border-radius: var(--radius-sm);
  background: var(--color-surface-2); color: var(--color-foreground);
  font: inherit; text-align: left; cursor: pointer;
  transition: background-color var(--dur-ui) ease-out, transform var(--dur-press) ease-out;
}
.doctor-row:hover { background: var(--color-tint); }
.doctor-row:active { transform: scale(0.98); }
.doctor-row:focus-visible { outline: 3px solid var(--color-ring); outline-offset: 2px; }
.doctor-row:disabled { cursor: progress; }
.doctor-row[aria-busy="true"] { justify-content: center; font-weight: 600; color: var(--color-primary-strong); }
.doctor-row-icon {
  flex: none; width: 40px; height: 40px; border-radius: 12px;
  display: grid; place-items: center;
  background: var(--color-surface); color: var(--color-primary-strong);
}
.doctor-row-icon svg { width: 20px; height: 20px; }
.doctor-row-text { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.doctor-row-text strong { font-weight: 700; }
.doctor-row-sub { font-size: 0.85rem; color: var(--color-text-secondary); }
.doctor-row .row-chevron { flex: none; width: 18px; height: 18px; color: var(--color-text-secondary); }

@media (max-width: 640px) {
  .bp-sections { display: flex; margin-bottom: var(--space-4); }
  .bp-sections .segment span { padding: 0 4px; font-size: 0.88rem; }
  /* One section at a time. Which cards belong where is in the markup. */
  #bp-panel[data-section="overview"] > [data-sect]:not([data-sect~="overview"]),
  #bp-panel[data-section="history"] > [data-sect]:not([data-sect~="history"]),
  #bp-panel[data-section="meds"] > [data-sect]:not([data-sect~="meds"]),
  #bp-panel[data-section="share"] > [data-sect]:not([data-sect~="share"]) { display: none; }
  /* One row of pickers instead of two rows of pills. */
  #bp-panel .toolbar #metric-tabs, #bp-panel .toolbar #range-picker { display: none; }
  .phone-pickers { display: flex; gap: 8px; }
  .phone-pickers select {
    flex: 1 1 0; min-width: 0; min-height: 44px; font-weight: 600;
    padding-left: 12px; padding-right: 32px; text-overflow: ellipsis;
    /* Drawn rather than left to the engine, whose arrow sits outside the
       padding and cut "Blood Pressure" short. */
    -webkit-appearance: none; appearance: none;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%235d6a85' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
    background-repeat: no-repeat; background-position: right 10px center; background-size: 16px;
  }
  /* The metric's name is the longer of the two. */
  #metric-select { flex-grow: 1.25; }
  .chart-card .card-head { flex-wrap: nowrap; }
  .chart-card .card-head h2 { font-size: 1.05rem; }
  .log-word { display: none; }
  /* Five figures in a smaller footprint, so the chart is on the first screen. */
  .stat-row { gap: 10px; margin-bottom: 14px; }
  .stat-tile { padding: 12px 14px; }
  .stat-value { font-size: 1.6rem; }
  .doctor-rows { grid-template-columns: minmax(0, 1fr); }
}

/* ================= Home ================= */
/* Desktop: greeting, the three tiles, then the reading beside today's
   budgets. Phone: one column, the reading first. */
.home {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  grid-template-areas: "greet greet" "tiles tiles" "alert alert" "hero today";
  gap: 16px 18px; align-items: start;
}
.home-greeting { grid-area: greet; }
.home-hero { grid-area: hero; }
.home-actions { grid-area: tiles; }
.home-alert { grid-area: alert; }
.home-today { grid-area: today; margin: 0; }
.home-greeting h1 { margin: 0; font: 800 1.6rem var(--font-heading); letter-spacing: -0.02em; }
.home-greeting p { margin: 2px 0 0; color: var(--color-text-secondary); }

/* The latest reading: one big number, what it is, how long ago. */
.home-hero {
  display: flex; flex-direction: column; align-items: flex-start; gap: 6px;
  width: 100%; margin: 0; padding: 18px 20px; border: 0; text-align: left;
  font: inherit; color: var(--color-foreground); cursor: pointer;
  background: linear-gradient(135deg, var(--color-tint) 0%, var(--color-surface) 75%);
  transition: transform var(--dur-press) ease-out;
}
.home-hero:active { transform: scale(0.985); }
.home-hero:focus-visible { outline: 3px solid var(--color-ring); outline-offset: 2px; }
.home-hero-top { display: flex; align-items: center; justify-content: space-between; gap: 8px; width: 100%; }
.home-hero-label { font-size: 0.9rem; font-weight: 600; color: var(--color-text-secondary); }
.home-hero-chevron { display: inline-flex; color: var(--color-text-secondary); flex: none; }
.home-hero-chevron svg { width: 18px; height: 18px; }
.home-hero .home-reading-value { font-size: 3rem; line-height: 1.05; }
.home-hero-chip { font-size: 0.85rem; padding: 4px 12px; }
.home-hero-empty { font-size: 1.05rem; font-weight: 700; color: var(--color-primary-strong); }

/* Three equal tiles: an icon and a verb. */
.home-actions { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; margin: 0; }
.home-tile {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px;
  min-height: 96px; padding: 14px 8px; border: 0; border-radius: var(--radius);
  font: 700 0.92rem var(--font-body); line-height: 1.2; text-align: center; cursor: pointer;
  background: var(--color-surface); color: var(--color-foreground); box-shadow: var(--shadow-card);
  transition: transform var(--dur-press) ease-out;
}
.home-tile:active { transform: scale(0.96); }
.home-tile:focus-visible { outline: 3px solid var(--color-ring); outline-offset: 2px; }
.tile-icon {
  width: 44px; height: 44px; border-radius: 14px; display: grid; place-items: center;
  background: var(--color-tint); color: var(--color-primary-strong);
}
.tile-icon svg { width: 22px; height: 22px; }
.tile-snap {
  background: linear-gradient(180deg, var(--color-primary) 0%, var(--color-primary-strong) 100%);
  color: var(--color-on-primary);
}
.tile-log { background: var(--color-foreground); color: var(--color-surface); }
.tile-snap .tile-icon, .tile-log .tile-icon { background: rgba(255, 255, 255, 0.18); color: inherit; }
[data-theme="dark"] .tile-snap .tile-icon, [data-theme="dark"] .tile-log .tile-icon { background: rgba(9, 14, 29, 0.1); }

/* At most one pattern, as a chip that opens My Triggers. */
.home-alert {
  display: flex; align-items: center; gap: 10px; width: 100%; min-height: 52px;
  padding: 12px 16px; border: 0; border-radius: var(--radius-sm); text-align: left;
  font: inherit; font-size: 0.95rem; color: var(--color-foreground); cursor: pointer;
  background: var(--color-surface); box-shadow: var(--shadow-card);
  transition: transform var(--dur-press) ease-out;
}
.home-alert:active { transform: scale(0.985); }
.home-alert:focus-visible { outline: 3px solid var(--color-ring); outline-offset: 2px; }
.home-alert-dot { flex: none; width: 10px; height: 10px; border-radius: 50%; background: #f59e0b; }
.home-alert-text { flex: 1 1 auto; min-width: 0; }

.home-today .card-head { align-items: center; margin-bottom: 6px; }
.home-today .card-head h2 { margin: 0; }
.link-btn {
  display: inline-flex; align-items: center; gap: 2px; min-height: 44px; padding: 0 4px;
  border: 0; background: none; cursor: pointer;
  font: 700 0.95rem var(--font-body); color: var(--color-primary-strong);
}
.link-btn .row-chevron { width: 16px; height: 16px; color: inherit; }
.home-goals-link { margin-top: 4px; margin-left: -4px; }
.budget-head .budget-figure { margin-left: auto; }
.budget-head { flex-wrap: wrap; }
.budget-cue { font-size: 0.78rem; white-space: nowrap; color: var(--color-text-secondary); }
.budget-badge { font-size: 0.75rem; font-weight: 700; padding: 2px 8px; border-radius: 999px; white-space: nowrap; }
.badge-over { background: #fef2f2; color: #991b1b; }
.badge-met { background: #f0fdf4; color: #166534; }
[data-theme="dark"] .badge-over { background: rgba(153, 27, 27, 0.25); color: #ff9b9b; }
[data-theme="dark"] .badge-met { background: rgba(34, 101, 60, 0.22); color: #7ee2a8; }

/* Placeholders while the first answer is on its way. */
.skeleton {
  display: block; border-radius: 8px;
  background: linear-gradient(90deg, var(--color-muted) 25%, var(--color-surface-2) 50%, var(--color-muted) 75%);
  background-size: 200% 100%; animation: shimmer 1.2s ease-in-out infinite;
}
.skeleton-line { height: 14px; width: 45%; }
.skeleton-big { height: 44px; width: 70%; margin: 4px 0; }
.skeleton-chip { height: 24px; width: 84px; border-radius: 999px; }
.skeleton-bar { height: 9px; width: 100%; margin: 8px 0 16px; }
@keyframes shimmer { from { background-position: 200% 0; } to { background-position: -200% 0; } }
@media (prefers-reduced-motion: reduce) { .skeleton { animation: none; } }

@media (max-width: 640px) {
  .home {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas: "greet" "hero" "tiles" "alert" "today";
    gap: 14px;
  }
  .home-greeting h1 { font-size: 1.45rem; }
  .home-tile { min-height: 92px; font-size: 0.88rem; }
}

/* ================= motion ================= */
/* Short and quiet: transform and opacity only, 100ms for a press, 180ms for
   a tab or a dialog, 260ms for a sheet. All of it goes when the phone asks
   for reduced motion. */

/* A tab slides in from the side it sits on. */
@keyframes panel-in-right { from { opacity: 0; transform: translateX(12px); } to { opacity: 1; transform: none; } }
@keyframes panel-in-left { from { opacity: 0; transform: translateX(-12px); } to { opacity: 1; transform: none; } }
.panel-in-right { animation: panel-in-right var(--dur-ui) var(--ease-out); }
.panel-in-left { animation: panel-in-left var(--dur-ui) var(--ease-out); }

/* Pressed: a small scale, so a tap is seen as well as felt. */
.btn:active:not(:disabled), .icon-btn:active, .range-btn:active,
.chip-button:active, .suggestion-btn:active { transform: scale(0.97); }
.segment:active span { transform: scale(0.97); }
.primary-tab:active svg { transform: scale(0.9); }
.primary-tab svg { transition: transform var(--dur-press) ease-out, background-color 180ms ease-out; }

/* Dialogs fade their backdrop in; a centred card rises into place. The
   phone's bottom sheet keeps its own slide up (its rule is more specific). */
@keyframes backdrop-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes modal-pop {
  from { opacity: 0; transform: translateY(8px) scale(0.98); }
  to { opacity: 1; transform: none; }
}
.modal-backdrop[open]::backdrop { animation: backdrop-in var(--dur-ui) ease-out; }
:where(.modal-backdrop[open]) > .modal { animation: modal-pop var(--dur-ui) var(--ease-out); }

/* Toasts arrive from the edge they sit on. */
@keyframes toast-in-up {
  from { opacity: 0; transform: translate(-50%, 10px); }
  to { opacity: 1; transform: translate(-50%, 0); }
}
@keyframes toast-in-down {
  from { opacity: 0; transform: translate(-50%, -10px); }
  to { opacity: 1; transform: translate(-50%, 0); }
}
.toast:not([hidden]) { animation: toast-in-up var(--dur-ui) var(--ease-out); }
@media (max-width: 640px) {
  .toast:not([hidden]) { animation-name: toast-in-down; }
}

@media (prefers-reduced-motion: reduce) {
  .panel-in-right, .panel-in-left, .toast:not([hidden]),
  :where(.modal-backdrop[open]) > .modal, .modal-backdrop[open]::backdrop { animation: none; }
  .btn:active:not(:disabled), .icon-btn:active, .range-btn:active, .chip-button:active,
  .suggestion-btn:active, .segment:active span, .primary-tab:active svg,
  .home-tile:active, .home-hero:active, .home-alert:active, .doctor-row:active,
  .stepper-btn:active, .choice-chip span:active { transform: none; }
}
