/* Karan OS — design system v1.1
   Polished on top of Tailwind. Inter font, refined spacing,
   subtle entrance animations, real dark mode. */

/* 5.2 Self-hosted Inter variable font — covers weights 100–900 in one file.
   Source: bunny.net (privacy-first Google Fonts mirror). No external request at runtime. */
@font-face {
  font-family: 'Inter';
  src: url('fonts/inter-var.woff2') format('woff2-variations');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

:root {
  --bg: #fafaf9;
  --card-bg: #ffffff;
  --card-border: rgba(15, 23, 42, 0.06);
  --card-shadow: 0 1px 3px rgba(15, 23, 42, 0.04), 0 1px 2px rgba(15, 23, 42, 0.03);
  --text: #0f172a;
  --text-muted: #64748b;
  --text-soft: #94a3b8;
  --accent: #6366f1;
  --accent-light: #c7d2fe;
  --good: #10b981;
  --warn: #f59e0b;
  --bad: #ef4444;
  --info: #0ea5e9;
  --tab-active-bg: #0f172a;
  --tab-active-fg: #ffffff;

  /* Status tint pairs (v7 D0) — text/value color is --good/--warn/--bad/--info
     above; *-bg is the matching low-opacity surface for chips/hero accents.
     Derived from --card-bg so light/dark both work without a second
     definition (--good etc. are intentionally constant across themes). */
  --good-bg: color-mix(in srgb, var(--good) 14%, var(--card-bg));
  --warn-bg: color-mix(in srgb, var(--warn) 14%, var(--card-bg));
  --bad-bg: color-mix(in srgb, var(--bad) 14%, var(--card-bg));
  --info-bg: color-mix(in srgb, var(--info) 14%, var(--card-bg));
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #0b1220;
    --card-bg: #131e33;
    --card-border: rgba(255, 255, 255, 0.05);
    --card-shadow: 0 1px 3px rgba(0, 0, 0, 0.4);
    --text: #f1f5f9;
    --text-muted: #94a3b8;
    --text-soft: #64748b;
    --accent: #818cf8;
    --accent-light: #312e81;
    --tab-active-bg: #f8fafc;
    --tab-active-fg: #0f172a;
  }
}

/* ── Preflight (V15 batch 6) ────────────────────────────────────────────────
   Minimal replacement for the Tailwind CDN's preflight reset, which this
   stylesheet was written on top of. Element selectors only — any class rule
   in this file still wins on specificity. */
*, ::before, ::after { box-sizing: border-box; border-width: 0; border-style: solid; border-color: var(--card-border); }
body { margin: 0; line-height: 1.5; }
h1, h2, h3, h4, p { margin: 0; }
ol, ul { list-style: none; margin: 0; padding: 0; }
a { color: inherit; text-decoration: inherit; }
button { background: transparent; padding: 0; color: inherit; cursor: pointer; font: inherit; }
input, select, textarea { font: inherit; color: inherit; margin: 0; }
img { max-width: 100%; height: auto; display: block; }
canvas { display: block; }

html, body {
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, system-ui, sans-serif;
  font-feature-settings: 'cv02', 'cv03', 'cv04', 'cv11', 'ss01';
  -webkit-tap-highlight-color: transparent;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  background: var(--bg);
  color: var(--text);
  letter-spacing: -0.005em;
}
/* V-scroll-fix: tried an overflow-x guard here (hidden, then clip, each paired
   with an explicit overflow-y) to stop the whole page from panning sideways
   if something overflowed the viewport width. Both attempts broke vertical
   scrolling for Karan in practice -- setting overflow-x AT ALL on the root
   html/body pair opts the page out of the browser's own "the root element
   scrolls by default" handling, and getting that back exactly right for
   every real device/browser combination proved too fragile for a benefit
   that was speculative to begin with (no confirmed horizontal-overflow
   source, just a defensive guess). Reverted -- html/body now carry no
   overflow override at all, so default browser scrolling is fully intact.
   If a genuine horizontal-scroll source shows up, fix it at that specific
   element instead of guarding the whole page's root. */

/* Sticky top bar — header + tabs pinned together as one unit.
   Previously header and .tabs-row were two separate sticky elements with a
   hardcoded `top: 92px` offset on the tabs and a frosted backdrop-filter.
   That combo broke on iOS: sticky + backdrop-filter blanks out during
   momentum/rubber-band scroll, and the 92px guess didn't match real header
   height across devices. Wrapping both in one sticky container with an opaque
   background fixes both — no magic offset, no blur layer to drop. */
.topbar {
  position: sticky;
  top: 0;
  z-index: 20;
  background: var(--bg);
  padding-top: env(safe-area-inset-top);
}

header {
  position: relative;
  z-index: 20;
}

/* Bottom tab bar — primary navigation. Fixed to the bottom, opaque, thumb-
   reachable. Buttons keep the .tab class for JS hooks but their pill look is
   overridden here by the higher-specificity .bottom-nav .nav-item rules. */
.bottom-nav {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 30;
  display: flex;
  background: var(--bg);
  border-top: 1px solid var(--card-border);
  padding-bottom: env(safe-area-inset-bottom);
}
.bottom-nav .nav-item {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  padding: 0.5rem 0 0.4rem;
  background: transparent;
  border: none;
  border-radius: 0;
  box-shadow: none;
  color: var(--text-soft);
  position: relative;
}
/* 5.3 SVG icon sprite — replaces Tabler webfont */
.icon {
  width: 1.5rem;
  height: 1.5rem;
  display: inline-block;
  vertical-align: middle;
  flex-shrink: 0;
  overflow: visible;
  /* Tabler outline icons are stroke-based, but the sprite's <symbol> paths carry
     no paint attributes — without these rules they fall back to SVG defaults
     (fill:black, stroke:none) and render as solid black blobs, invisible in dark
     mode. These properties inherit into the <use> shadow tree. */
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.icon-inline { width: 1em; height: 1em; vertical-align: -0.15em; margin-right: 0.35rem; }
.icon-muted { color: var(--text-muted); }

.bottom-nav .nav-item .nav-icon { width: 1.45rem; height: 1.45rem; }
.bottom-nav .nav-item .nav-label {
  font-size: 0.75rem;
  font-weight: 500;
  letter-spacing: 0.01em;
}
/* override .tab.tab-active pill: active item is just accent-colored, no pill */
.bottom-nav .nav-item.tab-active {
  background: transparent;
  box-shadow: none;
  color: var(--accent);
}
.bottom-nav .nav-item .tab-badge {
  position: absolute;
  top: 6px;
  left: 50%;
  margin-left: 6px;
}

/* Tab pills */
.tab {
  white-space: nowrap;
  padding: 0.45rem 0.95rem;
  border-radius: 9999px;
  font-size: 0.85rem;
  font-weight: 500;
  color: var(--text-muted);
  background: transparent;
  transition: background 0.18s ease, color 0.18s ease, transform 0.15s ease;
  border: 1px solid transparent;
}
.tab:active { transform: scale(0.96); }
.tab.tab-active {
  background: var(--tab-active-bg);
  color: var(--tab-active-fg);
  box-shadow: 0 2px 8px rgba(15, 23, 42, 0.15);
}

/* v7 D1: segmented sub-nav for the Coach (Insights/Chat) and Log
   (Eating/Weight/Movement) groups — sits between the primary tab bar and
   the page content for whichever group is active. */
.group-subnav {
  display: flex;
  gap: 0.3rem;
  padding: 0.3rem;
  margin: 0 0.1rem 1rem;
  background: color-mix(in srgb, var(--text-muted) 10%, transparent);
  border-radius: 0.85rem;
}
.group-subnav.hidden { display: none; }
.group-subnav-btn {
  flex: 1;
  padding: 0.5rem 0.6rem;
  border-radius: 0.65rem;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--text-muted);
  background: transparent;
  transition: background 0.18s ease, color 0.18s ease, transform 0.15s ease;
}
.group-subnav-btn:active { transform: scale(0.97); }
.group-subnav-btn.active {
  background: var(--card-bg);
  color: var(--text);
  box-shadow: 0 1px 4px rgba(15, 23, 42, 0.12);
}

/* Card primitives */
.card {
  background: var(--card-bg);
  border: 1px solid var(--card-border);
  border-radius: 1rem;
  padding: 1.1rem 1.2rem;
  box-shadow: var(--card-shadow);
  animation: card-in 0.42s cubic-bezier(0.16, 1, 0.3, 1) both;
}
.card-stat {
  font-size: 1.95rem;
  font-weight: 700;
  letter-spacing: -0.025em;
  line-height: 1.05;
  color: var(--text);
}
.card-label,
.section-label {
  font-size: 0.72rem;
  letter-spacing: 0.01em;
  color: var(--text-muted);
  font-weight: 500;
  margin-bottom: 0.35rem;
}
.card-sub {
  font-size: 0.78rem;
  color: var(--text-muted);
  margin-top: 0.3rem;
}

.quick-weighin-row {
  display: flex;
  gap: 0.5rem;
  align-items: center;
}
.quick-weighin-row input {
  flex: 1;
  padding: 0.55rem 0.7rem;
  border: 1px solid var(--card-border);
  border-radius: 0.6rem;
  font-size: 0.95rem;
  background: color-mix(in srgb, var(--text-muted) 5%, var(--card-bg));
  color: var(--text);
  font-family: inherit;
}
.quick-weighin-row .btn-save {
  flex-shrink: 0;
}

/* Entrance animation — staggered */
@keyframes card-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}
.card:nth-child(2) { animation-delay: 0.04s; }
.card:nth-child(3) { animation-delay: 0.08s; }
.card:nth-child(4) { animation-delay: 0.12s; }
.card:nth-child(5) { animation-delay: 0.16s; }

/* Progress bar with smooth fill */
.bar {
  height: 5px;
  background: color-mix(in srgb, var(--text-muted) 18%, transparent);
  border-radius: 9999px;
  overflow: hidden;
  margin-top: 0.7rem;
}
.bar > span {
  display: block;
  height: 100%;
  width: 0%;
  background: linear-gradient(90deg, #0ea5e9, var(--accent));
  border-radius: 9999px;
  transition: width 0.9s cubic-bezier(0.16, 1, 0.3, 1);
}
.bar.good > span { background: linear-gradient(90deg, #10b981, #059669); }
.bar.warn > span { background: linear-gradient(90deg, #f59e0b, #d97706); }
.bar.bad  > span { background: linear-gradient(90deg, #ef4444, #dc2626); }

/* Meal entries */
.meal {
  background: color-mix(in srgb, #f59e0b 8%, var(--card-bg));
  border-left: 3px solid #f59e0b;
  padding: 0.75rem 0.95rem;
  border-radius: 0.7rem;
  margin-bottom: 0.55rem;
  animation: card-in 0.36s cubic-bezier(0.16, 1, 0.3, 1) both;
}
.meal-meta { font-size: 0.7rem; color: #b45309; font-weight: 500; margin-bottom: 0.25rem; }
.meal-extra { background: color-mix(in srgb, #ef4444 8%, var(--card-bg)); border-left-color: #ef4444; }
.meal-extra .meal-meta { color: #b91c1c; }

@media (prefers-color-scheme: dark) {
  .meal { background: color-mix(in srgb, #f59e0b 12%, var(--card-bg)); }
  .meal-meta { color: #fbbf24; }
  .meal-extra { background: color-mix(in srgb, #ef4444 15%, var(--card-bg)); }
  .meal-extra .meal-meta { color: #fca5a5; }
}

/* Lesson card */
.lesson {
  background: var(--card-bg);
  border: 1px solid var(--card-border);
  border-radius: 0.75rem;
  padding: 0.85rem 1rem;
  margin-bottom: 0.5rem;
  display: flex;
  align-items: center;
  gap: 0.7rem;
}

/* Curriculum HTML rendering */
.prose-mobile { color: var(--text); line-height: 1.65; font-size: 1.02rem; }
.prose-mobile p { margin-bottom: 0.85rem; }
.prose-mobile strong { color: var(--text); font-weight: 600; }
.prose-mobile ul { margin: 0.5rem 0 0.9rem 1.25rem; list-style: disc; }
.prose-mobile li { margin-bottom: 0.4rem; line-height: 1.6; }

/* Empty state */
.empty {
  text-align: center;
  padding: 3rem 1rem;
  color: var(--text-soft);
  font-size: 0.95rem;
}
.empty::before {
  content: "·";
  display: block;
  font-size: 3rem;
  opacity: 0.3;
  margin-bottom: 0.5rem;
}

/* Floating voice button */
#voice-btn {
  background: var(--text);
  color: var(--bg);
  box-shadow: 0 10px 30px rgba(15, 23, 42, 0.35), 0 4px 12px rgba(15, 23, 42, 0.2);
  transition: transform 0.18s cubic-bezier(0.16, 1, 0.3, 1), box-shadow 0.18s ease;
  /* sit above the fixed bottom tab bar instead of overlapping it */
  bottom: calc(4.75rem + env(safe-area-inset-bottom));
}
#voice-btn:active { transform: scale(0.92); }
#voice-btn.chat-suppressed { display: none; }
@media (prefers-color-scheme: dark) {
  #voice-btn { background: var(--accent); color: white; }
}

/* Pull-to-refresh visual cue (subtle) */
body { overscroll-behavior-y: contain; }

/* Smooth scrolling */
html { scroll-behavior: smooth; }

/* Heading typography refinement */
h2.text-xl { font-size: 1.3rem; font-weight: 700; letter-spacing: -0.02em; }

/* Streak chips */
.streak-row {
  display: flex;
  gap: 0.5rem;
  margin: 0 0 1rem;
  flex-wrap: wrap;
}
.streak-chip {
  display: flex;
  align-items: center;
  gap: 0.3rem;
  background: var(--card-bg);
  border: 1px solid var(--card-border);
  border-radius: 9999px;
  padding: 0.3rem 0.7rem;
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--text-muted);
  animation: card-in 0.42s cubic-bezier(0.16, 1, 0.3, 1) both;
}
.streak-chip .streak-icon { font-size: 0.85rem; }
.streak-chip .streak-count { color: var(--text); }
.streak-chip.milestone-pulse {
  animation: streak-pulse 0.55s cubic-bezier(0.16, 1, 0.3, 1);
}
@keyframes streak-pulse {
  0%   { transform: scale(1);    box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 55%, transparent); }
  40%  { transform: scale(1.12); box-shadow: 0 0 0 6px color-mix(in srgb, var(--accent) 25%, transparent); }
  100% { transform: scale(1);    box-shadow: 0 0 0 0 transparent; }
}
@media (prefers-reduced-motion: reduce) {
  .streak-chip.milestone-pulse { animation: none; }
}

/* Chart cards (Chart.js canvases) */
.chart-toggle {
  display: flex;
  gap: 0.4rem;
  margin: 0.4rem 0 0.7rem;
}
.chart-toggle button {
  padding: 0.25rem 0.7rem;
  border-radius: 9999px;
  font-size: 0.72rem;
  font-weight: 600;
  background: transparent;
  border: 1px solid var(--card-border);
  color: var(--text-muted);
  transition: background 0.18s ease, color 0.18s ease;
}
.chart-toggle button.active {
  background: var(--accent);
  color: white;
  border-color: var(--accent);
}
.chart-legend {
  display: flex;
  gap: 0.9rem;
  font-size: 0.7rem;
  color: var(--text-muted);
  margin-bottom: 0.6rem;
}
.chart-dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 2px;
  margin-right: 4px;
  vertical-align: middle;
}
.chart-wrap { position: relative; }

/* Daily coach narrative hero card (Today tab) */
.narrative-text {
  font-size: 0.95rem;
  line-height: 1.55;
  margin-top: 0.5rem;
}
.narrative-refresh-btn {
  background: none;
  border: none;
  font-size: 1.05rem;
  color: var(--text-muted);
  cursor: pointer;
  padding: 0.2rem;
  min-width: 32px;
  min-height: 32px;
  flex-shrink: 0;
  transition: transform 0.4s cubic-bezier(0.16, 1, 0.3, 1);
}
.narrative-refresh-btn:active { transform: rotate(180deg); }
@media (prefers-reduced-motion: reduce) {
  .narrative-refresh-btn:active { transform: none; }
}

/* ═══════════════════════════════════════════════════════════════
   TAILWIND OVERRIDES for dark mode
   Tailwind CDN injects utility classes that don't auto-adapt.
   These overrides ensure readable contrast in both modes.
   ═══════════════════════════════════════════════════════════════ */

@media (prefers-color-scheme: dark) {
  /* Text colors — invert dark-on-light to light-on-dark */
  .text-slate-900,
  .text-slate-800,
  .text-slate-700,
  .text-gray-900,
  .text-gray-800,
  .text-gray-700,
  .text-black { color: #f1f5f9 !important; }

  .text-slate-600,
  .text-gray-600 { color: #cbd5e1 !important; }

  .text-slate-500,
  .text-gray-500 { color: #94a3b8 !important; }

  .text-slate-400,
  .text-gray-400 { color: #94a3b8 !important; }

  .text-slate-300,
  .text-gray-300 { color: #64748b !important; }

  /* Backgrounds — light → dark equivalents */
  .bg-white,
  .bg-slate-50,
  .bg-slate-100,
  .bg-gray-50,
  .bg-gray-100 { background-color: var(--card-bg) !important; }

  /* Tinted backgrounds — keep semantic color but dim */
  .bg-blue-50 { background-color: rgba(99, 102, 241, 0.14) !important; }
  .bg-indigo-50 { background-color: rgba(99, 102, 241, 0.14) !important; }
  .bg-amber-50, .bg-yellow-50 { background-color: rgba(245, 158, 11, 0.14) !important; }
  .bg-red-50 { background-color: rgba(239, 68, 68, 0.14) !important; }
  .bg-emerald-50, .bg-green-50 { background-color: rgba(16, 185, 129, 0.14) !important; }
  .bg-purple-50, .bg-violet-50 { background-color: rgba(168, 85, 247, 0.14) !important; }

  /* Borders */
  .border-slate-200,
  .border-slate-300,
  .border-gray-200,
  .border-gray-300 { border-color: rgba(255, 255, 255, 0.08) !important; }
  .border-red-200 { border-color: rgba(239, 68, 68, 0.25) !important; }

  /* Body fallback (in case Tailwind body classes get re-injected) */
  body { background: var(--bg) !important; color: var(--text) !important; }
}

/* In LIGHT mode, the original Tailwind classes work fine — nothing to override. */

/* ═══════════════════════════════════════════════════════════════
   CHAT TAB
   ═══════════════════════════════════════════════════════════════ */

.chat-container {
  display: flex;
  flex-direction: column;
  /* dvh tracks the *visible* viewport as the iOS URL bar collapses; plain vh
     counts the area behind it, which made this taller than the screen and let
     the chat view become body-scrollable (and the header drift). */
  height: calc(100dvh - 200px);
  margin: 0 -1rem;
  padding: 0 1rem;
}

.chat-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding-bottom: 0.4rem;
}

.chat-clear-btn {
  background: none;
  border: none;
  font-size: 0.8rem;
  color: var(--text-muted);
  cursor: pointer;
  padding: 0.3rem 0.6rem;
  border-radius: 6px;
}
.chat-clear-btn:active { opacity: 0.6; }
.chat-clear-btn.confirm-armed { color: white; background: var(--bad); }

.chat-messages {
  flex: 1;
  overflow-y: auto;
  padding-bottom: 1rem;
  scroll-behavior: smooth;
}

.chat-msg {
  margin-bottom: 0.7rem;
  display: flex;
  flex-direction: column;
  animation: card-in 0.32s cubic-bezier(0.16, 1, 0.3, 1) both;
}
.chat-msg.user { align-items: flex-end; }
.chat-msg.assistant { align-items: flex-start; }

.chat-edit-btn {
  margin-top: 0.3rem;
  margin-left: 0.3rem;
  font-size: 0.72rem;
  color: var(--text-soft);
  background: none;
  border: none;
  padding: 0.15rem 0.3rem;
  cursor: pointer;
}
.chat-edit-btn:active { opacity: 0.6; }

#chat-input.correcting {
  border-color: #f59e0b;
  background: rgba(245, 158, 11, 0.08);
}

.chat-bubble {
  max-width: 82%;
  padding: 0.65rem 0.9rem;
  border-radius: 1.1rem;
  font-size: 0.95rem;
  line-height: 1.5;
  word-wrap: break-word;
}
.chat-table {
  border-collapse: collapse;
  font-size: 0.85rem;
  margin: 0.35rem 0;
  width: 100%;
}
.chat-table th, .chat-table td {
  border: 1px solid var(--card-border);
  padding: 0.3rem 0.55rem;
  text-align: left;
  white-space: normal;
}
.chat-table thead { background: var(--surface-2, var(--card-bg)); font-weight: 600; }
.chat-table tr:nth-child(even) td { background: color-mix(in srgb, var(--card-bg) 85%, var(--accent) 15%); }
.chat-h { font-weight: 700; font-size: 0.9rem; margin: 0.45rem 0 0.1rem; }
.chat-hr { border: none; border-top: 1px solid var(--card-border); margin: 0.4rem 0; }
.chat-ul { margin: 0.2rem 0 0.2rem 1.1rem; padding: 0; list-style-type: disc; }
.chat-ul li { margin-bottom: 0.15rem; }
.chat-msg.user .chat-bubble {
  background: linear-gradient(135deg, #0ea5e9, var(--accent));
  color: white;
  border-bottom-right-radius: 0.3rem;
}
.chat-msg.assistant .chat-bubble {
  background: var(--card-bg);
  border: 1px solid var(--card-border);
  color: var(--text);
  border-bottom-left-radius: 0.3rem;
}
.chat-msg.assistant.conversation .chat-bubble {
  border-left: 3px solid var(--accent);
}
.chat-bubble strong { font-weight: 600; }
.chat-bubble em { font-style: italic; opacity: 0.85; }
.chat-bubble-followup { margin-top: 0.5rem; }

.chat-confirm-row {
  display: flex;
  gap: 0.5rem;
  margin-top: 0.5rem;
}
.chat-confirm-yes, .chat-confirm-no {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.35rem;
  min-height: 44px;
  padding: 0 1rem;
  border-radius: 0.7rem;
  font-size: 0.88rem;
  font-weight: 600;
  cursor: pointer;
  transition: transform 0.15s ease, opacity 0.15s ease;
}
.chat-confirm-yes:active, .chat-confirm-no:active { transform: scale(0.96); opacity: 0.85; }
.chat-confirm-yes {
  background: var(--accent);
  color: white;
  border: none;
}
.chat-confirm-no {
  background: transparent;
  color: var(--text);
  border: 1px solid var(--card-border);
}

/* V17 (bug #11): Retry on a failed-send bubble */
.chat-retry-row { margin-top: 0.5rem; }
.chat-retry-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.35rem;
  min-height: 44px;
  padding: 0 1rem;
  border-radius: 0.7rem;
  font-size: 0.88rem;
  font-weight: 600;
  cursor: pointer;
  background: transparent;
  color: var(--text);
  border: 1px solid var(--card-border);
  transition: transform 0.15s ease, opacity 0.15s ease;
}
.chat-retry-btn:active { transform: scale(0.96); opacity: 0.85; }
/* V18: shown instead of the button when the retry stash no longer has the
   payload (a real page reload happened since the failure) */
.chat-retry-expired { font-size: 0.85rem; color: var(--text-secondary, #888); }

.chat-input-bar {
  display: flex;
  gap: 0.5rem;
  align-items: flex-end;
  padding: 0.7rem 0.4rem;
  background: var(--card-bg);
  border-top: 1px solid var(--card-border);
  position: sticky;
  bottom: 0;
  margin-top: auto;
}

#chat-input {
  flex: 1;
  border: 1px solid var(--card-border);
  border-radius: 1.2rem;
  padding: 0.65rem 0.95rem;
  font-size: 0.95rem;
  background: var(--bg);
  color: var(--text);
  resize: none;
  max-height: 120px;
  font-family: inherit;
  line-height: 1.4;
}
#chat-input:focus {
  outline: none;
  border-color: var(--accent);
}

.chat-btn {
  flex-shrink: 0;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: none;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: transform 0.15s ease, background 0.18s ease;
  font-size: 1.1rem;
}
.chat-btn:active { transform: scale(0.9); }
.chat-btn.send {
  background: var(--accent);
  color: white;
}
.chat-btn.mic, .chat-btn.photo {
  background: var(--card-bg);
  border: 1px solid var(--card-border);
  color: var(--text);
}
.chat-btn.mic.recording {
  background: #ef4444;
  color: white;
  animation: pulse 1.2s infinite;
}
@keyframes pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(239, 68, 68, 0.5); }
  50% { box-shadow: 0 0 0 10px rgba(239, 68, 68, 0); }
}

.chat-typing {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.65rem 0.9rem;
  background: var(--card-bg);
  border: 1px solid var(--card-border);
  border-radius: 1.1rem;
  border-bottom-left-radius: 0.3rem;
  max-width: 60px;
}
.chat-typing span {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--text-soft);
  animation: typing 1.4s infinite;
}
.chat-typing span:nth-child(2) { animation-delay: 0.2s; }
.chat-typing span:nth-child(3) { animation-delay: 0.4s; }
@keyframes typing {
  0%, 60%, 100% { opacity: 0.3; transform: translateY(0); }
  30% { opacity: 1; transform: translateY(-4px); }
}

.chat-typing-note {
  padding: 0.65rem 0.9rem;
  background: var(--card-bg);
  border: 1px solid var(--card-border);
  border-radius: 1.1rem;
  border-bottom-left-radius: 0.3rem;
  font-size: 0.82rem;
  color: var(--text-muted);
  font-style: italic;
  max-width: max-content;
}

.chat-quick-actions {
  display: flex;
  gap: 0.4rem;
  padding: 0.5rem 0.2rem 0.7rem;
  overflow-x: auto;
}
.chat-quick-actions button {
  flex-shrink: 0;
  padding: 0.45rem 0.9rem;
  border-radius: 9999px;
  font-size: 0.82rem;
  font-weight: 500;
  background: var(--card-bg);
  color: var(--text);
  border: 1px solid var(--card-border);
  cursor: pointer;
  white-space: nowrap;
}
.chat-quick-actions button:active { transform: scale(0.96); }

.chat-empty {
  text-align: center;
  padding: 3rem 1rem;
  color: var(--text-soft);
}
.chat-empty h3 { font-size: 1.05rem; font-weight: 600; color: var(--text); margin-bottom: 0.5rem; }

/* Loading shimmer */
.shimmer {
  background: linear-gradient(90deg,
    color-mix(in srgb, var(--text-muted) 8%, transparent),
    color-mix(in srgb, var(--text-muted) 18%, transparent),
    color-mix(in srgb, var(--text-muted) 8%, transparent));
  background-size: 200% 100%;
  animation: shimmer 1.4s infinite;
  border-radius: 0.5rem;
}
@keyframes shimmer {
  0%   { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}

/* ---------- direct edit/delete: bottom-sheet modal ---------- */

.tappable-row { cursor: pointer; transition: background 0.15s ease; }
.tappable-row:active { background: color-mix(in srgb, var(--accent) 8%, var(--card-bg)); }

.modal-backdrop {
  position: fixed; inset: 0;
  background: rgba(15, 23, 42, 0.45);
  z-index: 40;
  opacity: 0;
  transition: opacity 0.2s ease;
}
.modal-backdrop.hidden { display: none; }
.modal-backdrop.show { opacity: 1; }

.bottom-sheet {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  background: var(--card-bg);
  border-radius: 1.25rem 1.25rem 0 0;
  padding: 0.9rem 1.25rem calc(1.5rem + env(safe-area-inset-bottom));
  z-index: 41;
  max-height: 80vh;
  overflow-y: auto;
  transform: translateY(100%);
  transition: transform 0.2s cubic-bezier(0.16, 1, 0.3, 1);
  box-shadow: 0 -4px 24px rgba(15, 23, 42, 0.15);
}
.bottom-sheet.hidden { display: none; }
.bottom-sheet.show { transform: translateY(0); }

.bottom-sheet-handle {
  width: 36px; height: 4px;
  background: var(--card-border);
  background-color: color-mix(in srgb, var(--text-muted) 35%, transparent);
  border-radius: 2px;
  margin: 0 auto 1rem;
}

.edit-field { margin-bottom: 0.85rem; }
.edit-field label {
  display: block;
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--text-muted);
  margin-bottom: 0.3rem;
}
.edit-field input,
.edit-field textarea,
.edit-field select {
  width: 100%;
  padding: 0.55rem 0.7rem;
  border: 1px solid var(--card-border);
  border-radius: 0.6rem;
  font-size: 0.95rem;
  background: color-mix(in srgb, var(--text-muted) 5%, var(--card-bg));
  color: var(--text);
  font-family: inherit;
}
.edit-field textarea { resize: vertical; min-height: 3rem; }
.edit-field select { appearance: none; }

.edit-modal-actions {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-top: 0.3rem;
}
.edit-modal-actions-right { display: flex; gap: 0.5rem; }

.btn-delete {
  color: var(--bad);
  background: none;
  border: none;
  padding: 0.5rem 0.7rem;
  font-weight: 500;
  font-size: 0.9rem;
  border-radius: 0.5rem;
  transition: background 0.15s ease, color 0.15s ease;
}
.btn-delete.confirm-armed { background: var(--bad); color: white; }

.btn-cancel {
  color: var(--text-muted);
  background: none;
  border: none;
  padding: 0.5rem 0.9rem;
  font-size: 0.9rem;
}

.btn-save {
  background: var(--accent);
  color: white;
  border: none;
  border-radius: 0.6rem;
  padding: 0.5rem 1.1rem;
  font-weight: 600;
  font-size: 0.9rem;
}
.btn-save:active, .btn-cancel:active, .btn-delete:active { opacity: 0.7; }
.btn-save:disabled { opacity: 0.5; pointer-events: none; }

/* Photo meal logging (V9-J) */
.photo-preview-actions {
  display: flex;
  justify-content: flex-end;
  gap: 0.5rem;
  margin-top: 0.3rem;
}
.photo-preview-img {
  width: 100%;
  max-height: 220px;
  object-fit: cover;
  border-radius: 0.75rem;
  margin-bottom: 0.85rem;
}
.btn-photo-log {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  background: var(--card-bg);
  border: 1px solid var(--card-border);
  color: var(--text);
  border-radius: 0.7rem;
  padding: 0.55rem 0.9rem;
  font-size: 0.88rem;
  font-weight: 500;
}
.btn-photo-log:active { opacity: 0.7; }

/* Generic tappable list row (weight / movement) — neutral, not food-themed */
.list-row {
  background: var(--card-bg);
  border: 1px solid var(--card-border);
  border-left: 3px solid var(--accent);
  padding: 0.75rem 0.95rem;
  border-radius: 0.7rem;
  margin-bottom: 0.55rem;
  animation: card-in 0.36s cubic-bezier(0.16, 1, 0.3, 1) both;
}
.list-row-meta { font-size: 0.7rem; color: var(--text-muted); font-weight: 500; margin-bottom: 0.25rem; }

/* ═══════════════════════════════════════════════════════════════
   NAVIGATION & FEEL — swipe transitions, login gate, pull-to-refresh
   ═══════════════════════════════════════════════════════════════ */

/* 6a — swipe between tabs */
@keyframes tab-enter-next { from { transform: translateX(20px); opacity: 0; } to { transform: translateX(0); opacity: 1; } }
@keyframes tab-enter-prev { from { transform: translateX(-20px); opacity: 0; } to { transform: translateX(0); opacity: 1; } }
.tab-enter-next { animation: tab-enter-next 180ms cubic-bezier(0.16, 1, 0.3, 1) both; }
.tab-enter-prev { animation: tab-enter-prev 180ms cubic-bezier(0.16, 1, 0.3, 1) both; }
@media (prefers-reduced-motion: reduce) {
  .tab-enter-next, .tab-enter-prev { animation: none; }
}

/* 6b — full-screen login gate */
.login-view {
  position: fixed;
  inset: 0;
  z-index: 999;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--bg);
  padding: 1.5rem;
}
.login-view.hidden { display: none; }
.login-card {
  width: 100%;
  max-width: 320px;
  text-align: center;
  animation: card-in 0.42s cubic-bezier(0.16, 1, 0.3, 1) both;
}
.login-logo {
  font-size: 1.6rem;
  font-weight: 800;
  letter-spacing: -0.02em;
  color: var(--text);
  margin-bottom: 0.4rem;
}
.login-sub {
  font-size: 0.88rem;
  color: var(--text-muted);
  margin-bottom: 1.5rem;
}
.login-input {
  width: 100%;
  padding: 0.75rem 1rem;
  border: 1px solid var(--card-border);
  border-radius: 0.8rem;
  font-size: 1rem;
  background: var(--card-bg);
  color: var(--text);
  text-align: center;
  margin-bottom: 0.8rem;
}
.login-input:focus { outline: none; border-color: var(--accent); }
.login-error {
  color: var(--bad);
  font-size: 0.82rem;
  margin-bottom: 0.8rem;
}
.login-submit {
  width: 100%;
  background: var(--accent);
  color: white;
  border: none;
  border-radius: 0.8rem;
  padding: 0.75rem 1rem;
  font-weight: 600;
  font-size: 0.95rem;
}
.login-submit:active { opacity: 0.8; }
.login-passkey-btn {
  width: 100%;
  background: var(--accent);
  color: white;
  border: none;
  border-radius: 0.8rem;
  padding: 0.75rem 1rem;
  font-weight: 600;
  font-size: 0.95rem;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  margin-bottom: 0.5rem;
}
.login-passkey-btn:active { opacity: 0.8; }
.login-passkey-divider {
  text-align: center;
  color: var(--text-muted);
  font-size: 0.82rem;
  margin: 0.25rem 0 0.5rem;
}

/* 6c — pull-to-refresh */
.ptr-indicator {
  position: fixed;
  top: calc(env(safe-area-inset-top) + 8px);
  left: 50%;
  transform: translateX(-50%) scale(0.8);
  z-index: 30;
  opacity: 0;
  transition: opacity 0.15s ease, transform 0.15s ease;
}
.ptr-indicator.hidden { display: none; }
.ptr-indicator.show { opacity: 1; transform: translateX(-50%) scale(1); }
.ptr-spinner {
  width: 22px;
  height: 22px;
  border: 2.5px solid color-mix(in srgb, var(--text-muted) 30%, transparent);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: ptr-spin 0.7s linear infinite;
}
@keyframes ptr-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .ptr-spinner { animation: none; }
}

/* ═══════════════════════════════════════════════════════════════
   INSIGHTS FEED + WEB PUSH (Epic D)
   ═══════════════════════════════════════════════════════════════ */

.tab-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  margin-left: 0.3rem;
  border-radius: 9999px;
  background: var(--bad);
  color: white;
  font-size: 0.62rem;
  font-weight: 700;
  vertical-align: 2px;
}
.tab-badge.hidden { display: none; }

.insight-card { position: relative; border-left: 3px solid var(--accent); }
.insight-card.insight-warn { border-left-color: var(--warn); }
.insight-card.insight-bad { border-left-color: var(--bad); }
.insight-card.unread { background: color-mix(in srgb, var(--accent) 6%, var(--card-bg)); }
.insight-unread-dot {
  position: absolute;
  top: 1.1rem;
  right: 1.1rem;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--accent);
  flex-shrink: 0;
}

/* ═══════════════════════════════════════════════════════════════
   QUICK ADD — recents/favorites + corrections that stick (Epic F)
   ═══════════════════════════════════════════════════════════════ */

.meal-star {
  float: right;
  background: none;
  border: none;
  font-size: 1.15rem;
  line-height: 1;
  padding: 0.1rem 0.2rem;
  margin: -0.1rem -0.2rem 0 0.4rem;
  color: var(--text-soft);
  cursor: pointer;
  min-width: 44px;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.meal-star.is-fav { color: var(--warn); }
.meal-star:active { transform: scale(0.85); }

.save-prompt {
  position: fixed;
  bottom: calc(5.5rem + env(safe-area-inset-bottom));
  left: 50%;
  transform: translateX(-50%) translateY(8px);
  background: var(--card-bg);
  border: 1px solid var(--card-border);
  color: var(--text);
  padding: 0.6rem 0.7rem 0.6rem 1rem;
  border-radius: 9999px;
  font-size: 0.85rem;
  font-weight: 500;
  box-shadow: 0 6px 20px rgba(15, 23, 42, 0.25);
  z-index: 50;
  display: flex;
  align-items: center;
  gap: 0.6rem;
  max-width: 92vw;
  opacity: 0;
  transition: opacity 0.2s cubic-bezier(0.16, 1, 0.3, 1), transform 0.2s cubic-bezier(0.16, 1, 0.3, 1);
}
.save-prompt.hidden { display: none; }
.save-prompt.show { opacity: 1; transform: translateX(-50%) translateY(0); }
.save-prompt-actions { display: flex; gap: 0.4rem; flex-shrink: 0; }
.save-prompt-actions button {
  border: none;
  border-radius: 9999px;
  padding: 0.35rem 0.7rem;
  font-size: 0.8rem;
  font-weight: 600;
  cursor: pointer;
}
#save-prompt-confirm { background: var(--accent); color: white; }
#save-prompt-dismiss { background: transparent; color: var(--text-muted); }
@media (prefers-reduced-motion: reduce) {
  .save-prompt { transition: opacity 0.12s linear; }
}

/* ═══════════════════════════════════════════════════════════════
   SETTINGS TAB
   ═══════════════════════════════════════════════════════════════ */

.settings-locked-badge {
  display: inline-block;
  margin-top: 0.5rem;
  font-size: 0.7rem;
  font-weight: 600;
  color: var(--text-muted);
  background: color-mix(in srgb, var(--text-muted) 12%, transparent);
  padding: 0.2rem 0.55rem;
  border-radius: 9999px;
}

.toast {
  position: fixed;
  bottom: calc(5.5rem + env(safe-area-inset-bottom));
  left: 50%;
  transform: translateX(-50%) translateY(8px);
  background: var(--text);
  color: var(--bg);
  padding: 0.6rem 1.1rem;
  border-radius: 9999px;
  font-size: 0.85rem;
  font-weight: 500;
  box-shadow: 0 6px 20px rgba(15, 23, 42, 0.25);
  z-index: 50;
  opacity: 0;
  transition: opacity 0.2s cubic-bezier(0.16, 1, 0.3, 1), transform 0.2s cubic-bezier(0.16, 1, 0.3, 1);
}
.toast.hidden { display: none; }
.toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }
/* severity variants */
.toast.toast-bad { background: var(--bad); color: white; }
.toast.toast-good { background: var(--good); color: white; }
.toast.toast-warn { background: var(--warn); color: var(--text); }
/* action button (undo, retry) */
.toast-msg { flex: 1; }
.toast-action {
  background: rgba(255,255,255,0.25);
  border: none;
  border-radius: 6px;
  color: inherit;
  font-size: 0.82rem;
  font-weight: 600;
  padding: 0.25rem 0.6rem;
  cursor: pointer;
  flex-shrink: 0;
  white-space: nowrap;
}
.toast-warn .toast-action { background: rgba(0,0,0,0.12); }
/* exercise-mode exit confirm */
.exercise-mode-exit-confirm {
  position: absolute;
  inset: 0;
  background: rgba(11,18,32,0.88);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1.25rem;
  z-index: 10;
  padding: 2rem;
}
.exercise-mode-exit-confirm p {
  color: var(--text);
  font-size: 1rem;
  font-weight: 500;
  text-align: center;
  margin: 0;
}
.exercise-mode-exit-actions {
  display: flex;
  gap: 0.75rem;
  width: 100%;
  max-width: 280px;
}
.exercise-mode-exit-actions button { flex: 1; }
@media (prefers-reduced-motion: reduce) {
  .toast { transition: opacity 0.12s linear; }
  .toast.show { transform: translateX(-50%) translateY(0); }
}


/* ═══════════════════════════════════════════════════════════════
   DESIGN SYSTEM COMPONENTS (v7 Epic D0)
   CSS for the shared template-literal helpers in app.js: statusChip,
   focusCard, ringStat, sparkline, macroBar, listRow. Status color
   always comes from --good/--warn/--bad/--info (+ -bg pairs) above —
   never a hardcoded hex.
   ═══════════════════════════════════════════════════════════════ */

.status-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  font-size: 0.78rem;
  font-weight: 500;
  padding: 0.25rem 0.65rem;
  border-radius: 9999px;
  line-height: 1.3;
}
.status-chip i { font-size: 0.95em; }
.status-chip-good    { color: var(--good); background: var(--good-bg); }
.status-chip-warn    { color: var(--warn); background: var(--warn-bg); }
.status-chip-bad     { color: var(--bad);  background: var(--bad-bg); }
.status-chip-info    { color: var(--info); background: var(--info-bg); }
.status-chip-neutral { color: var(--text-muted); background: color-mix(in srgb, var(--text-muted) 12%, transparent); }

.focus-card {
  background: var(--card-bg);
  border: 1px solid var(--card-border);
  border-left: 3px solid var(--info);
  border-radius: 1rem;
  padding: 1.1rem 1.2rem;
  box-shadow: var(--card-shadow);
  animation: card-in 0.42s cubic-bezier(0.16, 1, 0.3, 1) both;
}
.focus-card-good    { border-left-color: var(--good); }
.focus-card-warn    { border-left-color: var(--warn); }
.focus-card-bad     { border-left-color: var(--bad); }
.focus-card-info    { border-left-color: var(--info); }
.focus-card-neutral { border-left-color: var(--text-soft); }
.focus-card-label { font-size: 0.72rem; font-weight: 500; color: var(--text-muted); margin-bottom: 0.4rem; }
.focus-card-body { font-size: 0.95rem; line-height: 1.55; color: var(--text); }
.focus-card-action { margin-top: 0.65rem; }

.ring-stat { display: inline-flex; flex-direction: column; align-items: center; }
.ring-stat-circle { position: relative; display: inline-flex; }
.ring-stat-circle svg { display: block; }
.ring-track { stroke: color-mix(in srgb, var(--text-muted) 18%, transparent); }
.ring-stat-center {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}
.ring-stat-value { font-size: 1.1rem; font-weight: 700; color: var(--text); line-height: 1; }
.ring-stat-unit { font-size: 0.62rem; color: var(--text-muted); margin-top: 0.1rem; }
.ring-stat-label { font-size: 0.78rem; color: var(--text-muted); margin-top: 0.5rem; font-weight: 500; }

.sparkline { display: block; overflow: visible; }

.macro-bar { margin-bottom: 0.85rem; }
.macro-bar-row { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 0.3rem; }
.macro-bar-label { font-size: 0.85rem; font-weight: 500; color: var(--text); }
.macro-bar-value { font-size: 0.8rem; color: var(--text-muted); }
.macro-bar-sub { font-size: 0.72rem; color: var(--text-muted); margin-top: 0.3rem; }

.list-tile {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  background: var(--card-bg);
  border: 1px solid var(--card-border);
  border-radius: 0.85rem;
  padding: 0.75rem 0.95rem;
  margin-bottom: 0.5rem;
  animation: card-in 0.36s cubic-bezier(0.16, 1, 0.3, 1) both;
}
.list-tile-icon {
  flex-shrink: 0;
  width: 2.1rem;
  height: 2.1rem;
  border-radius: 0.6rem;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.05rem;
  color: var(--accent);
  background: color-mix(in srgb, var(--accent) 12%, var(--card-bg));
}
.list-tile-main { flex: 1; min-width: 0; }
.list-tile-title { font-size: 0.92rem; color: var(--text); font-weight: 500; }
.list-tile-sub { font-size: 0.76rem; color: var(--text-muted); margin-top: 0.15rem; }
.list-tile-trailing { flex-shrink: 0; text-align: right; font-size: 0.85rem; color: var(--text-muted); }
.list-tile-chevron { flex-shrink: 0; color: var(--text-soft); font-size: 0.9rem; }

/* ═══════════════════════════════════════════════════════════════
   TODAY REDESIGN (v7 Epic D2)
   ═══════════════════════════════════════════════════════════════ */

button.status-chip {
  border: none;
  font-family: inherit;
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
}

.today-slim-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 0.5rem;
}
.today-slim-header-text {
  font-size: 0.82rem;
  color: var(--text-muted);
  font-style: italic;
}

.narrative-text.is-collapsed {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.ring-stat-row {
  display: flex;
  justify-content: space-around;
  align-items: flex-start;
  background: var(--card-bg);
  border: 1px solid var(--card-border);
  border-radius: 1rem;
  padding: 1.1rem 0.5rem;
  box-shadow: var(--card-shadow);
  animation: card-in 0.42s cubic-bezier(0.16, 1, 0.3, 1) both;
}

.lab-strip {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0.5rem;
}
.lab-strip-item {
  background: var(--card-bg);
  border: 1px solid var(--card-border);
  border-radius: 0.7rem;
  padding: 0.55rem 0.4rem;
  text-align: center;
  animation: card-in 0.36s cubic-bezier(0.16, 1, 0.3, 1) both;
}
.lab-strip-good { background: color-mix(in srgb, var(--good) 8%, var(--card-bg)); }
.lab-strip-warn { background: color-mix(in srgb, var(--warn) 8%, var(--card-bg)); }
.lab-strip-label { font-size: 0.62rem; color: var(--text-muted); font-weight: 500; margin-bottom: 0.25rem; }
.lab-strip-value { font-size: 0.85rem; font-weight: 700; color: var(--text); }
.lab-strip-good .lab-strip-value { color: var(--good); }
.lab-strip-warn .lab-strip-value { color: var(--warn); }

/* ═══════════════════════════════════════════════════════════════
   HEALTH REDESIGN (v7 Epic D3)
   ═══════════════════════════════════════════════════════════════ */

.health-hero-value { font-size: 2rem; font-weight: 700; color: var(--text); line-height: 1; }
.health-hero-unit { font-size: 0.85rem; font-weight: 500; color: var(--text-muted); margin-left: 0.2rem; }
.health-hero-sub { font-size: 0.8rem; color: var(--text-muted); margin-top: 0.35rem; }
.health-hero-spark { flex-shrink: 0; }

.health-row-trailing { display: flex; align-items: center; gap: 0.5rem; }
.health-row-value { font-size: 0.88rem; font-weight: 600; color: var(--text); }
.health-row-trend { display: inline-flex; font-size: 0.95rem; }
.health-row-trend-good { color: var(--good); }
.health-row-trend-warn { color: var(--warn); }
.health-row-trend-bad  { color: var(--bad); }
.lab-strip-value i { font-size: 0.75em; margin-left: 0.1rem; }

/* ═══════════════════════════════════════════════════════════════
   EATING REDESIGN (v7 Epic D4)
   ═══════════════════════════════════════════════════════════════ */

.eating-hero-kcal { line-height: 1; }
.eating-hero-value { font-size: 2rem; font-weight: 700; color: var(--text); }
.eating-hero-unit { font-size: 0.85rem; font-weight: 500; color: var(--text-muted); margin-left: 0.2rem; }
.eating-hero-sub { font-size: 0.8rem; color: var(--text-muted); margin-top: 0.35rem; }

.meal-plan-row-logged .list-tile-trailing { color: var(--good); }
.meal-plan-row-logged .list-tile-icon { color: var(--good); }

/* ═══════════════════════════════════════════════════════════════
   CHAT REDESIGN (v7 Epic D6)
   ═══════════════════════════════════════════════════════════════ */

.chat-log-card {
  max-width: 82%;
  padding: 0.65rem 0.9rem;
  border-radius: 1.1rem;
  border: 1px solid var(--card-border);
  border-left: 3px solid var(--good);
  border-bottom-left-radius: 0.3rem;
  background: var(--card-bg);
}
/* V17: a turn can now render more than one card (bug #13 -- a second write in
   the same turn used to be invisible), stack them with a small gap. */
.chat-log-card + .chat-log-card { margin-top: 0.4rem; }
/* V17 (bug #5): a delete used to render with the same green "success" look
   as a fresh log -- visually distinct so removing something doesn't read as
   adding it. */
.chat-log-card-deleted {
  border-left-color: var(--bad);
  background: color-mix(in srgb, var(--bad) 6%, var(--card-bg));
}
.chat-log-card-deleted .chat-log-card-check { color: var(--bad); }
.chat-log-card-head { display: flex; align-items: center; gap: 0.45rem; }
.chat-log-card-check { color: var(--good); font-size: 1rem; display: inline-flex; flex-shrink: 0; }
.chat-log-card-label { font-size: 0.88rem; font-weight: 600; color: var(--text); flex: 1; }
.chat-log-card-edit {
  background: none; border: none; color: var(--text-soft); font-size: 0.95rem;
  padding: 0.2rem; cursor: pointer; display: inline-flex; flex-shrink: 0;
}
.chat-log-card-edit:active { opacity: 0.6; }
.chat-log-card-items { font-size: 0.85rem; color: var(--text); margin-top: 0.4rem; }
.chat-log-card-macros { display: flex; gap: 0.4rem; flex-wrap: wrap; margin-top: 0.4rem; }
.chat-log-card-macros span {
  font-size: 0.78rem; color: var(--text-muted);
  background: color-mix(in srgb, var(--text-muted) 12%, transparent);
  padding: 0.15rem 0.55rem; border-radius: 9999px;
}

/* ═══════════════════════════════════════════════════════════════
   INSIGHTS REDESIGN (v7 Epic D7)
   ═══════════════════════════════════════════════════════════════ */

.insight-digest-row .list-tile-chevron { transition: transform 0.15s ease; }
.insight-digest-row.expanded .list-tile-chevron { transform: rotate(90deg); }
.insight-digest-row-body {
  display: none;
  margin-top: 0.35rem;
  font-size: 0.82rem;
  color: var(--text-muted);
  white-space: pre-wrap;
}
.insight-digest-row.expanded .insight-digest-row-body { display: block; }

.insight-feedback {
  display: flex; align-items: center; gap: 0.4rem;
  margin-top: 0.6rem; padding-top: 0.5rem;
  border-top: 1px solid var(--card-border);
}
.insight-feedback-label { font-size: 0.75rem; color: var(--text-muted); flex: 1; }
.insight-feedback-btn {
  background: none; border: 1px solid var(--card-border); border-radius: 6px;
  padding: 0.2rem 0.45rem; cursor: pointer; color: var(--text-muted);
  font-size: 0.8rem; display: flex; align-items: center; gap: 0.2rem;
  transition: color 0.15s, border-color 0.15s;
}
.insight-feedback-btn:hover, .insight-feedback-btn.like-btn.active { color: var(--accent); border-color: var(--accent); }
.insight-feedback-btn.dislike-btn.active { color: var(--warn); border-color: var(--warn); }

/* ═══════════════════════════════════════════════════════════════
   MOVEMENT REDESIGN (v7 Epic D8)
   ═══════════════════════════════════════════════════════════════ */

.movement-exit-criteria { margin-top: 0.5rem; display: flex; flex-direction: column; gap: 0.35rem; }
.movement-exit-criterion {
  display: flex; align-items: flex-start; gap: 0.4rem;
  font-size: 0.78rem; color: var(--text-muted);
}
.movement-exit-criterion i { font-size: 0.95em; flex-shrink: 0; margin-top: 0.1em; }
.movement-exit-criterion-met { color: var(--good); }
.movement-exit-criterion-met i { color: var(--good); }
.movement-exit-criterion-tag {
  font-size: 0.68rem; color: var(--warn); background: var(--warn-bg);
  padding: 0.05rem 0.4rem; border-radius: 9999px; margin-left: 0.3rem; white-space: nowrap;
}
.movement-stepper { display: flex; align-items: flex-start; margin-top: 0.6rem; }
.movement-step { display: flex; flex-direction: column; align-items: center; gap: 0.3rem; flex: 0 0 auto; }
.movement-step-dot {
  width: 28px; height: 28px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-size: 0.78rem; font-weight: 700;
  background: color-mix(in srgb, var(--text-muted) 12%, transparent);
  color: var(--text-muted);
}
.movement-step-label { font-size: 0.68rem; color: var(--text-muted); white-space: nowrap; }
.movement-step-connector { flex: 1 1 auto; height: 2px; margin-top: 14px; background: var(--card-border); }
.movement-step-connector.passed { background: var(--good); }
.movement-step-done .movement-step-dot { background: var(--good-bg); color: var(--good); }
.movement-step-active .movement-step-dot { background: var(--accent); color: white; }
.movement-step-active .movement-step-label { color: var(--text); font-weight: 600; }
.movement-step-upcoming .movement-step-dot { opacity: 0.6; }

.movement-ex-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 0.6rem; margin-top: 0.6rem; }
.movement-ex-card {
  background: color-mix(in srgb, var(--text-muted) 6%, transparent);
  border-radius: 0.6rem; padding: 0.55rem 0.65rem;
}
.movement-ex-name { font-size: 0.85rem; font-weight: 600; color: var(--text); }
.movement-ex-sets { font-size: 0.78rem; color: var(--text-muted); margin-top: 0.15rem; }
.movement-ex-cue { font-size: 0.72rem; color: var(--text-soft); margin-top: 0.3rem; }
.movement-ex-why { font-size: 0.7rem; color: var(--info); margin-top: 0.35rem; }
.movement-ex-progress { font-size: 0.7rem; color: var(--text-muted); font-style: italic; margin-top: 0.2rem; }
.movement-ex-load-preview { font-size: 0.78rem; font-weight: 600; color: var(--text-muted); margin-top: 0.25rem; }
.movement-ex-start-btn {
  display: block; width: 100%; margin-top: 0.7rem;
  padding: 0.75rem; border: none; border-radius: 0.7rem;
  background: var(--accent); color: white;
  font-size: 0.95rem; font-weight: 600; cursor: pointer;
}
.movement-ex-start-btn:active { opacity: 0.85; }

/* ═══════════════════════════════════════════════════════════════
   EXERCISE MODE (PLAN_V12 Part 1) — full-screen sequential logging
   ═══════════════════════════════════════════════════════════════ */

.exercise-mode-overlay {
  position: fixed; inset: 0;
  background: var(--bg);
  z-index: 60;
  display: flex; flex-direction: column;
  /* V15 batch 6: slide-up + fade on open/close (was an instant cut) */
  opacity: 0;
  transform: translateY(24px);
  transition: opacity 0.22s ease, transform 0.26s cubic-bezier(0.16, 1, 0.3, 1);
}
.exercise-mode-overlay.is-open { opacity: 1; transform: translateY(0); }
.exercise-mode-overlay.hidden { display: none; }

/* Step change: the new exercise slides in — retriggered per step by JS */
@keyframes ex-mode-step-in {
  from { opacity: 0; transform: translateX(16px); }
  to   { opacity: 1; transform: translateX(0); }
}
.exercise-mode-body.step-in { animation: ex-mode-step-in 0.2s ease-out; }
@media (prefers-reduced-motion: reduce) {
  .exercise-mode-overlay { transition: none; transform: none; }
  .exercise-mode-body.step-in { animation: none; }
}

.exercise-mode-topbar {
  display: flex; align-items: center; justify-content: space-between;
  padding: calc(0.8rem + env(safe-area-inset-top)) 1rem 0.8rem;
  border-bottom: 1px solid var(--card-border);
  flex-shrink: 0;
}
.exercise-mode-close {
  width: 40px; height: 40px; border-radius: 50%; border: none;
  background: color-mix(in srgb, var(--text-muted) 8%, transparent);
  color: var(--text); font-size: 1.1rem;
  display: flex; align-items: center; justify-content: center;
  cursor: pointer;
}
.exercise-mode-close:active { opacity: 0.7; }
.exercise-mode-progress { font-size: 0.85rem; font-weight: 600; color: var(--text-muted); }

.exercise-mode-body {
  flex: 1; overflow-y: auto;
  padding: 1.25rem 1.25rem calc(1rem + env(safe-area-inset-bottom));
}
.exercise-mode-name { font-size: 1.5rem; font-weight: 700; color: var(--text); line-height: 1.2; }
.exercise-mode-sets { font-size: 1rem; color: var(--text-muted); margin-top: 0.3rem; }
.exercise-mode-cue {
  font-size: 1.05rem; line-height: 1.5; color: var(--text);
  background: color-mix(in srgb, var(--accent) 8%, transparent);
  border-left: 3px solid var(--accent);
  border-radius: 0.5rem;
  padding: 0.85rem 1rem;
  margin-top: 1rem;
}
.exercise-mode-why { font-size: 0.85rem; color: var(--info); margin-top: 0.7rem; }
.exercise-mode-progress-note { font-size: 0.85rem; color: var(--text-muted); font-style: italic; margin-top: 0.3rem; }

.exercise-mode-demo { margin-top: 1rem; display: flex; justify-content: center; }
.exercise-mode-demo svg { width: 100%; max-width: 220px; height: auto; }

/* V16 M3: Guided mode -- opt-in pacer inside Exercise Mode */
.guided-start-btn {
  display: block; margin: 0.9rem auto 0; padding: 0.55rem 1.2rem;
  border-radius: 999px; border: 1px solid var(--accent);
  background: color-mix(in srgb, var(--accent) 10%, transparent);
  color: var(--accent); font-size: 0.85rem; font-weight: 600; cursor: pointer;
}
.guided-start-btn:active { opacity: 0.7; }

.exercise-mode-guided { margin-top: 1rem; }
.guided-panel {
  display: flex; flex-direction: column; align-items: center; gap: 0.5rem;
  padding: 1rem; border-radius: 0.9rem;
  background: color-mix(in srgb, var(--accent) 6%, transparent);
  cursor: pointer; user-select: none;
}
.guided-ring-wrap { position: relative; width: 120px; height: 120px; }
.guided-ring-wrap svg { width: 100%; height: 100%; }
.guided-ring-track { stroke: var(--card-border); fill: none; }
.guided-ring-arc { fill: none; stroke-linecap: round; transition: stroke-dashoffset 0.2s linear; }
.guided-ring-center {
  position: absolute; inset: 0; display: flex; flex-direction: column;
  align-items: center; justify-content: center;
}
.guided-ring-value { font-size: 1.7rem; font-weight: 700; color: var(--text); line-height: 1; }
.guided-ring-unit { font-size: 0.7rem; color: var(--text-muted); margin-top: 0.15rem; }
.guided-phase-label { font-size: 0.85rem; font-weight: 600; color: var(--text-muted); }
.guided-set-chip { font-size: 0.78rem; color: var(--text-muted); }
.guided-pause-hint { font-size: 0.72rem; color: var(--text-muted); opacity: 0.7; }
.guided-panel.is-paused .guided-ring-arc { stroke: var(--text-muted); }

.guided-toolbar { display: flex; justify-content: center; gap: 0.6rem; margin-top: 0.6rem; }
.guided-sound-toggle {
  width: 34px; height: 34px; border-radius: 50%; border: 1px solid var(--card-border);
  background: var(--card-bg); color: var(--text-muted); display: flex;
  align-items: center; justify-content: center; cursor: pointer; font-size: 0.9rem;
}
.guided-sound-toggle.is-on { color: var(--accent); border-color: var(--accent); }

@keyframes guided-done-pulse {
  0% { transform: scale(1); } 50% { transform: scale(1.04); } 100% { transform: scale(1); }
}
.guided-done-pulse { animation: guided-done-pulse 0.6s ease-out; }
@keyframes guided-pain-highlight {
  0%, 100% { background: transparent; } 30% { background: color-mix(in srgb, var(--accent) 14%, transparent); }
}
.guided-pain-highlight { animation: guided-pain-highlight 1.4s ease-out; border-radius: 0.6rem; }

@media (prefers-reduced-motion: reduce) {
  .guided-ring-arc { transition: none; }
  .guided-done-pulse, .guided-pain-highlight { animation: none; }
}

.exercise-mode-load-row { display: flex; gap: 0.6rem; margin-top: 1.1rem; }
.exercise-mode-load-row input {
  flex: 1; padding: 0.7rem 0.8rem; border: 1px solid var(--card-border); border-radius: 0.6rem;
  font-size: 1rem; background: var(--card-bg); color: var(--text); font-family: inherit;
}

.exercise-mode-pain { margin-top: 1.3rem; }
.exercise-mode-pain-label { font-size: 0.85rem; font-weight: 600; color: var(--text-muted); margin-bottom: 0.5rem; }
.exercise-mode-pain-row { display: flex; gap: 0.5rem; }
.exercise-mode-pain-btn {
  flex: 1; padding: 0.65rem 0.4rem; border-radius: 0.6rem;
  border: 1px solid var(--card-border); background: var(--card-bg);
  color: var(--text); font-size: 0.8rem; font-weight: 600;
  cursor: pointer; text-align: center;
}
.exercise-mode-pain-btn.active { background: var(--accent); border-color: var(--accent); color: white; }
.exercise-mode-pain-btn.active.pain-warn { background: var(--warn); border-color: var(--warn); }
.exercise-mode-pain-btn.active.pain-bad { background: var(--bad); border-color: var(--bad); }

.exercise-mode-actions {
  display: flex; gap: 0.7rem;
  padding: 0.9rem 1.25rem calc(0.9rem + env(safe-area-inset-bottom));
  border-top: 1px solid var(--card-border);
  flex-shrink: 0;
}
.exercise-mode-actions .btn-cancel, .exercise-mode-actions .btn-save { flex: 1; padding: 0.8rem; font-size: 0.95rem; }
.exercise-mode-actions .btn-cancel:disabled { opacity: 0.35; pointer-events: none; }

.movement-week-strip { display: flex; justify-content: space-between; margin-top: 0.6rem; }
.movement-week-tile { display: flex; flex-direction: column; align-items: center; gap: 0.3rem; position: relative; }
.movement-week-dow { font-size: 0.65rem; font-weight: 600; color: var(--text-muted); text-transform: uppercase; }
.movement-week-dot {
  width: 30px; height: 30px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-size: 0.78rem; font-weight: 600;
  background: color-mix(in srgb, var(--text-muted) 10%, transparent);
  color: var(--text-muted);
}
.movement-week-done .movement-week-dot { background: var(--good-bg); color: var(--good); }
.movement-week-missed .movement-week-dot { background: var(--bad-bg); color: var(--bad); }
.movement-week-today .movement-week-dot { background: var(--info-bg); color: var(--info); border: 2px solid var(--info); }
.movement-week-upcoming .movement-week-dot { opacity: 0.55; }
.movement-week-catchup {
  position: absolute; top: -2px; right: -2px;
  width: 8px; height: 8px; border-radius: 50%; background: var(--warn);
}

/* ── Exercise demo SVGs (PLAN_V12 Part 2, moved here in V15 batch 4) ────────
   Shared stick-figure classes + movement keyframes for the inline demo SVGs
   in app.js — previously duplicated inside every demo's <defs><style>. */
.ex-body { fill: color-mix(in srgb, var(--text-muted) 18%, transparent); stroke: var(--text-muted); stroke-width: 1.2; }
.ex-limb { fill: none; stroke: var(--accent); stroke-width: 2.8; stroke-linecap: round; }
/* V16 M1: the non-working/reference limb in a unilateral pattern (e.g. the
   standing leg while the other one moves) — muted so the working limb reads
   as the point of the demo. */
.ex-limb-muted { fill: none; stroke: var(--text-muted); stroke-width: 2.2; stroke-linecap: round; opacity: 0.6; }
.ex-joint { fill: var(--accent); }
.ex-joint-muted { fill: var(--text-muted); opacity: 0.6; }
.ex-ground { stroke: var(--card-border); stroke-width: 1.5; fill: none; }
.ex-pulse { fill: color-mix(in srgb, var(--accent) 20%, transparent); }
.ex-sides-chip { text-align: center; font-size: 0.72rem; color: var(--text-muted); margin-top: 0.2rem; }

/* Tempo-only patterns (motion already honest, or a hold) — single segment,
   duration driven by --ex-cycle (set per-exercise in app.js: 2s/rep for reps,
   4s breathe for holds). */
@keyframes ex-lateral { 0%,100%{transform:translateX(0)} 50%{transform:translateX(20px)} }
@keyframes ex-bound { 0%{transform:translate(0,0)} 40%{transform:translate(18px,-16px)} 70%{transform:translate(28px,0)} 100%{transform:translate(28px,0)} }
@keyframes ex-deadbug-arm { 0%,100%{transform:rotate(0deg)} 50%{transform:rotate(-50deg)} }
@keyframes ex-deadbug-leg { 0%,100%{transform:rotate(0deg)} 50%{transform:rotate(45deg)} }
@keyframes ex-walk { 0%,100%{transform:translateX(0)} 50%{transform:translateX(6px)} }
@keyframes ex-shuffle { 0%,100%{transform:translateX(-12px)} 50%{transform:translateX(12px)} }
@keyframes ex-breathe { 0%,100%{rx:22px;opacity:0.3} 50%{rx:26px;opacity:0.6} }
@keyframes ex-iso-pulse { 0%,100%{r:5px;opacity:1} 50%{r:8px;opacity:0.5} }

/* Jointed rigs (V16 M1) — four-phase concentric/hold/eccentric/pause tempo
   (0% -> 30% concentric -> 50% hold -> 90% eccentric -> 100% pause), matching
   what the PT actually prescribes instead of a symmetric sine bounce. 0%/100%
   sit at a representative MID pose (not full rest) -- app.js sets the same
   value as a plain `transform` alongside `animation`, so prefers-reduced-motion
   (which disables the animation but not the static transform) still shows
   that mid pose instead of freezing at an uninformative dead-rest position. */
@keyframes ex-bridge          { 0%,100%{transform:translateY(-7px)}  30%,50%{transform:translateY(-14px)} 90%{transform:translateY(-7px)} }
@keyframes ex-sd-thigh        { 0%,100%{transform:rotate(8deg)}      30%,50%{transform:rotate(32deg)}     90%{transform:rotate(8deg)} }
@keyframes ex-sd-shin         { 0%,100%{transform:rotate(-6deg)}     30%,50%{transform:rotate(-28deg)}    90%{transform:rotate(-6deg)} }
@keyframes ex-legraise-thigh  { 0%,100%{transform:rotate(0deg)}      30%,50%{transform:rotate(30deg)}     90%{transform:rotate(0deg)} }
@keyframes ex-clam-thigh      { 0%,100%{transform:rotate(-10deg)}    30%,50%{transform:rotate(-38deg)}    90%{transform:rotate(-10deg)} }
@keyframes ex-clam-shin       { 0%,100%{transform:rotate(6deg)}      30%,50%{transform:rotate(20deg)}     90%{transform:rotate(6deg)} }
@keyframes ex-squat-body      { 0%,100%{transform:translateY(4px)}   30%,50%{transform:translateY(11px)}  90%{transform:translateY(4px)} }
@keyframes ex-squat-thigh     { 0%,100%{transform:rotate(6deg)}      30%,50%{transform:rotate(20deg)}     90%{transform:rotate(6deg)} }
@keyframes ex-squat-shin      { 0%,100%{transform:rotate(-10deg)}    30%,50%{transform:rotate(-32deg)}    90%{transform:rotate(-10deg)} }
@keyframes ex-squat-thigh-r   { 0%,100%{transform:rotate(-6deg)}     30%,50%{transform:rotate(-20deg)}    90%{transform:rotate(-6deg)} }
@keyframes ex-squat-shin-r    { 0%,100%{transform:rotate(10deg)}     30%,50%{transform:rotate(32deg)}     90%{transform:rotate(10deg)} }
@keyframes ex-splitsquat-thigh{ 0%,100%{transform:rotate(4deg)}      30%,50%{transform:rotate(16deg)}     90%{transform:rotate(4deg)} }
@keyframes ex-splitsquat-shin { 0%,100%{transform:rotate(-6deg)}     30%,50%{transform:rotate(-22deg)}    90%{transform:rotate(-6deg)} }
@keyframes ex-hinge-torso     { 0%,100%{transform:rotate(14deg)}     30%,50%{transform:rotate(34deg)}     90%{transform:rotate(14deg)} }
@keyframes ex-hinge-leg       { 0%,100%{transform:rotate(-6deg)}     30%,50%{transform:rotate(-22deg)}    90%{transform:rotate(-6deg)} }

/* Milestone 2: form annotations -- the "✓ pulse at the bottom of each rep"
   for step_down, timed to the same 30-50% lowered/hold window as ex-sd-thigh. */
@keyframes ex-sd-check { 0%,20%,90%,100%{opacity:0} 35%,45%{opacity:1} }

@media (prefers-reduced-motion: reduce) {
  .exercise-demo-row g, .exercise-demo-row ellipse, .exercise-demo-row circle { animation: none !important; }
}

/* ═══════════════════════════════════════════════════════════════
   MACRO TRENDS (v8 Epic E)
   ═══════════════════════════════════════════════════════════════ */

/* ── Skeleton shimmer (stale-while-revalidate loading state) ──────────────── */
@keyframes skeleton-shimmer {
  0%   { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}
.skeleton {
  background: linear-gradient(
    90deg,
    var(--card-border) 25%,
    color-mix(in srgb, var(--card-bg) 70%, var(--text)) 50%,
    var(--card-border) 75%
  );
  background-size: 200% 100%;
  animation: skeleton-shimmer 1.4s infinite;
  border-radius: 8px;
}
.skeleton-title { height: 1.5rem; width: 55%; margin-bottom: 1.25rem; }
.skeleton-page { padding: 1rem 0; }
@media (prefers-reduced-motion: reduce) {
  .skeleton { animation: none; background: var(--card-border); }
}

.macro-trend-row { padding: 0.5rem 0; border-top: 1px solid var(--card-border); }
.macro-trend-row:first-child { border-top: none; padding-top: 0; }
.macro-trend-row-head { display: flex; justify-content: space-between; align-items: baseline; }
.macro-trend-row-label { font-size: 0.82rem; font-weight: 600; color: var(--text); }
.macro-trend-row-avg { font-size: 0.74rem; color: var(--text-muted); }
.macro-trend-row-spark { display: flex; align-items: center; gap: 0.5rem; margin-top: 0.25rem; }
.macro-trend-row-delta { display: inline-flex; align-items: center; gap: 0.2rem; font-size: 0.72rem; color: var(--text-muted); white-space: nowrap; }
.macro-trend-row-delta-good { color: var(--good); }
.macro-trend-row-delta-bad { color: var(--bad); }

/* ── Batch 3: iOS input zoom prevention ─────────────────────────────────────
   iOS zooms the viewport when any focused input has font-size < 16px.
   This global floor prevents that without breaking layout — 16px = 1rem. */
input, textarea, select { font-size: 16px; }

/* ── Batch 3: View Transitions — directional tab slides ─────────────────────
   Browsers that support startViewTransition get a slide animation keyed off
   data-vt-dir="next|prev" on <html>. Older browsers keep the existing
   tab-enter-next/prev class animation unchanged. */
@keyframes vt-slide-out-left   { to   { transform: translateX(-6%); opacity: 0; } }
@keyframes vt-slide-in-right   { from { transform: translateX(6%);  opacity: 0; } }
@keyframes vt-slide-out-right  { to   { transform: translateX(6%);  opacity: 0; } }
@keyframes vt-slide-in-left    { from { transform: translateX(-6%); opacity: 0; } }

html[data-vt-dir="next"] ::view-transition-old(root) {
  animation: 220ms ease-out both vt-slide-out-left;
}
html[data-vt-dir="next"] ::view-transition-new(root) {
  animation: 220ms ease-out both vt-slide-in-right;
}
html[data-vt-dir="prev"] ::view-transition-old(root) {
  animation: 220ms ease-out both vt-slide-out-right;
}
html[data-vt-dir="prev"] ::view-transition-new(root) {
  animation: 220ms ease-out both vt-slide-in-left;
}
@media (prefers-reduced-motion: reduce) {
  ::view-transition-old(root), ::view-transition-new(root) { animation: none; }
}

/* 4.3 Collapsing large-title header — .topbar-compact toggled by JS on scroll > 48px */
header {
  transition: padding 0.25s cubic-bezier(0.16, 1, 0.3, 1);
}
#greeting-time, #today-date {
  transition: opacity 0.2s ease, max-height 0.25s ease, margin 0.25s ease;
  max-height: 2rem;
  overflow: hidden;
}
#greeting-name {
  transition: font-size 0.2s ease, margin-top 0.2s ease;
}
.topbar-compact header {
  padding-top: calc(env(safe-area-inset-top) + 0.5rem);
  padding-bottom: 0.5rem;
}
.topbar-compact #greeting-time,
.topbar-compact #today-date {
  opacity: 0;
  max-height: 0;
  margin: 0;
}
.topbar-compact #greeting-name {
  font-size: 1.125rem;
  margin-top: 0;
}

/* 4.5 prefers-reduced-motion — disable card-in, bar-width, and header transitions */
@media (prefers-reduced-motion: reduce) {
  .card,
  .macro-bar,
  .streak-chip,
  .focus-card,
  .insight-card,
  .list-tile,
  .meal,
  .list-row { animation: none; }
  .bar > span { transition: none; }
  header, #greeting-time, #today-date, #greeting-name { transition: none; }
}

/* ═══════════════════════════════════════════════════════════════
   UTILITIES (V15 batch 6) — the exact Tailwind-utility subset the
   markup uses, replacing the ~300KB runtime-compiler CDN. Kept last
   in the file to mirror the CDN's injected-last cascade position.
   Values match Tailwind v3 defaults. The dark-mode override block
   above still re-colors the slate/red/blue utilities in dark.
   ═══════════════════════════════════════════════════════════════ */

.hidden { display: none; }
.block { display: block; }
.flex { display: flex; }
.grid { display: grid; }
.fixed { position: fixed; }
.grid-cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.items-center { align-items: center; }
.items-baseline { align-items: baseline; }
.items-end { align-items: flex-end; }
.justify-between { justify-content: space-between; }
.gap-3 { gap: 0.75rem; }
.gap-x-3 { column-gap: 0.75rem; }
.space-y-1 > * + * { margin-top: 0.25rem; }
.bottom-6 { bottom: 1.5rem; }
.right-6 { right: 1.5rem; }
.h-6 { height: 1.5rem; }
.w-6 { width: 1.5rem; }
.w-full { width: 100%; }
/* Plain 100vh is computed against the LARGEST possible mobile viewport (chrome
   hidden); as the address bar/toolbar shows and hides during a scroll, the
   real visible height changes but this doesn't, making the fixed bottom-nav
   and topbar appear to jump. 100dvh tracks the actual visible viewport --
   same fix already applied to the Exercise Mode overlay elsewhere in this
   file. vh stays as the fallback for older WebViews that don't support dvh. */
.min-h-screen { min-height: 100vh; min-height: 100dvh; }
.mb-1 { margin-bottom: 0.25rem; }
.mb-2 { margin-bottom: 0.5rem; }
.mb-3 { margin-bottom: 0.75rem; }
.mb-4 { margin-bottom: 1rem; }
.mt-1 { margin-top: 0.25rem; }
.mt-2 { margin-top: 0.5rem; }
.mt-3 { margin-top: 0.75rem; }
.mt-4 { margin-top: 1rem; }
.mt-5 { margin-top: 1.25rem; }
.mx-2 { margin-left: 0.5rem; margin-right: 0.5rem; }
.p-3 { padding: 0.75rem; }
.p-4 { padding: 1rem; }
.pb-4 { padding-bottom: 1rem; }
.pb-24 { padding-bottom: 6rem; }
.pt-12 { padding-top: 3rem; }
.px-2 { padding-left: 0.5rem; padding-right: 0.5rem; }
.px-4 { padding-left: 1rem; padding-right: 1rem; }
.px-6 { padding-left: 1.5rem; padding-right: 1.5rem; }
.py-1\.5 { padding-top: 0.375rem; padding-bottom: 0.375rem; }
.py-4 { padding-top: 1rem; padding-bottom: 1rem; }
.py-12 { padding-top: 3rem; padding-bottom: 3rem; }
.text-xs { font-size: 0.75rem; line-height: 1rem; }
.text-sm { font-size: 0.875rem; line-height: 1.25rem; }
.text-base { font-size: 1rem; line-height: 1.5rem; }
.text-lg { font-size: 1.125rem; line-height: 1.75rem; }
.text-xl { font-size: 1.25rem; line-height: 1.75rem; }
.text-2xl { font-size: 1.5rem; line-height: 2rem; }
.text-3xl { font-size: 1.875rem; line-height: 2.25rem; }
.font-medium { font-weight: 500; }
.font-semibold { font-weight: 600; }
.font-bold { font-weight: 700; }
.text-center { text-align: center; }
.text-left { text-align: left; }
.uppercase { text-transform: uppercase; }
.tracking-widest { letter-spacing: 0.1em; }
.text-white { color: #ffffff; }
.text-slate-100 { color: #f1f5f9; }
.text-slate-400 { color: #94a3b8; }
.text-slate-500 { color: #64748b; }
.text-slate-600 { color: #475569; }
.text-slate-700 { color: #334155; }
.text-red-700 { color: #b91c1c; }
.text-blue-700 { color: #1d4ed8; }
.bg-slate-900 { background-color: #0f172a; }
.bg-red-50 { background-color: #fef2f2; }
.border { border-width: 1px; }
.border-red-200 { border-color: #fecaca; }
.hover\:bg-slate-50:hover { background-color: #f8fafc; }
.rounded { border-radius: 0.25rem; }
.rounded-lg { border-radius: 0.5rem; }
.rounded-xl { border-radius: 0.75rem; }
.rounded-full { border-radius: 9999px; }
.shadow-2xl { box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25); }
.cursor-pointer { cursor: pointer; }
.overflow-x-auto { overflow-x: auto; }
.antialiased { -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }
.transition-transform { transition: transform 0.15s cubic-bezier(0.4, 0, 0.2, 1); }
.active\:scale-95:active { transform: scale(0.95); }
