/* ============================================================
   Velrae Method — design system
   ============================================================ */

/* Force the HTML `hidden` attribute to always hide elements,
   even when a class on the same element sets display: flex/grid/block.
   Without this, elements like .overlay and .banner would stay visible. */
[hidden] { display: none !important; }

/* ============================================================
   v2.53 — App splash screen
   ============================================================
   Fullscreen teal panel with the V+brackets brand logo at 75vw,
   shown on cold-boot for ~2 seconds before fading. Removed from the
   DOM by the splash timer in app.js. Stays at z-index above
   everything so it covers the booting app until ready. The
   pointer-events:none during fade lets the user tap through as soon
   as the fade starts (no blocking delay). */
.app-splash {
  position: fixed;
  inset: 0;
  z-index: 99999;
  background: #70cbd0;
  display: flex;
  align-items: center;
  justify-content: center;
  animation: app-splash-fade 2.4s ease forwards;
}
.app-splash-logo {
  width: 75vw;
  max-width: 480px;
  height: auto;
  border-radius: 24px;
  filter: drop-shadow(0 8px 24px rgba(0,0,0,0.20));
}
@keyframes app-splash-fade {
  0%, 83% { opacity: 1; }                 /* hold for ~2 of 2.4s */
  100%    { opacity: 0; pointer-events: none; }
}
/* Respect users who've opted out of motion — show instantly, no fade. */
@media (prefers-reduced-motion: reduce) {
  .app-splash { animation: none; }
}
body.reduce-motion .app-splash { animation: none; }

/* ============================================================
   v2.58 — Smart Scan first-time explainer modal
   ============================================================
   Shown the first time Smart Scan auto-fires for a user. Single-tap
   "Got it" dismiss; stores a localStorage flag so we never show it
   again. Reads as warm, not technical — the user shouldn't feel like
   they triggered something unusual. */
.smart-scan-explainer-overlay {
  position: fixed;
  inset: 0;
  z-index: 9999;
  background: rgba(31, 29, 26, 0.55);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1rem;
}
.smart-scan-explainer {
  background: var(--cream-50, #fdfaf5);
  border-radius: 16px;
  padding: 1.5rem 1.25rem;
  max-width: 28rem;
  width: 100%;
  box-shadow: 0 12px 36px rgba(0, 0, 0, 0.28);
  color: var(--ink-800, #28201a);
}
.smart-scan-explainer h2 {
  margin: 0 0 0.5rem;
  font-size: 1.25rem;
  line-height: 1.25;
  color: var(--coral-500);   /* brand purple — warm, attention-grabbing */
}
.smart-scan-explainer p {
  margin: 0 0 0.75rem;
  font-size: 1rem;
  line-height: 1.4;
}
.smart-scan-explainer .smart-scan-explainer-close {
  margin-top: 0.5rem;
  width: 100%;
}

/* ============================================================
   v2.66 — Categorized conditions / diets picker
   ============================================================
   Replaces the flat 128-chip list with: a "Picked" strip at top, a
   sticky search bar with mic, a "Most common" 5-chip row, then 11
   collapsible category headers, then a separate diets section. All
   surfaces write to the same state.activeConditions array.
   Rae test: tap one category → see ~15 chips, not 128. */
.categorized-picker {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}
.picker-picked-strip {
  background: var(--green-50);
  border: 1px solid var(--green-100);
  border-radius: 12px;
  padding: 0.6rem 0.75rem;
}
.picker-picked-heading {
  margin: 0 0 0.4rem;
  font-weight: 700;
  font-size: 0.95rem;
  color: var(--green-700);
}
.picker-picked-heading.muted {
  color: var(--ink-500);
  font-weight: 600;
}
.picker-none-chip {
  font-style: italic;
}
.picker-search-wrap {
  position: sticky;
  top: 0;
  z-index: 3;
  background: var(--cream-50);
  padding: 0.4rem 0;
}
.picker-search-row {
  display: flex;
  gap: 0.4rem;
  align-items: stretch;
}
.picker-search-input {
  flex: 1;
  min-height: 48px;
  font-size: 1rem;
  padding: 0.6rem 0.8rem;
  border: 1px solid var(--cream-200);
  border-radius: 10px;
  font-family: inherit;
  background: var(--bg-surface);
}
.picker-search-input:focus {
  outline: none;
  border-color: var(--green-500);
  box-shadow: 0 0 0 3px rgba(112, 203, 208, 0.25);
}
/* v3.55 — Mic button colors made EXPLICIT and theme-independent. The old
   rule used background:var(--coral-500) + color:var(--on-primary); on the
   default purple/teal theme BOTH resolved to the same purple, so the mic
   icon was purple-on-purple = an invisible solid purple box. White button
   with a teal icon is always legible on any theme; rose when listening. */
.picker-mic-btn {
  min-width: 48px;
  min-height: 48px;
  background: #ffffff;
  color: #2b7a7f;           /* teal mic icon — visible on white, any theme */
  border: 1px solid #d8d2c4;
  border-radius: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}
.picker-mic-btn svg { width: 22px; height: 22px; }
.picker-mic-btn.listening {
  background: #e11d48;
  color: #ffffff;
  border-color: #e11d48;
  animation: picker-mic-pulse 1.2s ease-in-out infinite;
}
@keyframes picker-mic-pulse {
  0%, 100% { transform: scale(1); }
  50%      { transform: scale(1.08); }
}
.picker-section {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}
.picker-section-heading {
  margin: 0.4rem 0 0.2rem;
  font-weight: 700;
  font-size: 0.92rem;
  color: var(--ink-700);
  letter-spacing: 0.02em;
  text-transform: uppercase;
}
.picker-top-common .chip-group,
.picker-search-results .chip-group {
  margin-top: 0.2rem;
}
.picker-group {
  border: 1px solid var(--cream-200);
  border-radius: 12px;
  overflow: hidden;
  background: var(--bg-surface);
}
.picker-group-header {
  display: flex;
  align-items: center;
  width: 100%;
  min-height: 56px;
  padding: 0.75rem 0.9rem;
  background: var(--bg-surface);
  border: none;
  cursor: pointer;
  text-align: left;
  font-family: inherit;
  font-size: 1rem;
}
.picker-group-header:hover,
.picker-group-header:focus-visible {
  background: var(--cream-50);
  outline: none;
}
.picker-group-caret {
  font-size: 1rem;
  width: 1.2rem;
  margin-right: 0.5rem;
  color: var(--ink-500);
  flex-shrink: 0;
}
.picker-group-label {
  flex: 1;
  font-weight: 600;
  color: var(--ink-900);
}
.picker-group-count {
  font-size: 0.88rem;
  color: var(--ink-500);
  flex-shrink: 0;
}
.picker-group-selected {
  color: var(--green-700);
  font-weight: 700;
}
.picker-group-chips {
  padding: 0.6rem 0.75rem 0.85rem;
  border-top: 1px solid var(--cream-100);
  background: var(--cream-50);
}
.picker-section-diets .picker-group-header {
  background: var(--coral-50);
}
.picker-section-diets .picker-group-header:hover {
  background: var(--coral-100);
}
.picker-search-results {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  padding-bottom: 0.5rem;
}

/* ============================================================
   v2.73 — Nutrition Facts card with FDA context
   ============================================================
   Replaces the v2.36 4-cell grid. Vertical list of nutrient rows
   with a tier-shape badge, value, and plain-English context line
   below each ("43% of your day in one serving — very high"). Same
   tier-badge class as the ingredient rows so the visual language is
   consistent across the app. */
.nutrition-strip-v2 {
  margin: 0.6rem 1rem;
  padding: 0.55rem 0.75rem 0.45rem;
  background: var(--cream-50);
  border: 1px solid var(--cream-200);
  border-radius: 12px;
}
.nutrition-strip-v2-header {
  /* v2.77 — Centered header: title centered on top, basis +
     calorie comparison on a second line, both centered. */
  border-bottom: 1px solid var(--cream-200);
  padding-bottom: 0.5rem;
  margin-bottom: 0.55rem;
  text-align: center;
}
.nutrition-strip-v2-title {
  margin: 0;
  font-size: 0.95rem;
  font-weight: 700;
  color: var(--ink-900);
  letter-spacing: -0.005em;
}
.nutrition-strip-v2-subtitle {
  margin: 0.2rem 0 0;
  font-size: 0.88rem;
  color: var(--ink-700);
  line-height: 1.35;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.3rem 0.6rem;
}
.nutrition-strip-v2-basis {
  font-weight: 600;
  color: var(--ink-700);
}
.nutrition-strip-v2-cal-line {
  /* The calorie comparison "514 of 2,000 calories" — bold for the
     scan's value, muted for the daily reference, so the reader sees
     it as "how much of my day". */
  white-space: nowrap;
}
.nutrition-strip-v2-cal-value {
  font-weight: 700;
  color: var(--ink-900);
}
.nutrition-strip-v2-cal-ref {
  color: var(--ink-500);
  font-weight: 400;
}
/* v2.75/v2.77 — Horizontal grid of cells. One row, N columns based
   on how many nutrients the user is curated for. Each cell stacks
   tier shape + name + (% + value) line, all center-aligned. Badges
   use the SAME geometric-shape style as the "ingredients at a glance"
   chips (filled circle / half-fill / outline / triangle / circle-X
   from TIER_ICON_SVG, colored via .legend-row.tier-*) so the visual
   language is identical across the whole result screen. */
.nutrition-strip-v2-grid {
  display: grid;
  gap: 0.35rem 0.4rem;
  /* grid-template-columns is set inline based on key count */
}
.nutrition-strip-v2-cell {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 0.15rem;
  min-width: 0;
  padding: 0.25rem 0.1rem;
}
.nutrition-strip-v2-badge {
  /* v2.77 — Switched from .tier-badge (colored disk + white icon) to
     the ingredients-at-a-glance style: the geometric shape from
     TIER_ICON_SVG renders directly, colored via the .legend-row
     tier-* class (currentColor inside the SVG). One unified visual
     language for tier indicators across the entire app. */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  margin-top: 0;
  line-height: 1;
}
.nutrition-strip-v2-badge svg { width: 22px; height: 22px; display: block; }
.nutrition-strip-v2-name {
  margin: 0;
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--ink-700);
  letter-spacing: 0.01em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
}
.nutrition-strip-v2-line {
  margin: 0;
  display: flex;
  justify-content: center;
  align-items: baseline;
  gap: 0.25rem;
  font-variant-numeric: tabular-nums;
  line-height: 1.15;
}
.nutrition-strip-v2-pct {
  font-size: 0.78rem;
  font-weight: 700;
  /* Tier colors applied via the modifier classes below — same palette
     as the ingredient badges so colors mean the same thing everywhere. */
}
.nutrition-strip-v2-pct-good          { color: var(--health-good-700); }
.nutrition-strip-v2-pct-moderate_good { color: var(--health-good-500); }
.nutrition-strip-v2-pct-neutral       { color: var(--ink-500); }
.nutrition-strip-v2-pct-moderate_bad  { color: var(--health-bad-500); }
.nutrition-strip-v2-pct-bad           { color: var(--health-bad-700); }
.nutrition-strip-v2-value {
  font-size: 0.9rem;
  font-weight: 700;
  color: var(--ink-900);
  white-space: nowrap;
}
.nutrition-strip-v2-footer {
  margin: 0.45rem 0 0;
  padding-top: 0.4rem;
  border-top: 1px solid var(--cream-200);
  font-size: 0.78rem;
  color: var(--ink-500);
  text-align: center;
}
/* ============================================================
   v2.94 — Terms-of-use agreement modal (redesigned)
   Required acceptance gate. Visual hierarchy via distinct
   sections: paired IS/IS-NOT cards, warning-styled "before you
   act" alert, callout for the estimates note, numbered cards
   for the actual agreement items, sticky footer for the email +
   buttons (always reachable regardless of scroll position).
   Content unchanged — purely a visual refactor.
   ============================================================ */
.terms-overlay {
  background: rgba(20, 16, 14, 0.72);
  align-items: stretch;
  padding: 0;
}
.terms-overlay-content {
  max-width: 640px;
  width: 100%;
  max-height: 100vh;
  margin: auto;
  border-radius: 0;
  display: flex;
  flex-direction: column;
  padding: 0;
  overflow: hidden;
  background: var(--cream-50, #fefcf8);
}
@media (min-width: 640px) {
  .terms-overlay-content {
    max-height: 94vh;
    border-radius: var(--radius-lg);
    margin: 3vh auto;
  }
}

/* Header — fixed at top, never scrolls */
.terms-header {
  flex-shrink: 0;
  padding: 1.25rem 1.25rem 0.9rem;
  background: linear-gradient(180deg, var(--primary, #70cbd0) 0%, color-mix(in srgb, var(--primary, #70cbd0) 85%, white) 100%);
  color: white;
}
.terms-title {
  margin: 0;
  font-family: 'Fraunces', Georgia, serif;
  font-size: 1.3rem;
  line-height: 1.3;
  font-weight: 700;
  color: white;
}
.terms-subtitle {
  margin: 0.3rem 0 0;
  font-size: 0.88rem;
  color: rgba(255,255,255,0.92);
  line-height: 1.4;
}

/* Scrollable body */
.terms-scroll {
  flex: 1;
  overflow-y: auto;
  padding: 1.1rem 1.25rem 1rem;
  font-size: 0.95rem;
  line-height: 1.55;
  color: var(--ink-700);
}
.terms-intro {
  margin: 0 0 1rem;
  padding: 0.85rem 1rem;
  background: var(--bg-surface);
  border-left: 3px solid var(--primary, #70cbd0);
  border-radius: 0 8px 8px 0;
  font-size: 0.95rem;
}
.terms-intro strong { color: var(--ink-900); }

/* Paired IS / IS-NOT cards. Stacked on mobile, side-by-side on
   wider screens. The contrast (green vs red) is the visual point. */
.terms-pair {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0.7rem;
  margin: 0 0 1rem;
}
@media (min-width: 540px) {
  .terms-pair { grid-template-columns: 1fr 1fr; }
}
.terms-pair-card {
  border-radius: 12px;
  padding: 0.85rem 1rem 0.95rem;
  border: 1px solid transparent;
}
.terms-pair-yes {
  background: #ecf6f0;
  border-color: #c5e6d3;
}
.terms-pair-no {
  background: #fef2f2;
  border-color: #fecaca;
}
.terms-pair-title {
  margin: 0 0 0.55rem;
  font-family: 'Fraunces', Georgia, serif;
  font-size: 1rem;
  font-weight: 700;
  display: flex;
  align-items: center;
  gap: 0.5rem;
}
.terms-pair-yes .terms-pair-title { color: #1a5d44; }
.terms-pair-no  .terms-pair-title { color: #991b1b; }
.terms-pair-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  font-size: 0.85rem;
  font-weight: 800;
  color: white;
  flex-shrink: 0;
}
.terms-pair-yes .terms-pair-icon { background: var(--health-good-700, #1a5d44); }
.terms-pair-no  .terms-pair-icon { background: var(--health-bad-700, #991b1b); }
.terms-clean-list {
  margin: 0;
  padding: 0;
  list-style: none;
}
.terms-clean-list li {
  position: relative;
  padding: 0.3rem 0 0.3rem 1rem;
  font-size: 0.9rem;
  line-height: 1.45;
  color: var(--ink-700);
  border-bottom: 1px solid rgba(0,0,0,0.04);
}
.terms-clean-list li:last-child { border-bottom: none; }
.terms-clean-list li::before {
  content: '•';
  position: absolute;
  left: 0.25rem;
  top: 0.3rem;
  font-weight: 700;
}
.terms-pair-yes .terms-clean-list li::before { color: var(--health-good-700, #1a5d44); }
.terms-pair-no  .terms-clean-list li::before { color: var(--health-bad-700, #991b1b); }

/* Warning-styled "Before you act" block */
.terms-alert {
  margin: 0 0 1rem;
  padding: 0.95rem 1rem;
  background: #fffaeb;
  border: 1px solid #fde68a;
  border-left: 4px solid #d97706;
  border-radius: 10px;
}
.terms-alert-title {
  margin: 0 0 0.55rem;
  font-family: 'Fraunces', Georgia, serif;
  font-size: 1rem;
  font-weight: 700;
  color: #92400e;
}
.terms-alert-item {
  margin: 0 0 0.55rem;
  font-size: 0.92rem;
  line-height: 1.5;
  color: var(--ink-700);
}
.terms-alert-item:last-child { margin-bottom: 0; }
.terms-alert-item strong { color: #7c2d12; }

/* Estimates note — neutral callout */
.terms-note {
  margin: 0 0 1.1rem;
  padding: 0.85rem 1rem;
  background: var(--cream-100, #faf5ec);
  border-radius: 10px;
  font-size: 0.9rem;
  line-height: 1.5;
  color: var(--ink-700);
}
.terms-note p { margin: 0; }
.terms-note strong { color: var(--ink-900); }

/* THE AGREEMENT — discrete numbered cards. This is the binding
   surface, so it gets the most visual weight. */
.terms-agreement-block {
  margin: 0 0 0.5rem;
  padding: 1rem 0.5rem 0.5rem;
  border-top: 2px solid var(--cream-200);
}
.terms-agreement-heading {
  margin: 0 0 0.85rem;
  font-family: 'Fraunces', Georgia, serif;
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--ink-900);
  text-align: center;
}
.terms-agreement-list {
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
}
.terms-agreement-item {
  display: flex;
  gap: 0.75rem;
  align-items: flex-start;
  padding: 0.7rem 0.9rem;
  background: var(--bg-surface);
  border: 1px solid var(--cream-200);
  border-radius: 10px;
}
.terms-agreement-num {
  flex-shrink: 0;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--primary, #70cbd0);
  color: white;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: 'Fraunces', Georgia, serif;
  font-weight: 700;
  font-size: 0.92rem;
}
.terms-agreement-text {
  flex: 1;
  font-size: 0.93rem;
  line-height: 1.5;
  color: var(--ink-700);
}
.terms-agreement-text strong { color: var(--ink-900); font-weight: 700; }
.terms-sublist {
  margin: 0.5rem 0 0;
  padding-left: 1.2rem;
  font-size: 0.88rem;
  color: var(--ink-500);
}
.terms-sublist li { margin-bottom: 0.2rem; line-height: 1.4; }

.terms-version {
  margin: 1rem 0 0;
  font-size: 0.78rem;
  color: var(--ink-500);
  font-style: italic;
  text-align: center;
}

/* Sticky footer — email + buttons. Always reachable, never scrolls. */
.terms-footer {
  flex-shrink: 0;
  padding: 0.85rem 1.25rem 1rem;
  background: var(--bg-surface);
  border-top: 1px solid var(--cream-200);
  box-shadow: 0 -8px 16px -8px rgba(0,0,0,0.08);
}
.terms-email-label {
  display: block;
  font-size: 0.82rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--ink-700);
  margin: 0 0 0.35rem;
}
.terms-email-input {
  width: 100%;
  padding: 0.7rem 0.85rem;
  font-size: 1rem;
  border: 2px solid var(--cream-200);
  border-radius: 10px;
  font-family: inherit;
  color: var(--ink-900);
  background: var(--cream-50, #fefcf8);
}
.terms-email-input:focus {
  outline: none;
  border-color: var(--primary, #70cbd0);
  background: var(--bg-surface);
}
.terms-error-msg {
  margin: 0.45rem 0 0;
  color: var(--health-bad-700, #991b1b);
  font-size: 0.85rem;
  font-weight: 600;
}
.terms-btn-agree,
.terms-btn-disagree {
  display: block;
  width: 100%;
  border-radius: 10px;
  font-family: inherit;
  font-weight: 700;
  cursor: pointer;
  border: none;
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.terms-btn-agree {
  margin-top: 0.7rem;
  min-height: 54px;
  font-size: 1rem;
  background: var(--primary, #70cbd0);
  color: white;
  box-shadow: 0 2px 8px rgba(112, 203, 208, 0.4);
}
.terms-btn-agree:hover { transform: translateY(-1px); box-shadow: 0 4px 12px rgba(112, 203, 208, 0.5); }
.terms-btn-agree:disabled {
  opacity: 0.6;
  cursor: default;
  transform: none;
}
.terms-btn-disagree {
  margin-top: 0.4rem;
  min-height: 44px;
  font-size: 0.88rem;
  background: transparent;
  color: var(--ink-500);
  border: 1px solid var(--cream-200);
}
.terms-btn-disagree:hover { background: var(--cream-100); color: var(--ink-700); }
.terms-toc-link-wrap {
  margin: 0.6rem 0 0;
  text-align: center;
  font-size: 0.82rem;
}
.terms-toc-link {
  color: var(--ink-500);
  text-decoration: underline;
}
.terms-toc-link:hover { color: var(--ink-700); }

/* v2.92 — My Devices list in Settings → Subscription.
   Each device row mirrors the .history-row pattern: icon + meta + action. */
.device-row {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.75rem 0.85rem;
  border: 1px solid var(--cream-200);
  border-radius: 10px;
  background: var(--bg-surface);
  margin-bottom: 0.5rem;
}
.device-row-icon {
  width: 36px;
  height: 36px;
  border-radius: 9px;
  background: var(--cream-100);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.3rem;
  flex-shrink: 0;
}
.device-row-meta { flex: 1; min-width: 0; }
.device-row-label {
  margin: 0;
  font-weight: 600;
  color: var(--ink-900);
  font-size: 0.95rem;
}
.device-row-when {
  margin: 0.15rem 0 0;
  color: var(--ink-500);
  font-size: 0.82rem;
}
.device-row-this {
  flex-shrink: 0;
  padding: 0.3rem 0.7rem;
  background: var(--primary, #70cbd0);
  color: white;
  border-radius: 8px;
  font-size: 0.78rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}
.device-row-remove {
  flex-shrink: 0;
  background: none;
  border: 1px solid var(--health-bad-500);
  color: var(--health-bad-700);
  padding: 0.4rem 0.85rem;
  border-radius: 8px;
  font-family: inherit;
  font-size: 0.85rem;
  font-weight: 600;
  cursor: pointer;
}
.device-row-remove:hover { background: var(--health-bad-50); }

/* ============================================================
   v2.97 — Menu-page scan modal
   Two-step restaurant flow: capture menu photo → AI extracts items
   → user picks one → existing describe-meal flow takes over for
   the per-item grade card.
   ============================================================ */
.menu-scan-modal-content {
  max-width: 560px;
  width: 100%;
  max-height: 92vh;
  display: flex;
  flex-direction: column;
  padding: 0;
  overflow: hidden;
  background: var(--cream-50, #fefcf8);
}
@media (max-width: 560px) {
  .menu-scan-modal-content {
    max-height: 100vh;
    border-radius: 0;
    margin: 0;
  }
}
.menu-scan-modal-header {
  flex-shrink: 0;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 0.5rem;
  padding: 0.85rem 1rem 0.7rem;
  background: var(--bg-surface);
  border-bottom: 1px solid var(--cream-200);
}
.menu-scan-modal-title {
  margin: 0;
  font-family: 'Fraunces', Georgia, serif;
  font-size: 1.15rem;
  font-weight: 700;
  color: var(--ink-900);
}
.menu-scan-modal-tier {
  margin: 0.2rem 0 0;
  font-size: 0.78rem;
  color: var(--ink-500);
}
.menu-scan-modal-body {
  flex: 1;
  overflow-y: auto;
  padding: 1rem;
}

/* Item picker — tappable rows */
.menu-scan-pick-item {
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
  width: 100%;
  text-align: left;
  background: var(--bg-surface);
  border: 1px solid var(--cream-200);
  border-radius: 10px;
  padding: 0.7rem 0.85rem;
  margin-bottom: 0.4rem;
  cursor: pointer;
  transition: all 0.12s ease;
  font-family: inherit;
}
.menu-scan-pick-item:hover {
  border-color: var(--primary, #70cbd0);
  transform: translateY(-1px);
  box-shadow: 0 2px 8px rgba(0,0,0,0.05);
}
/* v3.85 — multi-select: circular check chip on the left, teal-filled when chosen */
.menu-scan-pick-item-body { flex: 1; min-width: 0; }
.menu-scan-pick-check {
  flex: none;
  width: 1.6rem;
  height: 1.6rem;
  border-radius: 50%;
  border: 1.5px solid var(--cream-200);
  color: var(--ink-500);
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 700;
  line-height: 1;
  margin-top: 0.05rem;
  transition: background 0.12s ease, border-color 0.12s ease, color 0.12s ease;
}
.menu-scan-pick-item.selected {
  border-color: var(--primary, #70cbd0);
  background: var(--teal-50, #eef9fa);
}
.menu-scan-pick-item.selected .menu-scan-pick-check {
  background: var(--primary, #70cbd0);
  border-color: var(--primary, #70cbd0);
  color: #fff;
}
.menu-scan-pick-item-name {
  margin: 0;
  font-weight: 700;
  color: var(--ink-900);
  font-size: 0.95rem;
}
.menu-scan-pick-item-desc {
  margin: 0.2rem 0 0;
  color: var(--ink-500);
  font-size: 0.82rem;
  line-height: 1.4;
}
.menu-scan-pick-item-price {
  display: inline-block;
  margin-left: 0.5rem;
  color: var(--ink-700);
  font-weight: 600;
  font-size: 0.85rem;
}
.menu-scan-pick-cat-label {
  margin: 0.6rem 0 0.3rem;
  font-size: 0.78rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ink-500);
}
.menu-scan-pick-cat-label:first-child { margin-top: 0; }

/* v2.82 — Portion-size picker chips used in the describe-meal modal
   when context = 'restaurant'. Tap-to-select pattern (not a dropdown)
   per user preference. Active chip carries the teal primary color. */
.portion-chip {
  background: var(--cream-50);
  border: 2px solid var(--cream-200);
  border-radius: 10px;
  padding: 0.55rem 0.5rem;
  font-family: inherit;
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--ink-700);
  cursor: pointer;
  transition: all 0.15s cubic-bezier(0.2, 0.7, 0.2, 1);
}
.portion-chip:hover {
  border-color: var(--primary, #70cbd0);
}
.portion-chip.active {
  background: var(--primary, #70cbd0);
  border-color: var(--primary, #70cbd0);
  color: white;
}

/* v2.81 — Footer separator dot between the two reference links
   (See full nutrition facts · % of FDA daily value · see full FDA table) */
.nutrition-strip-v2-footer-sep { color: var(--ink-300); }

/* ============================================================
   v2.81 — Full Nutrition Facts modal
   FDA-style label recreation. Uses real-label typography
   (heavy black rules between sections, big calories number,
   indented sub-rows) so it reads as "this is the label" rather
   than a generic app card.
   ============================================================ */
.full-nf-title-block { text-align: center; margin-bottom: 0.5rem; }
.full-nf-title {
  font-family: 'Fraunces', Georgia, serif;
  font-size: 1.7rem;
  font-weight: 800;
  margin: 0;
  letter-spacing: -0.01em;
}
.full-nf-sub {
  margin: 0.15rem 0 0;
  font-size: 0.78rem;
  color: var(--ink-500);
}
.full-nf-header {
  border-top: 8px solid var(--ink-900);
  border-bottom: 1px solid var(--ink-900);
  padding: 0.4rem 0;
  margin-top: 0.5rem;
}
.full-nf-serving-row {
  display: flex;
  justify-content: space-between;
  font-size: 0.95rem;
  padding: 0.15rem 0;
}
.full-nf-calories {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  padding: 0.4rem 0;
  border-bottom: 4px solid var(--ink-900);
  font-weight: 800;
}
.full-nf-calories span { font-size: 1.05rem; }
.full-nf-calories strong { font-size: 1.9rem; font-family: 'Fraunces', Georgia, serif; }
.full-nf-dv-header {
  text-align: right;
  font-weight: 700;
  font-size: 0.8rem;
  padding: 0.3rem 0 0.2rem;
  border-bottom: 1px solid var(--ink-900);
}
.full-nf-row {
  display: flex;
  justify-content: space-between;
  padding: 0.3rem 0;
  border-bottom: 1px solid var(--cream-200);
  font-size: 0.92rem;
}
.full-nf-row.full-nf-bold { font-weight: 700; }
.full-nf-row.full-nf-indent { padding-left: 1.2rem; }
.full-nf-row.full-nf-divider { border-bottom: 4px solid var(--ink-900); }
.full-nf-label strong { font-weight: 600; }
.full-nf-pct { font-weight: 700; min-width: 3rem; text-align: right; }
.full-nf-footnote {
  margin: 0.7rem 0 0;
  font-size: 0.72rem;
  color: var(--ink-500);
  line-height: 1.45;
}

/* v2.76 — Reference link is a real button so users can actually
   navigate to the FDA table from the footer. */
.nutrition-strip-v2-ref-link {
  background: none;
  border: none;
  padding: 0;
  margin: 0;
  font: inherit;
  font-weight: 600;
  color: var(--green-700);
  text-decoration: underline;
  text-underline-offset: 2px;
  cursor: pointer;
}
.nutrition-strip-v2-ref-link:hover,
.nutrition-strip-v2-ref-link:focus-visible {
  color: var(--coral-500);
  outline: none;
}

/* v2.73 — Settings → References card showing FDA daily values. Two-column
   table-style layout that reads cleanly even on iPhone SE width. */
.fda-references-table {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 0.3rem 0.75rem;
  margin: 0.5rem 0 0;
  font-size: 0.95rem;
}
.fda-references-name {
  color: var(--ink-700);
}
.fda-references-value {
  font-weight: 700;
  color: var(--ink-900);
  font-variant-numeric: tabular-nums;
  text-align: right;
}

/* v2.72 — Add-to-list picker modal rows. Each existing list renders
   as a large tappable button (Pillar 4 — elderly-friendly target).
   The picker is shown inside the standard .overlay so backdrop +
   centering come for free. */
.add-to-list-row {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.2rem;
  padding: 0.85rem 1rem;
  min-height: 64px;
  background: var(--bg-surface);
  border: 1px solid var(--cream-200);
  border-radius: 12px;
  cursor: pointer;
  text-align: left;
  font-family: inherit;
  width: 100%;
}
.add-to-list-row:hover,
.add-to-list-row:focus-visible {
  background: var(--green-50);
  border-color: var(--green-300);
  outline: none;
}
.add-to-list-row-name {
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--ink-900);
}
.add-to-list-row-meta {
  font-size: 0.85rem;
  color: var(--ink-500);
}

/* v2.63 — Smart Scan badge under the product name on results. Tiny
   informational pill — not a CTA. Lets the user see at a glance that
   cloud assist was used on this scan. */
.smart-scan-badge {
  text-align: center;
  margin: 0.25rem 1rem 0;
}
.smart-scan-badge-pill {
  display: inline-block;
  padding: 0.15rem 0.55rem;
  background: var(--coral-50);
  color: var(--coral-500);
  border: 1px solid var(--coral-100);
  border-radius: 999px;
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.02em;
}

/* v2.62 — Friendly hint when Smart Scan got ingredients but the
   nutrition facts panel wasn't visible enough to read. Shown in
   place of the nutrition strip so the user knows what to do next
   (retake focused on the back panel). */
.nutrition-strip-missing {
  margin: 0.75rem 1rem;
  padding: 0.75rem 0.9rem;
  background: var(--amber-50, #fff8e6);
  border: 1px solid var(--amber-100, #fce8a8);
  border-left: 4px solid var(--amber-500, #d97706);
  border-radius: 10px;
}
.nutrition-strip-missing-header {
  margin: 0 0 0.25rem;
  font-weight: 700;
  font-size: 0.98rem;
  color: var(--ink-800, #28201a);
}
.nutrition-strip-missing-body {
  margin: 0;
  font-size: 0.9rem;
  line-height: 1.35;
  color: var(--ink-700, #4a3f33);
}

/* ============================================================
   v2.55 — Stale-backup banner (home screen)
   ============================================================
   Renders at the top of the home tab when the user hasn't backed up
   in 14+ days (or has never backed up). Attention-getting amber so
   it's visible without being alarming red, but still clearly more
   urgent than a regular muted note. Padded for finger-tap on the
   "Back up now" CTA and the small dismiss X. Hides itself for 24h
   after dismissal so we're persistent but not naggy.
   Per-pillar: elderly-accessibility — large target on the CTA,
   readable copy, high contrast text on amber. */
.backup-stale-banner {
  display: grid;
  grid-template-columns: auto 1fr auto;
  grid-template-areas:
    "icon body close"
    "cta cta cta";
  gap: 0.6rem 0.75rem;
  align-items: start;
  margin: 0.75rem 1rem 0.5rem;
  padding: 0.85rem 0.9rem;
  background: var(--amber-50, #fff8e6);
  border: 1px solid var(--amber-100, #fce8a8);
  border-left: 4px solid var(--amber-500, #d97706);
  border-radius: 12px;
  color: var(--ink-800, #28201a);
  box-shadow: 0 1px 4px rgba(0,0,0,0.06);
}
.backup-stale-icon {
  grid-area: icon;
  font-size: 1.4rem;
  line-height: 1.1;
}
.backup-stale-body {
  grid-area: body;
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  min-width: 0;
}
.backup-stale-body strong { font-size: 1.02rem; line-height: 1.25; }
.backup-stale-body span   { font-size: 0.92rem; line-height: 1.35; color: var(--ink-700, #4a3f33); }
.backup-stale-cta {
  grid-area: cta;
  margin-top: 0.25rem;
  width: 100%;
}
.backup-stale-close {
  grid-area: close;
  background: transparent;
  border: none;
  color: var(--ink-600, #5a4f44);
  font-size: 1.5rem;
  line-height: 1;
  width: 32px;
  height: 32px;
  border-radius: 16px;
  cursor: pointer;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}
.backup-stale-close:hover,
.backup-stale-close:focus-visible {
  background: rgba(0,0,0,0.06);
  outline: none;
}

/* ============================================================
   THEME OVERRIDES — applied via body.theme-<name>
   The base palette uses --green-* names for legacy reasons; each
   theme overrides those values to recolor the entire app without
   touching individual rules. Tier colors (good/bad) stay constant
   so a red "Avoid" verdict always reads as a warning.
   ============================================================ */

/* Forest (default) — already defined in :root */

/* v2.51 — Brand-purple theme (was generic 'Royal' #7c3aed; now anchored
   on user-specified brand purple #4b246b). Paired with brand teal as
   the accent — mirror of the default Teal theme which has teal primary +
   purple accent. */
body.theme-royal {
  --green-50:  #f4edfa;
  --green-100: #e6d5f0;
  --green-300: #9168b3;
  --green-500: #4b246b;   /* BRAND purple — user-specified */
  --green-700: #2c1342;   /* deepest purple */
  --green-900: #1a0827;
  --coral-50:  #ecf7f8;
  --coral-100: #cfedef;
  --coral-500: #70cbd0;   /* BRAND teal — paired as accent */
  --coral-700: #1a4f53;
}

body.theme-ocean {
  --green-50:  #e6f4f8;
  --green-100: #c5e6ee;
  --green-300: #6cb7c8;
  --green-500: #0e7490;
  --green-700: #155e75;
  --green-900: #083344;
  --coral-50:  #fff7ed;
  --coral-100: #ffedd5;
  --coral-500: #ea580c;
  --coral-700: #9a3412;
}

body.theme-coral {
  --green-50:  #fff1ed;
  --green-100: #ffe1d6;
  --green-300: #fda58c;
  --green-500: #ea580c;
  --green-700: #9a3412;
  --green-900: #5e2208;
  --coral-50:  #fef9c3;
  --coral-100: #fef08a;
  --coral-500: #ca8a04;
  --coral-700: #854d0e;
}

body.theme-rose {
  --green-50:  #fdf2f8;
  --green-100: #fce7f3;
  --green-300: #f9a8d4;
  --green-500: #db2777;
  --green-700: #9d174d;
  --green-900: #500724;
  --coral-50:  #f3e8ff;
  --coral-100: #e9d5ff;
  --coral-500: #a855f7;
  --coral-700: #6b21a8;
}

body.theme-slate {
  --green-50:  #eef2f6;
  --green-100: #d6dde6;
  --green-300: #7e8da3;
  --green-500: #475569;
  --green-700: #1e293b;
  --green-900: #0f172a;
  --coral-50:  #fef3c7;
  --coral-100: #fde68a;
  --coral-500: #d97706;
  --coral-700: #92400e;
}

/* True blue (distinct from teal-leaning ocean). */
body.theme-blue {
  --green-50:  #eff6ff;
  --green-100: #dbeafe;
  --green-300: #93c5fd;
  --green-500: #1d4ed8;
  --green-700: #1e3a8a;
  --green-900: #172554;
  --coral-50:  #fff7ed;
  --coral-100: #ffedd5;
  --coral-500: #f59e0b;
  --coral-700: #b45309;
}

/* True red (distinct from rose, which is pink). */
body.theme-red {
  --green-50:  #fef2f2;
  --green-100: #fee2e2;
  --green-300: #fca5a5;
  --green-500: #dc2626;
  --green-700: #991b1b;
  --green-900: #7f1d1d;
  --coral-50:  #fff7ed;
  --coral-100: #ffedd5;
  --coral-500: #f59e0b;
  --coral-700: #b45309;
}

/* Gold / deep yellow. White on bright yellow fails contrast, so we
   push toward a richer amber that still reads as a 'yellow theme' in
   accents and chips while keeping topbar text legible. */
body.theme-gold {
  --green-50:  #fefce8;
  --green-100: #fef9c3;
  --green-300: #facc15;
  --green-500: #a16207;
  --green-700: #713f12;
  --green-900: #422006;
  --coral-50:  #ecfeff;
  --coral-100: #cffafe;
  --coral-500: #0891b2;
  --coral-700: #155e75;
}

/* v2.56 — Every alternative theme uses a dark primary color where
   white-on-primary passes WCAG just fine. Override the default's
   purple-on-teal on-primary value back to white for these themes.
   The default :root keeps --on-primary: var(--coral-500) (purple). */
body.theme-royal,
body.theme-ocean,
body.theme-coral,
body.theme-rose,
body.theme-slate,
body.theme-blue,
body.theme-red,
body.theme-gold {
  --on-primary: white;
}

/* ============================================================
   ACCESSIBILITY
   ============================================================ */

/* Larger default tap targets for limited motor skills */
.btn, .chip, .mode-btn, .tab-btn, .icon-btn, .tab-strip-btn {
  min-height: 48px;  /* WCAG recommends >= 44px; we go 48 for comfort */
}
.icon-btn { width: 48px; height: 48px; }

/* Text size scaling — toggle via body class */
body.text-large { font-size: 18px; }
body.text-xlarge { font-size: 20px; }

/* High contrast mode — pushes contrast further for very low vision.
   Default colors already pass WCAG AA; this is for users who want max
   readability over visual softness. */
body.high-contrast {
  --ink-500: #2a2a2a;   /* "muted" becomes nearly black */
  --ink-300: #4a4a4a;
}
body.high-contrast .card { border: 1px solid #1a1a1a; }
body.high-contrast .ingredient-row { border-left-width: 6px; }
body.high-contrast .muted { color: var(--ink-500) !important; }

/* Soft theme — opt-out for users who prefer the older, lighter aesthetic.
   Restores the original (lower-contrast) muted color. Not recommended for
   elderly users; available as a personal preference toggle. */
body.theme-soft {
  --ink-500: #6b6357;
  --ink-300: #b4a99b;
}

/* Reduced motion — honors OS preference for users sensitive to animation */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}
body.reduce-motion *, body.reduce-motion *::before, body.reduce-motion *::after {
  animation-duration: 0.01ms !important;
  animation-iteration-count: 1 !important;
  transition-duration: 0.01ms !important;
  scroll-behavior: auto !important;
}

/* Stronger focus rings for keyboard / switch-control users */
*:focus-visible {
  outline: 3px solid var(--green-500);
  outline-offset: 2px;
  border-radius: 4px;
}

/* ============================================================
   THEME PICKER (settings UI)
   ============================================================ */
.theme-swatches {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0.5rem;
  margin-top: 0.5rem;
}
.theme-swatch {
  border: 3px solid transparent;
  border-radius: 14px;
  padding: 0.6rem 0.5rem;
  cursor: pointer;
  background: var(--cream-50);
  transition: transform 0.15s ease, border-color 0.15s ease;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.4rem;
  font-family: inherit;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--ink-700);
  min-height: 64px;
}
.theme-swatch:hover { transform: translateY(-2px); }
.theme-swatch.selected { border-color: var(--ink-900); }
.theme-swatch-dot {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  box-shadow: inset 0 0 0 2px white, 0 1px 3px rgba(0,0,0,0.15);
}

/* ============================================================
   PROFILE SWITCHER (multi-profile)
   ============================================================ */
.profile-pill {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  background: rgba(255,255,255,0.18);
  color: white;
  border: none;
  padding: 0.35rem 0.7rem 0.35rem 0.4rem;
  border-radius: 999px;
  font-size: var(--text-secondary);
  font-weight: 600;
  cursor: pointer;
  font-family: inherit;
  min-height: 40px;
}
.profile-pill:hover { background: rgba(255,255,255,0.28); }
.profile-pill-avatar {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--bg-surface);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--green-700);
  font-weight: 800;
  font-size: var(--text-pill);
}

/* Pillar 2 — when 2+ profiles exist, the pill becomes the primary action
   for caregivers. Bigger, brighter, harder to miss. */
body.has-multiple-profiles .profile-pill {
  background: rgba(255,255,255,0.32);
  font-size: var(--text-body);
  font-weight: 700;
  padding: 0.45rem 0.95rem 0.45rem 0.5rem;
  min-height: 48px;
  box-shadow: 0 2px 8px rgba(0,0,0,0.12);
}
body.has-multiple-profiles .profile-pill::after {
  content: '⇄';
  margin-left: 0.25rem;
  font-size: 0.85rem;
  opacity: 0.85;
}
body.has-multiple-profiles .profile-pill-avatar {
  width: 32px;
  height: 32px;
  font-size: var(--text-secondary);
}

.profile-row {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.75rem 0;
  border-bottom: 1px solid var(--cream-100);
}
.profile-row:last-of-type { border-bottom: none; }
.profile-avatar {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  color: white;
  font-weight: 800;
  font-family: 'Fraunces', Georgia, serif;
  flex-shrink: 0;
}
.profile-meta { flex: 1; min-width: 0; }
.profile-name { font-weight: 600; margin: 0; }
.profile-conditions { font-size: 0.82rem; color: var(--ink-500); margin: 0.15rem 0 0; }
.profile-actions { display: flex; gap: 0.5rem; }

/* ============================================================
   AIP PHASE TRACKER
   ============================================================ */
.aip-phase-pill {
  display: inline-flex;
  align-items: center;
  padding: 0.35rem 0.85rem;
  border-radius: 999px;
  font-size: 0.85rem;
  font-weight: 600;
  letter-spacing: 0.02em;
}
.aip-phase-pill.none { background: var(--cream-100); color: var(--ink-700); }
.aip-phase-pill.elimination { background: var(--coral-50); color: var(--coral-700); }
.aip-phase-pill.reintroducing { background: var(--green-50); color: var(--green-700); }

.aip-stage {
  background: var(--bg-surface);
  border-radius: var(--radius);
  margin: 0.5rem 1rem;
  padding: 1.1rem 1.25rem;
  box-shadow: var(--shadow-sm);
}
.aip-stage h3 {
  font-family: 'Fraunces', Georgia, serif;
  margin: 0 0 0.3rem;
  font-size: 1.1rem;
}
.aip-food-group {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.6rem 0;
  border-bottom: 1px solid var(--cream-100);
}
.aip-food-group:last-child { border-bottom: none; }
.aip-food-status {
  font-size: var(--text-pill);
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  padding: 0.25rem 0.65rem;
  border-radius: 999px;
}
.aip-food-status.untested { background: var(--cream-100); color: var(--ink-500); }
.aip-food-status.testing { background: var(--amber-50); color: var(--amber-700); }
.aip-food-status.ok { background: var(--green-50); color: var(--green-700); }
.aip-food-status.bad { background: var(--rose-50); color: var(--rose-700); }

/* ============================================================
   MEAL BUILDER
   ============================================================ */
.meal-component {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.65rem 0;
  border-bottom: 1px solid var(--cream-100);
}
.meal-component:last-child { border-bottom: none; }
.meal-component-name {
  flex: 1;
  min-width: 0;
  font-weight: 500;
  color: var(--ink-900);
}
.meal-component-tier {
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  padding: 0.2rem 0.55rem;
  border-radius: 999px;
  color: white;
  white-space: nowrap;
}
.meal-component-tier.tier-good           { background: var(--tier-good); }
.meal-component-tier.tier-moderate_good  { background: var(--tier-moderate-good); }
.meal-component-tier.tier-neutral        { background: var(--tier-neutral); }
.meal-component-tier.tier-moderate_bad   { background: var(--tier-moderate-bad); }
.meal-component-tier.tier-bad            { background: var(--tier-bad); }
.meal-component-remove {
  background: transparent;
  border: none;
  width: 32px; height: 32px;
  border-radius: 50%;
  color: var(--ink-500);
  cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  transition: background 0.15s ease;
}
.meal-component-remove:hover { background: rgba(0,0,0,0.06); color: var(--rose-700); }
.meal-component-remove svg { width: 16px; height: 16px; }

.meal-empty {
  padding: 0.75rem 0;
  color: var(--ink-500);
  font-size: 0.9rem;
  font-style: italic;
}

/* Big primary actions on the meal builder — sized for elderly users with
   limited motor skills. Each button is ~64px tall with a leading icon and
   plain-language label. */
.meal-action-big {
  min-height: 64px !important;
  font-size: 1.05rem;
  gap: 0.6rem;
}
.meal-action-big svg { flex-shrink: 0; }

/* Voice modal: pulsing mic indicator while recording */
#voice-mic-indicator {
  transition: background 0.3s ease, color 0.3s ease, transform 0.3s ease;
}
#voice-mic-indicator.listening {
  background: var(--rose-50);
  color: var(--rose-700);
  animation: micPulse 1.5s ease-in-out infinite;
}
@keyframes micPulse {
  0%, 100% { transform: scale(1); box-shadow: 0 0 0 0 rgba(208, 84, 80, 0.55); }
  50%      { transform: scale(1.06); box-shadow: 0 0 0 18px rgba(208, 84, 80, 0); }
}
body.reduce-motion #voice-mic-indicator.listening { animation: none; }

/* ----- OCR confirmation banner (shown above paste textarea after photo/camera scan) ----- */
.ocr-banner {
  background: linear-gradient(135deg, #ecf6f0 0%, #d8eee0 100%);
  border: 1px solid #7fc2a0;
  margin: 1rem 1rem 0;
  padding: 0.875rem 1rem;
  border-radius: 14px;
  display: flex;
  align-items: center;
  gap: 0.75rem;
  box-shadow: 0 1px 2px rgba(40, 30, 20, 0.05);
  animation: ocrBannerIn 0.35s cubic-bezier(0.2, 0.7, 0.2, 1);
}
@keyframes ocrBannerIn {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: translateY(0); }
}
.ocr-banner-icon {
  width: 36px; height: 36px;
  border-radius: 50%;
  background: var(--bg-surface);
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0;
  color: #1a4f53;
  box-shadow: 0 1px 2px rgba(40, 30, 20, 0.05);
}
.ocr-banner-icon svg { width: 20px; height: 20px; }
.ocr-banner-body { flex: 1; display: flex; flex-direction: column; line-height: 1.3; min-width: 0; }
.ocr-banner-body strong { color: #1a4f53; font-size: var(--text-body); }
.ocr-banner-body .small { font-size: var(--text-secondary); color: var(--ink-500); margin-top: 0.15rem; }
.ocr-banner-dismiss {
  background: transparent; border: none;
  width: 30px; height: 30px;
  border-radius: 50%;
  color: #6b6357;
  cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0;
  transition: background 0.15s ease;
}
.ocr-banner-dismiss:hover { background: rgba(0,0,0,0.05); }
.ocr-banner-dismiss svg { width: 16px; height: 16px; }

/* ----- Scan log modal (developer) ----- */
.scanlog-modal-content {
  background: var(--bg-surface);
  width: 96%;
  max-width: 720px;
  max-height: 90vh;
  border-radius: 14px;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  box-shadow: 0 12px 32px rgba(40, 30, 20, 0.18);
}
.scanlog-modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 1rem 1.25rem;
  border-bottom: 1px solid #ede4d3;
}
.scanlog-modal-header h2 {
  margin: 0;
  font-family: 'Fraunces', Georgia, serif;
  font-size: 1.25rem;
}
.scanlog-modal-body {
  padding: 0.5rem 0 1rem;
  overflow-y: auto;
  flex: 1;
}
.scanlog-entry {
  padding: 0.875rem 1.25rem;
  border-bottom: 1px solid #f6f0e6;
}
.scanlog-entry:last-child { border-bottom: none; }
.scanlog-entry-head {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
  font-size: 0.85rem;
  color: #6b6357;
  margin-bottom: 0.5rem;
}
.scanlog-entry-grade {
  font-family: 'Fraunces', Georgia, serif;
  font-weight: 800;
  background: linear-gradient(135deg, #2d7479, #1a4f53);
  color: white;
  padding: 0.1rem 0.55rem;
  border-radius: 999px;
  font-size: 0.85rem;
}
.scanlog-entry-grade.grade-D, .scanlog-entry-grade.grade-F {
  background: linear-gradient(135deg, #d05450, #9c2e2a);
}
.scanlog-entry-grade.grade-C { background: linear-gradient(135deg, #b4a99b, #6b6357); }
.scanlog-entry-tag {
  display: inline-flex;
  align-items: center;
  font-size: 0.7rem;
  padding: 0.1rem 0.45rem;
  border-radius: 999px;
  background: #f6f0e6;
  color: #3d3a36;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  font-weight: 600;
}
.scanlog-entry-tag.edited { background: #fef5e7; color: #b46a18; }
.scanlog-entry-tag.failed { background: #fdecec; color: #9c2e2a; }
.scanlog-entry-tag.source { background: #ecf7f8; color: #1a4f53; }
.scanlog-entry-detail {
  font-size: 0.8rem;
  color: #6b6357;
  margin: 0.25rem 0 0.5rem;
}
.scanlog-entry-text {
  background: #fbf6ee;
  border-radius: 8px;
  padding: 0.6rem 0.75rem;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.8rem;
  color: #3d3a36;
  white-space: pre-wrap;
  word-break: break-word;
  margin-top: 0.4rem;
  max-height: 8em;
  overflow-y: auto;
}
.scanlog-entry-label {
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: #6b6357;
  font-weight: 700;
  margin: 0.6rem 0 0.2rem;
}
.scanlog-empty {
  text-align: center;
  padding: 2rem 1.5rem;
  color: #6b6357;
}

/* ----- Fonts ----- */
@import url('https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,500;9..144,700;9..144,900&family=Inter:wght@400;500;600;700&display=swap');

/* ----- Design tokens ----- */
:root {
  /* v2.56 — Brand palette: literal user-specified TEAL #70cbd0 as the
     PRIMARY color (per repeated user direction), PURPLE #4b246b as the
     ACCENT and as the foreground color on teal surfaces (to handle WCAG
     contrast — white on #70cbd0 fails at 1.84:1, purple on teal passes
     at 5.84:1). Follows the same green-500/coral-500 pattern every
     other theme uses, so it themes consistently with Ocean/Sunset/etc.
     Variable names (--green-*, --coral-*) retained for backwards
     compatibility with hundreds of existing rule references. */
  --green-50:  #ecf7f8;
  --green-100: #cfedef;
  --green-300: #a3dde0;   /* lighter teal — subtle backgrounds */
  --green-500: #70cbd0;   /* BRAND TEAL — primary, user-specified literal */
  --green-700: #4a989d;   /* darker teal — hover/borders only */
  --green-900: #2a6064;

  --coral-50:  #f4edfa;
  --coral-100: #e6d5f0;
  --coral-500: #4b246b;   /* BRAND PURPLE — accent + foreground on teal */
  --coral-700: #2c1342;

  /* v2.56 — Foreground color for text/icons rendered on top of a
     primary (green-500) surface. Default brand teal #70cbd0 is too
     light for white, so the default is brand purple (passes WCAG
     5.84:1). Every body.theme-* with a darker primary overrides this
     back to white. Use var(--on-primary) anywhere you'd otherwise
     write color:white on a primary background. */
  --on-primary: var(--coral-500);

  --amber-50:  #fef5e7;
  --amber-500: #e8923a;
  --amber-700: #b46a18;

  --rose-50:   #fdecec;
  --rose-500:  #d05450;
  --rose-700:  #9c2e2a;

  --cream-50:  #fdfaf5;   /* main app background */
  --cream-100: #f6f0e6;
  --cream-200: #ede4d3;
  --cream-300: #e0d4bd;   /* v3.91 — defined for dark-mode parity (was inline-only) */

  /* v3.91 — Semantic surface tokens. Light defaults; the dark @media block
     below remaps these. Cards/sheets use var(--bg-surface) instead of a
     hardcoded white so they invert automatically with the system setting. */
  --bg-app:     var(--cream-50);
  --bg-surface: #ffffff;

  --ink-900:   #1f1d1a;
  --ink-700:   #3d3a36;
  /* Default --ink-500 is intentionally dark enough to pass WCAG AA against
     --cream-50 (4.7:1). The old #6b6357 (3.6:1) was the most common Pillar 4
     violation — looked elegant, failed elderly eyes. body.theme-soft can
     opt back into the lighter aesthetic for users who prefer it. */
  --ink-500:   #4a443c;
  --ink-300:   #847a6b;

  /* ===== Type scale (Pillar 4) =====
     Reach for these via var(--text-*) instead of literal font-size values.
     Reference: .small uses --text-secondary, NOT 0.875rem directly. */
  --text-body:      1rem;       /* 16px @ 16px root — body text minimum */
  --text-large:     1.125rem;   /* 18px — light emphasis */
  --text-secondary: 0.95rem;    /* 15.2px — used to be "small", now legible */
  --text-caption:   0.875rem;   /* 14px — true asides only (timestamps, footnotes) */
  --text-pill:      0.85rem;    /* 13.6px — chip/badge labels (raised from 0.7-0.75rem) */

  /* ============================================================
     HEALTH-MEANING COLORS — these encode "good for you / bad for you"
     and MUST NEVER be themed. Picking a slate or royal theme remaps
     --green-* / --coral-* for branding, but a Grade A always has to
     read as the same trusted green. Themes are forbidden from
     touching anything below this line. */
  --health-good-50:   #ecf6f0;
  --health-good-500:  #2d8662;
  --health-good-700:  #1a5d44;
  /* Caution (Grade C) — gold, biased toward yellow. White text needs at
     least 3:1 contrast for the large grade-letter rule; #b8860b lands at
     ~3.3:1, which is the closest we can get to "stoplight yellow" while
     keeping white text readable. Goes notably more golden than the prior
     #ca8a04 to widen the hue gap between C (gold) and D (orange) — the
     prior pair both read as "yellow-orange" at arm's length. */
  --health-caution-50:   #fef9c3;
  --health-caution-500:  #b8860b;
  --health-caution-700:  #6b4a07;
  /* Warn (Grade D) — true orange (not amber). Sits at hue ~18°, clearly
     orange rather than warm-yellow. White contrast ~3.5:1, passes the
     large-text rule. */
  --health-warn-50:   #ffedd5;
  --health-warn-500:  #ea580c;
  --health-warn-700:  #9a3412;
  /* Bad (Grade F) — true stoplight red (not muted salmon). White contrast
     4.8:1, passes WCAG AA everywhere. The prior #d05450 read as too
     friendly for "not for you." */
  --health-bad-50:    #fef2f2;
  --health-bad-500:   #dc2626;
  --health-bad-700:   #991b1b;
  --health-neutral-500: #b4a99b;
  --health-neutral-700: #6b6357;
  --health-lime-500:    #84cc16;   /* moderate-good (between A and C) */

  /* Tier semantics — derived from the health colors, never themed.
     v2.78 — Repointed from -500 to -700 so the .tier-badge disks
     in "worth flagging for you", .ingredient-row left-border accents,
     and .meal-component-tier chips all use the SAME color values as
     .ingredient-glance-chip text + .legend-row text (which are -700).
     Per user: "the colors are different... I would like this to be
     consistent between all of these areas." One palette across every
     tier-coded surface on the verdict screen. (Moderate-good = #4d7c0f
     matches the hand-coded -700 already used in the chip/legend rules
     since there's no --health-moderate-good-700 var defined.) */
  --tier-good:           var(--health-good-700);
  --tier-moderate-good:  #4d7c0f;
  --tier-neutral:        var(--health-caution-700);
  --tier-moderate-bad:   var(--health-warn-700);
  --tier-bad:            var(--health-bad-700);

  --shadow-sm:  0 1px 2px rgba(40, 30, 20, 0.05);
  --shadow-md:  0 4px 14px rgba(40, 30, 20, 0.08);
  --shadow-lg:  0 12px 32px rgba(40, 30, 20, 0.10);
  --shadow-glow: 0 0 32px rgba(112, 203, 208, 0.30);   /* v2.50 — teal-tinted glow */

  --radius-sm: 8px;
  --radius:    14px;
  --radius-lg: 20px;
  --radius-xl: 28px;
}

/* ============================================================
   v3.91 — Dark mode (Stage 1 foundation)
   ============================================================
   Follows the phone's system setting automatically — no in-app toggle,
   per product direction ("just follow the phone"). Remaps ONLY the shared
   neutrals + semantic surface tokens + light accent-tint backgrounds +
   shadows. The brand accent HUES (teal/purple) and the health-meaning tier
   colors are left alone — dark mode is the canvas, the brand stays the brand,
   and a Grade-A green still reads as trusted green. Because ~745 CSS surfaces
   already draw from these vars (and the 44 former `background: white` cards
   now use var(--bg-surface)), remapping here flips most of the app at once.

   Stage 2 (separate ship) sweeps the remaining hardcoded inline colors in
   js/app.js + the ~30 hardcoded text/bg hexes still in this file. Until then
   a few spots may stay light — tracked, not forgotten. */
@media (prefers-color-scheme: dark) {
  /* v3.93 — System mode honors the phone, UNLESS the user forced Light in
     Settings (data-color-mode="light" on <html>). Forced Dark is handled by
     the separate [data-color-mode="dark"] block below so it works on a
     light phone too. */
  :root:not([data-color-mode="light"]) {
    /* Warm-neutral dark canvas — keeps the brand's warmth, not cold gray. */
    --cream-50:   #16191b;   /* app background — calm cool charcoal (v3.99, was warm #17150f) */
    --cream-100:  #1c2023;   /* slightly raised wash */
    --cream-200:  #2a2f33;   /* borders / dividers */
    --cream-300:  #383e43;
    --bg-app:     #16191b;
    --bg-surface: #1e2224;   /* cards: a touch lighter than app bg = elevation */

    /* Ink scale inverts: darkest-text token becomes lightest text. */
    --ink-900: #eef1f0;   /* headings — soft cool white (v3.99) */
    --ink-700: #c9cfd0;   /* body text */
    --ink-500: #98a0a2;   /* muted text — still AA on the dark canvas */
    --ink-300: #5f676a;

    /* Light accent-tint backgrounds → dark tints; deep accent text → light. */
    --green-50:  #10211f;
    --green-100: #163530;
    --green-700: #8fd6da;   /* was deep-teal-on-light → now light-on-dark */
    --coral-50:  #21142a;
    --coral-100: #2f1c3d;
    --coral-700: #c9a8e0;   /* was deep-purple-on-light → now light-on-dark */

    /* Soft status tints (amber/rose) darken so their text stays readable. */
    --amber-50:  #2a2008;
    --rose-50:   #2a1413;

    /* v3.99 — Health/tier tint backgrounds darken too. These back the colored
       glance-chips, history tags, and legend swatches; un-remapped they stayed
       light islands with dark text. Paired with the lightened tier TEXT
       overrides below. */
    --health-good-50:    #122a1f;
    --health-good-100:   #163a2a;
    --health-caution-50: #2a2206;
    --health-warn-50:    #2a1605;
    --health-bad-50:     #2a1313;

    /* Shadows deepen so elevation still reads on a dark background. */
    --shadow-sm:  0 1px 3px rgba(0,0,0,0.45), 0 1px 2px rgba(0,0,0,0.30);
    --shadow-md:  0 4px 14px rgba(0,0,0,0.50);
    --shadow-lg:  0 12px 32px rgba(0,0,0,0.60);

    /* color-scheme tells the browser to render form controls, scrollbars,
       and the address bar in dark variants too. */
    color-scheme: dark;
  }

  /* v3.92 — Targeted dark overrides for surfaces that deliberately use hard
     color literals in light mode (so a theme remap can't reintroduce the old
     transparency bug). Light mode keeps those literals byte-for-byte; these
     apply only when the phone is in dark mode. --bg-surface is already a solid
     dark color here, so there's no transparency risk.

     .overlay-inner = every modal (first-pattern, read-only paywall, trial-
     extension gift, etc.) — without this they'd be white cards with dark text
     floating over the dark app. .picker-mic-btn = the voice mic button on the
     conditions/diets search. */
  .overlay-inner {
    background: var(--bg-surface);
    color: var(--ink-900);
    border-color: var(--cream-200);
  }
  .overlay-inner h2 { color: var(--ink-900); }
  .overlay-inner p  { color: var(--ink-700); }
  .picker-mic-btn {
    background: var(--bg-surface);
    border-color: var(--cream-200);
    color: #5fc7cd;   /* brighter teal mic icon, readable on dark */
  }

  /* v3.98 — Readability sweep. These selectors set DARK color literals tuned
     for light surfaces, but their backgrounds already flip dark in this mode
     (var(--bg-surface) / --amber-50 / --cream-*), so the text would land
     dark-on-dark and vanish — the exact "unreadable in dark mode" bug. Lift
     each to a light / brightened tone. Gated by :not([data-color-mode="light"])
     so a forced-Light choice on a dark phone still wins. KEEP IN SYNC with the
     forced-Dark mirror below. */
  :root:not([data-color-mode="light"]) .terms-pair-yes { background: #142420; border-color: #28463a; }
  :root:not([data-color-mode="light"]) .terms-pair-no  { background: #251515; border-color: #4a2424; }
  :root:not([data-color-mode="light"]) .terms-alert    { background: #241c08; border-color: #5a4612; }
  :root:not([data-color-mode="light"]) .terms-pair-yes .terms-pair-title { color: #74d99b; }
  :root:not([data-color-mode="light"]) .terms-pair-no  .terms-pair-title { color: #f0a0a0; }
  :root:not([data-color-mode="light"]) .terms-alert-title { color: #f0c987; }
  :root:not([data-color-mode="light"]) .terms-alert-item strong { color: #f0c987; }
  :root:not([data-color-mode="light"]) .ocr-banner-icon { color: #5fc7cd; }
  :root:not([data-color-mode="light"]) .scanlog-entry-head,
  :root:not([data-color-mode="light"]) .scanlog-entry-detail,
  :root:not([data-color-mode="light"]) .scanlog-entry-label,
  :root:not([data-color-mode="light"]) .scanlog-empty { color: var(--ink-500); }
  :root:not([data-color-mode="light"]) .scanlog-entry-tag { background: var(--cream-200); color: var(--ink-700); }
  :root:not([data-color-mode="light"]) .scanlog-entry-text { background: var(--cream-100); color: var(--ink-700); }

  /* v3.99 — Fine-detail / eyebrow readability. Accent-colored small text
     (teal/amber/rose/health-tier) uses tokens that AREN'T remapped for dark
     because they double as solid pill backgrounds elsewhere — so used as TEXT
     they landed dark-on-dark and vanished (the eyebrows the user flagged).
     Lift each to a light/brightened tone. The two hardcoded light-gradient
     cards (Today Pro pill, early-patterns) also get a dark surface so their
     now-light body text stops vanishing. KEEP IN SYNC with the forced-Dark
     mirror below. */
  :root:not([data-color-mode="light"]) .nudge-toast-title { color: #5fc7cd; }
  :root:not([data-color-mode="light"]) .early-patterns-eyebrow { color: #5fc7cd; }
  :root:not([data-color-mode="light"]) .watching-symptom-label strong { color: #f0c987; }
  :root:not([data-color-mode="light"]) .day-verdict-flare-note { color: #f0a878; }
  :root:not([data-color-mode="light"]) .insight-chip-trigger { color: #f0a0a0; }
  :root:not([data-color-mode="light"]) .insight-chip-watching { color: #f0c987; }
  :root:not([data-color-mode="light"]) .ingredient-flagged-aip,
  :root:not([data-color-mode="light"]) .ingredient-flagged-goal { color: #f0c987; }
  :root:not([data-color-mode="light"]) .history-tag.safe { color: #74d99b; }
  :root:not([data-color-mode="light"]) .history-tag.fav { color: #f0c987; }
  :root:not([data-color-mode="light"]) .legend-row.tier-good,
  :root:not([data-color-mode="light"]) .ingredient-glance-chip.tier-good { color: #74d99b; }
  :root:not([data-color-mode="light"]) .legend-row.tier-moderate_good,
  :root:not([data-color-mode="light"]) .ingredient-glance-chip.tier-moderate_good { color: #a3d977; background: #1e2a10; }
  :root:not([data-color-mode="light"]) .legend-row.tier-neutral,
  :root:not([data-color-mode="light"]) .ingredient-glance-chip.tier-neutral { color: #e6c463; }
  :root:not([data-color-mode="light"]) .legend-row.tier-moderate_bad,
  :root:not([data-color-mode="light"]) .ingredient-glance-chip.tier-moderate_bad { color: #f0a878; }
  :root:not([data-color-mode="light"]) .legend-row.tier-bad,
  :root:not([data-color-mode="light"]) .ingredient-glance-chip.tier-bad { color: #f0a0a0; }
  :root:not([data-color-mode="light"]) .today-pro-pill { background: #1a2a2b; border-color: #2c5c60; }
  :root:not([data-color-mode="light"]) .today-pro-pill-text strong,
  :root:not([data-color-mode="light"]) .today-pro-pill-arrow { color: #5fc7cd; }
  :root:not([data-color-mode="light"]) .early-patterns-card { background: #1a2a2b; }

  /* v3.99 — Calm dark canvas. The old dark background carried over the light
     theme's two corner glows; in dark the coral one rendered as a harsh purple
     wash. Replace both with a single, very faint teal glow on the cool-charcoal
     field so the screen reads calm and on-brand (no purple). */
  :root:not([data-color-mode="light"]) body {
    background:
      radial-gradient(at 100% 0%, rgba(95,199,205,0.05) 0%, transparent 55%),
      var(--cream-50);
  }
}

/* ============================================================
   v3.93 — Forced Dark (user picked "Dark" in Settings)
   ============================================================
   Applies the SAME dark canvas as the @media block above, but keyed on the
   data-color-mode="dark" attribute (set on <html> by Prefs.applyColorMode),
   so it works regardless of the phone's system setting. KEEP THESE VALUES IN
   SYNC with the @media (prefers-color-scheme: dark) block above — they are
   intentionally identical; only the trigger differs (phone setting vs. the
   user's explicit choice). "Auto" mode removes the attribute and falls back
   to the @media rule; "Light" sets data-color-mode="light", which the @media
   rule excludes via :not(), so a Light choice wins even on a dark phone. */
:root[data-color-mode="dark"] {
  --cream-50:   #16191b;
  --cream-100:  #1c2023;
  --cream-200:  #2a2f33;
  --cream-300:  #383e43;
  --bg-app:     #16191b;
  --bg-surface: #1e2224;
  --ink-900: #eef1f0;
  --ink-700: #c9cfd0;
  --ink-500: #98a0a2;
  --ink-300: #5f676a;
  --green-50:  #10211f;
  --green-100: #163530;
  --green-700: #8fd6da;
  --coral-50:  #21142a;
  --coral-100: #2f1c3d;
  --coral-700: #c9a8e0;
  --amber-50:  #2a2008;
  --rose-50:   #2a1413;
  --health-good-50:    #122a1f;
  --health-good-100:   #163a2a;
  --health-caution-50: #2a2206;
  --health-warn-50:    #2a1605;
  --health-bad-50:     #2a1313;
  --shadow-sm:  0 1px 3px rgba(0,0,0,0.45), 0 1px 2px rgba(0,0,0,0.30);
  --shadow-md:  0 4px 14px rgba(0,0,0,0.50);
  --shadow-lg:  0 12px 32px rgba(0,0,0,0.60);
  color-scheme: dark;
}
:root[data-color-mode="dark"] .overlay-inner {
  background: var(--bg-surface);
  color: var(--ink-900);
  border-color: var(--cream-200);
}
:root[data-color-mode="dark"] .overlay-inner h2 { color: var(--ink-900); }
:root[data-color-mode="dark"] .overlay-inner p  { color: var(--ink-700); }
:root[data-color-mode="dark"] .picker-mic-btn {
  background: var(--bg-surface);
  border-color: var(--cream-200);
  color: #5fc7cd;
}

/* v3.98 — Readability sweep (forced Dark). Mirror of the rules in the
   @media (prefers-color-scheme: dark) block above; KEEP IN SYNC. */
:root[data-color-mode="dark"] .terms-pair-yes { background: #142420; border-color: #28463a; }
:root[data-color-mode="dark"] .terms-pair-no  { background: #251515; border-color: #4a2424; }
:root[data-color-mode="dark"] .terms-alert    { background: #241c08; border-color: #5a4612; }
:root[data-color-mode="dark"] .terms-pair-yes .terms-pair-title { color: #74d99b; }
:root[data-color-mode="dark"] .terms-pair-no  .terms-pair-title { color: #f0a0a0; }
:root[data-color-mode="dark"] .terms-alert-title { color: #f0c987; }
:root[data-color-mode="dark"] .terms-alert-item strong { color: #f0c987; }
:root[data-color-mode="dark"] .ocr-banner-icon { color: #5fc7cd; }
:root[data-color-mode="dark"] .scanlog-entry-head,
:root[data-color-mode="dark"] .scanlog-entry-detail,
:root[data-color-mode="dark"] .scanlog-entry-label,
:root[data-color-mode="dark"] .scanlog-empty { color: var(--ink-500); }
:root[data-color-mode="dark"] .scanlog-entry-tag { background: var(--cream-200); color: var(--ink-700); }
:root[data-color-mode="dark"] .scanlog-entry-text { background: var(--cream-100); color: var(--ink-700); }

/* v3.99 — Fine-detail / eyebrow readability (forced Dark). Mirror of the
   rules in the @media (prefers-color-scheme: dark) block above. KEEP IN SYNC. */
:root[data-color-mode="dark"] .nudge-toast-title { color: #5fc7cd; }
:root[data-color-mode="dark"] .early-patterns-eyebrow { color: #5fc7cd; }
:root[data-color-mode="dark"] .watching-symptom-label strong { color: #f0c987; }
:root[data-color-mode="dark"] .day-verdict-flare-note { color: #f0a878; }
:root[data-color-mode="dark"] .insight-chip-trigger { color: #f0a0a0; }
:root[data-color-mode="dark"] .insight-chip-watching { color: #f0c987; }
:root[data-color-mode="dark"] .ingredient-flagged-aip,
:root[data-color-mode="dark"] .ingredient-flagged-goal { color: #f0c987; }
:root[data-color-mode="dark"] .history-tag.safe { color: #74d99b; }
:root[data-color-mode="dark"] .history-tag.fav { color: #f0c987; }
:root[data-color-mode="dark"] .legend-row.tier-good,
:root[data-color-mode="dark"] .ingredient-glance-chip.tier-good { color: #74d99b; }
:root[data-color-mode="dark"] .legend-row.tier-moderate_good,
:root[data-color-mode="dark"] .ingredient-glance-chip.tier-moderate_good { color: #a3d977; background: #1e2a10; }
:root[data-color-mode="dark"] .legend-row.tier-neutral,
:root[data-color-mode="dark"] .ingredient-glance-chip.tier-neutral { color: #e6c463; }
:root[data-color-mode="dark"] .legend-row.tier-moderate_bad,
:root[data-color-mode="dark"] .ingredient-glance-chip.tier-moderate_bad { color: #f0a878; }
:root[data-color-mode="dark"] .legend-row.tier-bad,
:root[data-color-mode="dark"] .ingredient-glance-chip.tier-bad { color: #f0a0a0; }
:root[data-color-mode="dark"] .today-pro-pill { background: #1a2a2b; border-color: #2c5c60; }
:root[data-color-mode="dark"] .today-pro-pill-text strong,
:root[data-color-mode="dark"] .today-pro-pill-arrow { color: #5fc7cd; }
:root[data-color-mode="dark"] .early-patterns-card { background: #1a2a2b; }

/* v3.99 — Calm dark canvas (forced Dark mirror). KEEP IN SYNC with @media. */
:root[data-color-mode="dark"] body {
  background:
    radial-gradient(at 100% 0%, rgba(95,199,205,0.05) 0%, transparent 55%),
    var(--cream-50);
}

/* ----- Reset & base ----- */
*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; padding: 0; min-height: 100%; }

/* Lock horizontal scroll + pinch-zoom but KEEP vertical scrolling fully
   functional. iOS is finicky here — extra body rules (position:relative,
   width:100%) can accidentally break vertical scroll, so we keep this
   minimal: html clips horizontal, body stays as the natural scroll
   container, screens are width-capped to defend against runaway elements. */
html {
  touch-action: pan-y;             /* only vertical pan/scroll gestures */
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  overflow-x: hidden;
  overscroll-behavior-x: none;
  max-width: 100vw;
}
body {
  overscroll-behavior-y: none;     /* no vertical bounce */
  -webkit-overflow-scrolling: touch;
  max-width: 100vw;
}
.screen {
  max-width: 100vw;
  overflow-x: hidden;
}

body {
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  background:
    radial-gradient(at 0% 0%, var(--coral-50) 0%, transparent 40%),
    radial-gradient(at 100% 100%, var(--green-50) 0%, transparent 40%),
    var(--cream-50);
  background-attachment: fixed;
  color: var(--ink-900);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  font-size: 16px;
  min-height: 100vh;
}

h1, h2, h3, .display { font-family: 'Fraunces', Georgia, serif; font-weight: 700; }

/* ============================================================
   Screens
   ============================================================ */
.screen { display: none; min-height: 100vh; padding-bottom: 3rem; animation: fadeIn 0.3s ease; }
.screen.active { display: block; }

@keyframes fadeIn {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* ============================================================
   Hero (onboarding)
   ============================================================ */
.hero {
  position: relative;
  background:
    radial-gradient(at 30% 0%, var(--green-700) 0%, transparent 60%),
    linear-gradient(160deg, var(--green-500) 0%, var(--green-700) 100%);
  color: white;
  padding: 3.5rem 1.5rem 4rem;
  text-align: center;
  overflow: hidden;
  border-bottom-left-radius: 40px 24px;
  border-bottom-right-radius: 40px 24px;
}
.hero::before {
  /* subtle leaf pattern overlay */
  content: '';
  position: absolute; inset: 0;
  background-image:
    radial-gradient(circle at 15% 20%, rgba(255,255,255,0.08) 0%, transparent 40%),
    radial-gradient(circle at 85% 70%, rgba(249,124,91,0.18) 0%, transparent 50%);
  pointer-events: none;
}
/* v2.40 — hero now uses an <img> for the new brand logo. Sized up from
   56px to 96px since the new mark carries more identity per pixel
   (square logo with V + brackets vs. abstract leaf). Rounded corners
   match the icon's own corner radius; soft shadow gives elevation
   against the hero's green gradient so it doesn't blend. */
.hero-logo {
  margin: 0 auto 1rem;
  display: block;
  width: 96px;
  height: 96px;
  border-radius: 20px;
  filter: drop-shadow(0 6px 18px rgba(0,0,0,0.25));
}
.hero h1 {
  font-size: 2.5rem;
  margin: 0 0 0.6rem;
  line-height: 1.1;
  letter-spacing: -0.02em;
  position: relative;
  font-weight: 900;
}
.hero .tagline {
  margin: 0;
  font-size: 1.05rem;
  opacity: 0.95;
  position: relative;
  font-weight: 400;
  max-width: 22rem;
  margin-left: auto;
  margin-right: auto;
}
.hero em { font-style: italic; font-weight: 700; color: var(--coral-100); }

/* ============================================================
   Topbar (sub-pages)
   ============================================================ */
.topbar {
  display: flex;
  align-items: center;
  background: linear-gradient(135deg, var(--green-500), var(--green-700));
  /* v2.56 — Use the theme's on-primary color (purple in the default
     teal theme; white in every dark-primary theme). See --on-primary
     in :root. */
  color: var(--on-primary);
  padding: 0.875rem 1rem;
  position: sticky;
  top: 0;
  z-index: 10;
  box-shadow: var(--shadow-sm);
}
.topbar .app-title {
  font-size: 1.3rem;
  margin: 0;
  text-align: center;
  flex: 1;
  font-weight: 700;
  font-family: 'Fraunces', Georgia, serif;
  line-height: 1.15;
  letter-spacing: -0.005em;
}
.topbar .spacer { width: 2.75rem; }

/* Home brand topbar — left-anchored leaf + wordmark, right-anchored
   profile avatar + kebab. The brand block is intentionally a WHITE pill
   with brand-green contents that NEVER follow the theme — the wordmark
   and leaf are the app's identity and should look the same whether the
   user is on Forest, Royal, Rose, or anything else. (Same philosophy as
   the locked --health-* grade colors.) */
.topbar-brand {
  gap: 0.5rem;
  padding: 0.55rem 0.75rem;
}
/* v2.40 — White pill dropped. The new icon.png is itself a green-square
   logo with its own visual frame, so wrapping it in a white pill created
   nested backgrounds. The logo sits directly on the topbar's green
   gradient; the wordmark next to it switched to white so it reads
   against the same gradient. */
.topbar-brand .brand-block {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-right: auto;       /* pushes right-side buttons to the edge */
  min-width: 0;
  padding: 0.1rem 0;
}
.topbar-brand .brand-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: 10px;
  overflow: hidden;
  flex-shrink: 0;
  box-shadow: 0 1px 3px rgba(0,0,0,0.18);   /* subtle edge definition against the topbar gradient */
}
.topbar-brand .brand-icon img {
  width: 100%;
  height: 100%;
  display: block;
  object-fit: cover;
}
/* Back-compat for any remaining <svg> uses that might surface i-leaf. */
.topbar-brand .brand-icon svg {
  width: 32px;
  height: 32px;
  stroke-width: 2;
}
.topbar-brand .brand-wordmark {
  font-family: 'Fraunces', Georgia, serif;
  font-weight: 700;
  font-size: 1.3rem;
  line-height: 1.1;
  letter-spacing: -0.01em;
  color: var(--on-primary);  /* v2.56 — theme-aware (purple on teal default; white on dark-primary themes) */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Bare icon-btn — kebab on home should sit on the topbar with no tile
   background. Hover gives a subtle wash but no permanent circle. */
.icon-btn-bare {
  background: transparent;
}
.icon-btn-bare:hover { background: rgba(255,255,255,0.15); }
.icon-btn-bare svg { width: 26px; height: 26px; }

/* Compact profile pill — drops the name to avoid 'Me' / Settings being
   two right-side widgets competing for the eye. Avatar alone is enough
   identity; the kebab next to it is the settings entry. */
.profile-pill-compact { padding: 0.2rem; gap: 0; background: transparent; }
.profile-pill-compact:hover { background: rgba(255,255,255,0.18); }
.profile-pill-name-hidden { display: none !important; }
/* When 2+ profiles exist, the multi-profile pill rule below adds back
   the ⇄ swap glyph; we also restore a subtle background so it reads as
   tappable. Name stays hidden — the avatar + swap glyph is enough. */
body.has-multiple-profiles .profile-pill-compact {
  background: rgba(255,255,255,0.22);
  padding: 0.25rem 0.55rem 0.25rem 0.3rem;
}

.icon-btn {
  background: rgba(255,255,255,0.12);
  border: none;
  color: white;
  width: 48px;            /* must match min-height so the circle stays round */
  height: 48px;
  min-width: 48px;
  border-radius: 50%;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background 0.15s ease, transform 0.05s ease;
}
.icon-btn:hover { background: rgba(255,255,255,0.22); }
.icon-btn:active { transform: scale(0.94); }
.icon-btn svg { width: 22px; height: 22px; }

/* ============================================================
   Cards
   ============================================================ */
.card {
  background: var(--bg-surface);
  border-radius: var(--radius);
  margin: 1rem;
  padding: 1.5rem;
  box-shadow: var(--shadow-sm);
  animation: cardIn 0.35s cubic-bezier(0.2, 0.7, 0.2, 1);
}
@keyframes cardIn {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: translateY(0); }
}
.card h2 {
  margin: 0 0 0.4rem;
  font-size: 1.4rem;
  letter-spacing: -0.01em;
  color: var(--ink-900);
}

/* ============================================================
   Typography helpers
   ============================================================ */
.muted { color: var(--ink-500); }
/* `.small` is the most-used secondary-text class in the app. Bumped to
   --text-secondary (~0.95rem) so it's readable for elderly eyes. True
   asides should use `.caption` (--text-caption, 0.875rem) instead. */
.small   { font-size: var(--text-secondary); }
.caption { font-size: var(--text-caption); }
.field-label {
  display: block;
  font-weight: 600;
  margin: 1.25rem 0 0.5rem;
  font-size: var(--text-secondary);
  color: var(--ink-700);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

/* ============================================================
   Buttons
   ============================================================ */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  padding: 0.85rem 1.25rem;
  border-radius: 999px;
  border: none;
  font-family: inherit;
  font-size: 0.98rem;
  font-weight: 600;
  cursor: pointer;
  transition: transform 0.08s ease, box-shadow 0.18s ease, background 0.15s ease;
  text-align: center;
  text-decoration: none;
  line-height: 1.2;
}
.btn:active { transform: translateY(1px) scale(0.985); }
.btn:disabled { opacity: 0.45; cursor: not-allowed; }
.btn-primary {
  background: linear-gradient(135deg, var(--green-500), var(--green-700));
  /* v2.56 — Theme-aware on-primary foreground. Default teal theme
     yields purple; dark-primary themes yield white. */
  color: var(--on-primary);
  box-shadow: 0 6px 16px rgba(45, 134, 98, 0.32);
}
.btn-primary:hover:not(:disabled) { box-shadow: 0 8px 22px rgba(45, 134, 98, 0.42); }
.btn-secondary {
  background: var(--cream-100);
  color: var(--ink-700);
}
.btn-secondary:hover:not(:disabled) { background: var(--cream-200); }

/* Onboarding "Myself / Someone I care for" picker. Uses the theme primary
   (--green-500, which is overridden by body.theme-* for purple/teal/coral
   etc.) so the buttons match whatever look the user has picked. Default
   state is outlined in theme; selected state fills solid theme + white
   text — high-contrast and immediately readable across all themes.
   Specificity .btn.onboarding-for-btn (0,2,0) beats .btn-secondary (0,1,0)
   so these rules win without !important. */
.btn.onboarding-for-btn {
  background: transparent;
  border: 2px solid var(--green-500);
  color: var(--green-700);
  transition: background 0.15s ease, color 0.15s ease;
}
.btn.onboarding-for-btn:hover:not(:disabled) {
  background: var(--green-50);
}
.btn.onboarding-for-btn.selected {
  background: var(--green-500);
  color: #ffffff;
  border-color: var(--green-500);
}
.btn.onboarding-for-btn.selected:hover:not(:disabled) {
  background: var(--green-700);
  border-color: var(--green-700);
}
.btn-coral {
  background: linear-gradient(135deg, var(--coral-500), var(--coral-700));
  color: white;
  box-shadow: 0 6px 16px rgba(249, 124, 91, 0.32);
}
.btn-block {
  display: flex;
  width: 100%;
  margin-top: 1.25rem;
}
.btn-row {
  display: flex;
  gap: 0.5rem;
  margin-top: 0.75rem;
  flex-wrap: wrap;
}
.btn-row .btn { flex: 1; min-width: 140px; }

/* ============================================================
   Chips (condition selection)
   ============================================================ */
.chip-group {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-top: 0.75rem;
}
.chip {
  display: inline-flex;
  align-items: center;
  padding: 0.6rem 1rem;
  border-radius: 999px;
  background: var(--cream-100);
  border: 2px solid transparent;
  color: var(--ink-700);
  cursor: pointer;
  font-size: 0.95rem;
  font-family: inherit;
  line-height: 1.2;
  transition: all 0.18s cubic-bezier(0.2, 0.7, 0.2, 1);
  user-select: none;
  -webkit-tap-highlight-color: transparent;   /* kills iOS tap flash */
  touch-action: manipulation;                  /* disables 300ms tap delay */
  appearance: none;                            /* reset native <button> chrome */
  -webkit-appearance: none;
}
.chip:focus-visible {
  outline: 3px solid var(--green-500);
  outline-offset: 2px;
}
.chip:hover { background: var(--cream-200); transform: translateY(-1px); }
.chip.selected {
  background: var(--green-50);
  border-color: var(--green-500);
  color: var(--green-700);
  font-weight: 600;
  box-shadow: 0 4px 12px rgba(45, 134, 98, 0.18);
}

/* ============================================================
   Scan mode buttons (Home)
   ============================================================ */
.scan-modes {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.75rem;
  margin-top: 1rem;
}

/* Compact row used on the home screen so all mode buttons + scan-type
   toggle fit on a typical phone screen without scrolling. Column count is
   set inline (3 buttons today) so this rule does not fight the markup. */
.scan-modes-compact {
  gap: 0.5rem !important;
  width: 100%;
}
.scan-modes-compact .mode-btn {
  padding: 0.7rem 0.25rem;
  min-height: 80px;
  width: 100%;
}
.scan-modes-compact .mode-icon {
  width: 36px;
  height: 36px;
  margin-bottom: 0.35rem;
}
.scan-modes-compact .mode-icon svg { width: 18px; height: 18px; }
.scan-modes-compact .mode-label {
  font-size: 0.82rem;
  font-weight: 600;
}
/* v2.80 — Subtitle under each mode chip explains when it's the right
   choice. Sized small so the chips don't grow vertically; line-height
   tight so two-word subtitles don't wrap awkwardly. */
.scan-modes-compact .mode-desc {
  font-size: 0.68rem;
  font-weight: 500;
  color: var(--ink-500);
  line-height: 1.15;
  margin-top: 0.15rem;
  padding: 0 0.1rem;
  text-align: center;
}
.scan-modes-compact .mode-btn {
  /* Slightly taller now that there's a subtitle — keeps icon + label
     + desc all visible without text being cramped. */
  min-height: 96px;
}
/* v2.80 — Camera is the headline mode. Subtle teal ring + soft glow
   to flag it as the new go-to without overriding the .active treatment
   that fires when the user actually selects it. */
.scan-modes-compact .mode-btn-headline {
  border-color: var(--primary, #70cbd0);
  box-shadow: 0 0 0 1px var(--primary, #70cbd0) inset, var(--shadow-sm);
}
.scan-modes-compact .mode-btn-headline .mode-icon {
  color: var(--primary, #70cbd0);
}
.mode-btn {
  background: var(--cream-50);
  border: 2px solid var(--cream-200);
  border-radius: var(--radius);
  padding: 1.25rem 0.75rem;
  cursor: pointer;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  font-family: inherit;
  transition: all 0.18s cubic-bezier(0.2, 0.7, 0.2, 1);
}
.mode-btn:hover {
  background: var(--green-50);
  border-color: var(--green-300);
  transform: translateY(-2px);
  box-shadow: var(--shadow-md);
}
.mode-btn.active {
  background: var(--green-50);
  border-color: var(--green-500);
}
.mode-icon {
  font-size: 1.6rem;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: var(--bg-surface);
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 0.5rem;
  box-shadow: var(--shadow-sm);
  color: var(--green-700);
}
.mode-icon svg { width: 22px; height: 22px; }
.mode-label { font-weight: 600; font-size: 0.95rem; color: var(--ink-900); }
.mode-desc { font-size: 0.8rem; color: var(--ink-500); margin-top: 0.125rem; }

.mode-panel { display: none; animation: cardIn 0.3s ease; }
.mode-panel.active { display: block; }

/* ============================================================
   Form controls
   ============================================================ */
textarea, input[type="text"], input[type="number"] {
  width: 100%;
  padding: 0.875rem;
  border: 2px solid var(--cream-200);
  border-radius: var(--radius-sm);
  font-family: inherit;
  font-size: 1rem;
  background: var(--cream-50);
  resize: vertical;
  transition: border 0.15s ease, background 0.15s ease;
}
textarea:focus, input[type="text"]:focus, input[type="number"]:focus {
  outline: none;
  border-color: var(--green-500);
  background: var(--bg-surface);
}
input[type="file"] {
  display: block;
  width: 100%;
  padding: 0.5rem;
  font-family: inherit;
}

/* ============================================================
   Camera/video
   ============================================================ */
.video-wrap {
  background: #111;
  border-radius: var(--radius);
  overflow: hidden;
  margin-top: 0.75rem;
  aspect-ratio: 4 / 3;
  position: relative;
}
.video-wrap video { width: 100%; height: 100%; object-fit: cover; display: block; }

/* ============================================================
   Progress overlay
   ============================================================ */
.overlay {
  position: fixed; inset: 0;
  background: rgba(20, 15, 10, 0.55);
  backdrop-filter: blur(4px);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 100;
  animation: fadeIn 0.18s ease;
}
.overlay-content {
  background: var(--bg-surface);
  padding: 2.5rem 2rem;
  border-radius: var(--radius-lg);
  text-align: center;
  max-width: 90%;
  min-width: 260px;
  box-shadow: var(--shadow-lg);
}

/* v3.58 — .overlay-inner had NO rule, so every modal using it
   (first-pattern "look what your data found", read-only paywall,
   trial-extension gift, etc.) rendered with a TRANSPARENT body —
   dark text over whatever was behind it, which is the hard-to-read
   "matched you" popup the user reported. Give it a solid, theme-safe
   card so its text is always legible regardless of theme. Hard color
   literals so a theme remap can't reintroduce the transparency. */
.overlay-inner {
  background: #ffffff;
  color: #1f1d1a;
  width: 100%;
  max-width: 460px;
  margin: 1.25rem;
  border-radius: 16px;
  border: 1px solid #e7ddcb;
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.28);
  max-height: 90vh;
  overflow-y: auto;
}
.overlay-inner h2 { color: #1f1d1a; }
.overlay-inner p  { color: #4a463f; }

/* v3.58 — Indeterminate progress bar for the scan overlay. The fill
   slides left→right on a CSS transform (GPU compositor thread), so it
   keeps animating smoothly even while OCR pegs the main thread — the
   round spinner can visually freeze under that load, which is why the
   circle "looked like it should move but didn't." */
.progress-indeterminate {
  width: 200px;
  max-width: 70vw;
  height: 6px;
  margin: 0.85rem auto 0;
  background: var(--cream-200, #ede4d3);
  border-radius: 999px;
  overflow: hidden;
}
.progress-indeterminate-fill {
  width: 40%;
  height: 100%;
  border-radius: 999px;
  background: var(--green-500, #70cbd0);
  animation: progress-indeterminate-slide 1.1s ease-in-out infinite;
}
@keyframes progress-indeterminate-slide {
  0%   { transform: translateX(-120%); }
  100% { transform: translateX(320%); }
}
body.reduce-motion .progress-indeterminate-fill { animation: none; width: 100%; }
.spinner {
  width: 44px;
  height: 44px;
  border: 4px solid var(--cream-200);
  border-top-color: var(--green-500);
  border-radius: 50%;
  margin: 0 auto 1rem;
  animation: spin 0.9s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* ============================================================
   Results — Grade card with circular ring
   ============================================================ */
.grade-card {
  margin: 1rem;
  border-radius: var(--radius-xl);
  padding: 2rem 1.5rem 1.75rem;
  text-align: center;
  position: relative;
  overflow: hidden;
  color: white;
  animation: gradeIn 0.55s cubic-bezier(0.18, 0.7, 0.18, 1);
  box-shadow: var(--shadow-md);
}
@keyframes gradeIn {
  from { opacity: 0; transform: scale(0.92); }
  to { opacity: 1; transform: scale(1); }
}
/* Grade card backgrounds use the THEME-PROOF --health-* vars. The previous
   version used var(--green-*) which the slate/royal/etc themes remap for
   branding — meaning Grade A would show as gray (slate) or purple (royal).
   Grade colors carry meaning ("green = good for you") and must never bend
   to brand themes. */
.grade-card.grade-A { background: linear-gradient(135deg, var(--health-good-500) 0%, var(--health-good-700) 100%); }
.grade-card.grade-B { background: linear-gradient(135deg, var(--health-lime-500) 0%, var(--health-good-500) 100%); }
.grade-card.grade-C { background: linear-gradient(135deg, var(--health-caution-500) 0%, var(--health-caution-700) 100%); }
.grade-card.grade-D { background: linear-gradient(135deg, var(--health-warn-500) 0%, var(--health-warn-700) 100%); }
.grade-card.grade-F { background: linear-gradient(135deg, var(--health-bad-500) 0%, var(--health-bad-700) 100%); }
/* Fallback for unscored results (grade '?') */
.grade-card { background: linear-gradient(135deg, #6b6357 0%, #3d3a36 100%); }
.grade-card::after {
  /* subtle glow ring */
  content: '';
  position: absolute;
  top: -40%; right: -20%;
  width: 250px; height: 250px;
  border-radius: 50%;
  background: rgba(255,255,255,0.08);
  pointer-events: none;
}

.grade-ring-wrap {
  position: relative;
  width: 180px;
  height: 180px;
  margin: 0 auto 0.75rem;
}
.grade-ring-wrap svg {
  width: 100%;
  height: 100%;
  transform: rotate(-90deg);
}
.grade-ring-track {
  fill: none;
  stroke: rgba(255,255,255,0.18);
  stroke-width: 12;
}
.grade-ring-fill {
  fill: none;
  stroke: white;
  stroke-width: 12;
  stroke-linecap: round;
  filter: drop-shadow(0 0 8px rgba(255,255,255,0.4));
  transition: stroke-dashoffset 1.1s cubic-bezier(0.18, 0.7, 0.18, 1);
}
.grade-ring-inner {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}
.grade-score-big {
  font-family: 'Fraunces', Georgia, serif;
  font-weight: 900;
  font-size: 3.4rem;
  line-height: 1;
  letter-spacing: -0.04em;
  margin: 0;
}
.grade-score-of {
  font-size: var(--text-secondary);   /* was 0.85rem */
  opacity: 0.95;                       /* up from 0.85 */
  margin: 0;
  letter-spacing: 0.05em;
  text-transform: uppercase;
}
/* The letter pill ("Grade A") was 0.78rem with a translucent background
   that read as low-contrast over the gradient. Bumped to body size, made
   the background a solid white, and used the card's accent color for the
   letter — Pillar 3 wants this VERY readable. */
.grade-letter-pill {
  display: inline-block;
  margin-top: 0.4rem;
  padding: 0.3rem 0.85rem;
  background: var(--bg-surface);
  color: var(--ink-900);
  border-radius: 999px;
  font-size: var(--text-body);
  font-weight: 700;
  letter-spacing: 0.06em;
  box-shadow: 0 2px 6px rgba(0,0,0,0.15);
}

.grade-verdict {
  font-family: 'Fraunces', Georgia, serif;
  font-size: 1.55rem;
  font-weight: 700;
  margin: 0.6rem 0 0.25rem;
  letter-spacing: -0.01em;
}
.grade-subverdict {
  font-size: var(--text-large);        /* was 0.95rem — pillar 4 */
  margin: 0;
  opacity: 0.95;
  font-weight: 500;
  line-height: 1.4;
}

/* ============================================================
   Results — sections
   ============================================================ */
.section-heading {
  font-size: 0.78rem;
  font-weight: 700;
  margin: 1.75rem 1.25rem 0.5rem;
  text-transform: uppercase;
  color: var(--ink-500);
  letter-spacing: 0.08em;
}

.ingredient-row {
  background: var(--bg-surface);
  border-radius: var(--radius);
  margin: 0.5rem 1rem;
  padding: 1rem 1.1rem;
  display: flex;
  align-items: flex-start;
  gap: 0.85rem;
  box-shadow: var(--shadow-sm);
  border-left: 4px solid var(--ink-300);
  transition: transform 0.15s ease;
}
.ingredient-row:hover { transform: translateX(2px); }
.ingredient-row.tier-good           { border-left-color: var(--tier-good); }
.ingredient-row.tier-moderate_good  { border-left-color: var(--tier-moderate-good); }
.ingredient-row.tier-neutral        { border-left-color: var(--tier-neutral); }
.ingredient-row.tier-moderate_bad   { border-left-color: var(--tier-moderate-bad); }
.ingredient-row.tier-bad            { border-left-color: var(--tier-bad); }

.tier-badge {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  color: white;
  font-size: 1rem;
  /* v2.78 — Was margin-top:1px to nudge optical alignment with the
     ingredient name baseline; per user feedback the disk read as
     "not completely round" because that 1px shift made the visual
     center sit lower than the geometric center. Removed — alignment
     is now whatever the flex parent's align-items decides, which is
     the natural row center. */
  margin-top: 0;
}
.tier-badge.tier-good           { background: var(--tier-good); }
.tier-badge.tier-moderate_good  { background: var(--tier-moderate-good); }
.tier-badge.tier-neutral        { background: var(--tier-neutral); }
.tier-badge.tier-moderate_bad   { background: var(--tier-moderate-bad); }
.tier-badge.tier-bad            { background: var(--tier-bad); }
.tier-badge svg { width: 16px; height: 16px; }

.ingredient-body { flex: 1; min-width: 0; }
.ingredient-name { font-weight: 700; font-size: 1rem; margin: 0; color: var(--ink-900); }
/* The TIER and the WHY are the answers to "is this good for me?" + "why".
   They were originally caption-sized (Pillar 3 violation). Bumped to body
   size so Rae reads them without leaning in. */
.ingredient-tier { font-size: var(--text-secondary); font-weight: 700; margin: 0.15rem 0; text-transform: uppercase; letter-spacing: 0.05em; }
.ingredient-why  { font-size: var(--text-body); color: var(--ink-700); margin: 0.4rem 0 0; line-height: 1.55; }
/* Pillar 1 — "Better picks for you" promoted to the top of the results
   page when the grade is poor (C/D/F). This is the actionable "what should
   I buy instead?" moment in the grocery aisle. Visually distinct from the
   later "Better stuff to look for" educational block. */
.alternatives-at-shelf {
  margin: 0 1rem 1rem;
  padding: 1rem;
  background: linear-gradient(135deg, var(--green-50) 0%, var(--cream-100) 100%);
  border: 2px solid var(--green-200, var(--green-100));
  border-radius: 16px;
  box-shadow: var(--shadow-md);
}
.alternatives-at-shelf-title {
  margin: 0 0 0.6rem;
  font-family: 'Fraunces', Georgia, serif;
  font-size: var(--text-large);
  font-weight: 700;
  color: var(--green-700);
}
.alternatives-at-shelf .alternatives-card {
  background: var(--bg-surface);
  margin-top: 0.5rem;
}

/* Pillar 2 — "Grading for Rae · Hashimoto's, IBD" line below the grade card.
   Anchors the personalized score to the person + conditions, so the user
   never wonders "for who?" or "for what conditions?". */
.grading-for {
  margin: 0 1rem 0.75rem;
  padding: 0.6rem 0.9rem;
  background: var(--cream-100);
  border-radius: 12px;
  color: var(--ink-700);
  font-size: var(--text-secondary);
  text-align: center;
}
.grading-for strong { color: var(--ink-900); }
/* Visually distinct when grading on someone else's behalf — the recipient
   should never mistake whose body the grade reflects. */
.grading-for.grading-for-other {
  background: var(--coral-50);
  border: 1px solid var(--coral-100);
  color: var(--coral-700);
}
.grading-for.grading-for-other strong { color: var(--coral-700); }

/* "Flagged for: IBD, Celiac" — the personalized verdict. Promoted from a
   tiny pill to a real visual element. Sits ABOVE the why-text now (see
   makeIngredientRow) since it's the one-sentence answer to "why does THIS
   matter for ME." */
.ingredient-flagged {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  font-size: var(--text-secondary);
  color: var(--coral-700);
  background: var(--coral-50);
  border: 1px solid var(--coral-100);
  padding: 0.4rem 0.7rem;
  border-radius: 10px;
  margin: 0.4rem 0 0.5rem;
  font-weight: 600;
}
.ingredient-flagged svg { width: 18px; height: 18px; flex-shrink: 0; }
/* AIP-driven flags styled distinctly so they read as "phase-dependent",
   not as a permanent condition flag. */
.ingredient-flagged.ingredient-flagged-aip {
  color: var(--amber-700);
  background: var(--amber-50);
  border-color: #f6d28a;
}
/* Goal-driven concerns — softer than a condition flag because goals are
   aspirational, not diagnostic. Same shape, lighter palette. */
.ingredient-flagged.ingredient-flagged-goal {
  color: var(--amber-700);
  background: var(--amber-50);
  border-color: #f6d28a;
  font-weight: 500;
}
/* Goal-supports — the positive counterpart. Tells the user "this is
   exactly what you're looking for" without the alert framing. Theme green
   so it ties visually to the good-tier badge above it. */
.ingredient-supports-goal {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  font-size: var(--text-secondary);
  color: var(--green-700, #166534);
  background: rgba(34, 197, 94, 0.08);
  border: 1px solid rgba(34, 197, 94, 0.2);
  padding: 0.4rem 0.7rem;
  border-radius: 10px;
  margin: 0.4rem 0 0.5rem;
  font-weight: 500;
}
.ingredient-supports-goal svg { width: 18px; height: 18px; flex-shrink: 0; }

/* Attention pulse — used by the iOS barcode "still looking…" nudge to
   draw the eye to the manual UPC entry button after a 10s timeout. */
@keyframes attention-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(217, 74, 38, 0.45); }
  50%      { box-shadow: 0 0 0 12px rgba(217, 74, 38, 0); }
}
.attention-pulse {
  animation: attention-pulse 1.5s ease-out 2;
  border-color: var(--coral-500) !important;
}
body.reduce-motion .attention-pulse { animation: none; }

/* Composite-food summary — one-liner about the WHOLE dish/product before
   the per-ingredient why-text. Italicized to signal "headline answer". */
.ingredient-summary {
  margin: 0.4rem 0 0;
  font-size: var(--text-body);
  font-style: italic;
  color: var(--ink-700);
  line-height: 1.5;
}

.unknown-row {
  background: var(--cream-100);
  border-radius: var(--radius-sm);
  margin: 0.25rem 1rem;
  padding: 0.5rem 0.75rem;
  font-size: 0.875rem;
  color: var(--ink-500);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}

/* ============================================================
   Alternatives card
   ============================================================ */
.alternatives-card {
  background:
    linear-gradient(135deg, white 0%, var(--cream-50) 100%);
  border-radius: var(--radius);
  margin: 0.75rem 1rem;
  padding: 1.1rem 1.25rem;
  box-shadow: var(--shadow-sm);
  border: 1px solid var(--cream-200);
}
.alternatives-card h3 {
  margin: 0 0 0.5rem;
  font-size: 1.1rem;
  font-family: 'Fraunces', Georgia, serif;
  font-weight: 700;
}
.alternatives-card .swap-list { margin: 0.4rem 0 0.5rem; padding-left: 1.25rem; }
.alternatives-card .swap-list li { margin: 0.2rem 0; font-size: 0.95rem; }
.alternatives-card .swap-list li::marker { color: var(--green-500); }
.alternatives-card .tip {
  font-size: 0.88rem;
  color: var(--ink-700);
  font-style: italic;
  margin: 0.6rem 0 0;
  padding-top: 0.6rem;
  border-top: 1px solid var(--cream-200);
}

/* v2.62 — Product name on the results card. Was small italic muted
   ink (0.95rem, --ink-500, italic) which made it nearly invisible
   under the grade. User reported almost missing the product name.
   Now: larger, bolder, full-contrast ink. Reads as a real heading
   sibling to "Looks pretty good" — the second-most-prominent line
   on the card. */
.product-name {
  text-align: center;
  margin: 0.75rem 1rem 0;
  font-size: 1.35rem;
  line-height: 1.25;
  color: var(--ink-900);
  font-weight: 700;
  font-family: 'Fraunces', Georgia, serif;
  letter-spacing: -0.005em;
}

/* ============================================================
   Bottom tab bar
   ============================================================ */
.tab-bar {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  background: var(--bg-surface);
  border-top: 1px solid var(--cream-200);
  display: flex;
  z-index: 50;
  padding-bottom: env(safe-area-inset-bottom);
  box-shadow: 0 -4px 16px rgba(40, 30, 20, 0.06);
}
.tab-btn {
  flex: 1;
  background: transparent;
  border: none;
  padding: 0.625rem 0.25rem 0.625rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  color: var(--ink-500);
  font-size: var(--text-secondary);   /* was 0.72rem — Pillar 4 violation */
  font-family: inherit;
  font-weight: 600;                    /* slightly heavier so labels read clearly at small phone sizes */
  cursor: pointer;
  transition: color 0.15s ease;
  position: relative;
}
.tab-btn:hover { color: var(--green-500); }
.tab-btn svg {
  width: 26px;                         /* was 24 — sized up with the labels */
  height: 26px;
  margin-bottom: 0.2rem;
  transition: transform 0.18s cubic-bezier(0.2, 0.7, 0.2, 1);
}
.tab-btn.active { color: var(--green-700); font-weight: 700; }
.tab-btn.active svg { transform: translateY(-2px) scale(1.08); }
.tab-btn.active::before {
  content: '';
  position: absolute;
  top: 0;
  left: 50%;
  transform: translateX(-50%);
  width: 28px;
  height: 3px;
  background: var(--green-500);
  border-radius: 0 0 999px 999px;
}

body.has-tabs .screen.active { padding-bottom: 6rem; }
body.has-tabs #screen-results { padding-bottom: 6rem; }

/* ============================================================
   Banner (daily check-in nudge)
   ============================================================ */
.banner {
  background:
    linear-gradient(135deg, var(--coral-50) 0%, var(--cream-100) 100%);
  border: 1px solid var(--coral-100);
  margin: 1rem;
  padding: 1rem 1.1rem;
  border-radius: var(--radius);
  display: flex;
  align-items: center;
  gap: 0.875rem;
  box-shadow: var(--shadow-sm);
  animation: cardIn 0.4s ease;
}
.banner-icon {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: var(--bg-surface);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  color: var(--coral-500);
  box-shadow: var(--shadow-sm);
}
.banner-icon svg { width: 22px; height: 22px; }
.banner-body { flex: 1; display: flex; flex-direction: column; line-height: 1.3; }
.banner-body strong { color: var(--ink-900); font-size: var(--text-body); }
.banner-body .muted { font-size: var(--text-secondary); color: var(--ink-500); margin-top: 0.15rem; }
.banner .btn { white-space: nowrap; padding: 0.55rem 0.95rem; font-size: var(--text-secondary); }

/* ============================================================
   Diary sliders
   ============================================================ */
.diary-greeting {
  text-align: center;
  font-family: 'Fraunces', Georgia, serif;
  font-size: 1.6rem;
  font-weight: 700;
  color: var(--ink-900);
  margin: 0 0 0.25rem;
  letter-spacing: -0.01em;
}
.diary-date-label {
  text-align: center;
  color: var(--ink-500);
  font-size: 0.9rem;
  margin: 0 0 1rem;
}

.slider-row {
  display: flex;
  flex-direction: column;
  margin: 1.25rem 0 1rem;
}
.slider-row label {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-weight: 600;
  font-size: 1rem;
  margin-bottom: 0.5rem;
  color: var(--ink-900);
}
.slider-row .slider-emoji { font-size: 1.4rem; margin-right: 0.4rem; }
.slider-row .slider-value-pill {
  background: var(--green-50);
  color: var(--green-700);
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  padding: 0.2rem 0.6rem;
  border-radius: 999px;
  font-size: 0.85rem;
}
.slider-row input[type="range"] {
  width: 100%;
  appearance: none;
  -webkit-appearance: none;
  height: 10px;
  background: linear-gradient(to right,
    var(--rose-500) 0%,
    var(--amber-500) 30%,
    var(--ink-300) 50%,
    #84cc16 70%,
    var(--green-500) 100%);
  border-radius: 999px;
  outline: none;
  cursor: pointer;
}
.slider-row input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--bg-surface);
  border: 3px solid var(--green-500);
  cursor: grab;
  box-shadow: var(--shadow-md);
  transition: transform 0.1s ease, box-shadow 0.15s ease;
}
.slider-row input[type="range"]:active::-webkit-slider-thumb { transform: scale(1.18); cursor: grabbing; }
.slider-row input[type="range"]::-moz-range-thumb {
  width: 28px; height: 28px;
  border-radius: 50%;
  background: var(--bg-surface);
  border: 3px solid var(--green-500);
  cursor: grab;
  box-shadow: var(--shadow-md);
}
.slider-scale {
  display: flex;
  justify-content: space-between;
  font-size: 0.75rem;
  color: var(--ink-500);
  margin-top: 0.3rem;
}

/* Flare checkbox styled */
.flare-toggle {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.85rem 1rem;
  background: var(--cream-100);
  border-radius: var(--radius);
  margin: 1.25rem 0 0;
  cursor: pointer;
  border: 2px solid transparent;
  transition: all 0.15s ease;
}
.flare-toggle:hover { background: var(--cream-200); }
.flare-toggle input { accent-color: var(--coral-500); width: 18px; height: 18px; }
.flare-toggle strong { color: var(--coral-700); }
.flare-toggle.checked { background: var(--coral-50); border-color: var(--coral-100); }

/* ============================================================
   Recent diary
   ============================================================ */
.diary-entry-row {
  display: flex;
  align-items: center;
  padding: 0.85rem 0;
  border-bottom: 1px solid var(--cream-100);
  font-size: 0.95rem;
}
.diary-entry-row:last-child { border-bottom: none; }
.diary-entry-date { flex: 1; color: var(--ink-700); }
.diary-entry-overall {
  font-weight: 700;
  color: var(--green-700);
  padding: 0.2rem 0.55rem;
  background: var(--green-50);
  border-radius: 999px;
  font-size: 0.85rem;
}
.diary-flare-pill {
  display: inline-block;
  background: var(--coral-50);
  color: var(--coral-700);
  border-radius: 999px;
  padding: 0.15rem 0.55rem;
  font-size: 0.72rem;
  margin-left: 0.5rem;
  font-weight: 700;
  letter-spacing: 0.03em;
  text-transform: uppercase;
}

/* ============================================================
   History screen
   ============================================================ */
.tab-strip {
  display: flex;
  margin: 1rem;
  background: var(--cream-100);
  border-radius: 999px;
  padding: 0.3rem;
}
.tab-strip-btn {
  flex: 1;
  background: transparent;
  border: none;
  padding: 0.55rem;
  font-size: 0.92rem;
  font-weight: 600;
  font-family: inherit;
  border-radius: 999px;
  color: var(--ink-500);
  cursor: pointer;
  transition: all 0.15s ease;
}
.tab-strip-btn.active {
  background: var(--bg-surface);
  color: var(--ink-900);
  box-shadow: var(--shadow-sm);
}
.htab-panel { display: none; }
.htab-panel.active { display: block; animation: fadeIn 0.25s ease; }
/* One-line tab subtitle — sits between the tab strip and the first row,
   so the tab name (Safe / Eaten / All scans) is self-explanatory on
   first land without a separate help icon. */
.htab-subtitle {
  margin: 0.6rem 1rem 0.4rem;
  line-height: 1.35;
}

/* Retroactive "I had this" button on All scans rows. Compact pill that
   sits to the right of the meta block — taps log the scan to Eaten with
   the current timestamp and the row re-renders to show an "eaten" pill
   instead of the button. */
.history-actions {
  margin-left: auto;
  display: flex;
  align-items: center;
  flex-shrink: 0;
}
.history-eaten-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  background: var(--coral-50);
  color: var(--coral-700);
  border: 1.5px solid var(--coral-500);
  border-radius: 999px;
  padding: 0.4rem 0.75rem;
  font-family: inherit;
  font-weight: 700;
  font-size: 0.85rem;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
  appearance: none;
  -webkit-appearance: none;
}
.history-eaten-btn:hover { background: var(--coral-100); }
.history-eaten-btn:active { transform: scale(0.97); }
.history-eaten-btn svg { width: 16px; height: 16px; }

/* Small "change date" pill on Eaten rows. Subtle so the row reads as
   "logged" not "needs your attention," but tappable when the user needs
   to fix a date they forgot to backdate. */
.history-edit-date-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  background: transparent;
  color: var(--ink-500);
  border: 1px solid var(--cream-200);
  border-radius: 999px;
  padding: 0.3rem 0.6rem;
  font-family: inherit;
  font-weight: 600;
  font-size: 0.8rem;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
}
.history-edit-date-btn:hover { background: var(--cream-100); color: var(--ink-700); }

/* Recently-eaten pantry recovery — collapsed under a <details> so the
   open Pantry stays visually dominant. Rows are de-emphasized but
   functional: "Buy again" puts the item back in open pantry. */
.pantry-history {
  margin: 1rem;
}
.pantry-history-summary {
  cursor: pointer;
  font-size: 0.9rem;
  color: var(--ink-500);
  padding: 0.5rem 0;
  display: flex;
  align-items: center;
  gap: 0.4rem;
  list-style: none;   /* hide native disclosure triangle on iOS */
}
.pantry-history-summary::-webkit-details-marker { display: none; }
.pantry-history-summary svg { width: 16px; height: 16px; }
.pantry-history-summary::after {
  content: '▾';
  margin-left: auto;
  transition: transform 0.15s ease;
}
.pantry-history[open] .pantry-history-summary::after { transform: rotate(180deg); }
.pantry-consumed-row { opacity: 0.7; }
.pantry-consumed-row .history-title { text-decoration: line-through; }

/* ============================================================
   Settings help system — TOC chips + inline "?" + popover panel
   ============================================================ */
/* Small circular "?" button injected next to each Settings card heading.
   Sits inline with the H2 text but doesn't compete for visual weight. */
.settings-help-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  margin-left: 0.55rem;
  padding: 0;
  border-radius: 50%;
  background: var(--green-50);
  color: var(--green-700);
  border: 1.5px solid var(--green-500);
  font-family: inherit;
  font-weight: 800;
  font-size: 1.2rem;
  line-height: 1;
  cursor: pointer;
  vertical-align: middle;
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
  appearance: none;
  -webkit-appearance: none;
}
.settings-help-btn:hover { background: var(--green-100); }
.settings-help-btn:active { transform: scale(0.94); }

/* Inline help popover that drops in below the heading when "?" is tapped.
   Cream-tinted to read as "informational aside," not a real card. */
.settings-help-panel {
  background: var(--cream-100);
  border-left: 3px solid var(--green-500);
  border-radius: 8px;
  padding: 0.7rem 0.85rem;
  margin: 0.5rem 0 0.75rem;
  font-size: 0.92rem;
  line-height: 1.45;
  color: var(--ink-700);
  animation: fadeIn 0.2s ease;
}

/* TOC card chips — sized for readability over compactness. Adopt the
   theme-green treatment (matches the look of a selected condition chip
   in "What applies to you") so the labels read clearly and the chips
   feel like inviting tappable destinations, not subtle nav hints.

   v3.11 — Switched from flex-wrap to a CSS grid that auto-fits as
   many columns as the phone width allows (minmax 150px). Pre-v3.11
   each chip wrapped onto its own row with whitespace beside it; the
   grid packs short labels (Theme, About) into the same row as the
   long ones (Autoimmune Protocol, What applies to you), saving 2-3
   rows of vertical space on a typical phone. */
#settings-toc-card { padding: 0.85rem 1rem; }
#settings-toc-card h2 { color: var(--ink-500); letter-spacing: 0.04em; text-transform: uppercase; font-size: 0.8rem; }
#settings-toc-chips {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 0.5rem;
  margin-top: 0.5rem;
}
#settings-toc-chips .chip {
  display: flex;                       /* fill the grid cell */
  justify-content: center;
  align-items: center;
  text-align: center;
  width: 100%;
  padding: 0.6rem 0.7rem;
  font-size: 0.92rem;
  font-weight: 600;
  background: var(--green-50);
  color: var(--green-700);
  border: 2px solid var(--green-500);
  line-height: 1.2;                    /* allow 2-line wrap inside cell */
  white-space: normal;                 /* let long labels wrap, not overflow */
}
#settings-toc-chips .chip:hover {
  background: var(--green-100);
  transform: translateY(-1px);
}
#settings-toc-chips .chip:active {
  transform: translateY(0) scale(0.97);
}

/* ============================================================
   Eaten — log chooser (Quick log vs Build a meal)
   ============================================================ */
/* Two big tappable cards that disambiguate the two log paths. Single
   primary "+ Log a meal or snack" expands this card; each option has
   an icon, a clear title, and a one-line subtitle. */
#eaten-log-chooser {
  padding: 0.85rem 0.85rem 1rem;
}
.log-chooser-option {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  width: 100%;
  padding: 0.85rem 1rem;
  background: var(--green-50);
  border: 2px solid var(--green-500);
  border-radius: var(--radius-sm);
  cursor: pointer;
  text-align: left;
  font-family: inherit;
  color: var(--ink-900);
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
  transition: background 0.15s ease, transform 0.08s ease;
}
.log-chooser-option:hover {
  background: var(--green-100);
}
.log-chooser-option:active {
  transform: scale(0.98);
}
.log-chooser-icon {
  font-size: 1.7rem;
  line-height: 1;
  flex-shrink: 0;
}
.log-chooser-body {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-width: 0;
}
.log-chooser-title {
  font-weight: 700;
  font-size: 1rem;
  color: var(--green-700);
}
.log-chooser-sub {
  font-size: 0.85rem;
  color: var(--ink-500);
  margin-top: 0.15rem;
  line-height: 1.35;
}
.log-chooser-arrow {
  font-size: 1.5rem;
  color: var(--green-700);
  flex-shrink: 0;
}

/* ============================================================
   Eaten — "My usual meals" templates strip
   ============================================================ */
.eaten-templates-row {
  margin: 0.25rem 1rem 0.75rem;
  padding: 0.6rem 0.85rem;
  background: var(--bg-surface);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
}
.eaten-templates-row .chip-group { gap: 0.4rem; }
/* Template chip is composite — body button (log) + small × (delete).
   Using a span wrapper instead of a button so the two children can be
   independent tap targets. */
.eaten-template-chip {
  display: inline-flex;
  align-items: center;
  padding: 0;
  overflow: hidden;
}
.eaten-template-chip .template-log-btn {
  background: transparent;
  border: none;
  color: inherit;
  font: inherit;
  padding: 0.55rem 0.5rem 0.55rem 0.95rem;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.eaten-template-chip .template-del-btn {
  background: transparent;
  border: none;
  color: var(--ink-500);
  font-size: 1.1rem;
  line-height: 1;
  padding: 0 0.7rem 0 0.35rem;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.eaten-template-chip .template-del-btn:hover {
  color: var(--rose-700);
}

/* ============================================================
   Eaten — meal-type pill (cycle on tap)
   ============================================================ */
.eaten-meal-pill {
  display: inline-flex;
  align-items: center;
  gap: 0.2rem;
  padding: 0.15rem 0.55rem;
  margin-left: 0.4rem;
  border-radius: 999px;
  background: var(--green-50);
  color: var(--green-700);
  border: 1.5px solid var(--green-500);
  font-family: inherit;
  font-size: 0.75rem;
  font-weight: 600;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
  vertical-align: middle;
}
.eaten-meal-pill:hover { background: var(--green-100); }
.eaten-meal-pill-empty {
  background: transparent;
  color: var(--ink-500);
  border: 1.5px dashed var(--cream-200);
}
.eaten-meal-pill-empty:hover {
  background: var(--cream-100);
  color: var(--ink-700);
  border-color: var(--cream-200);
}

/* ============================================================
   Numbers — multi-entry rows (BP, glucose)
   ============================================================ */
.numbers-readings-list {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  margin: 0.4rem 0 0.5rem;
}
.numbers-reading-row {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.5rem 0.75rem;
  background: var(--cream-100);
  border-radius: 10px;
  font-size: 0.9rem;
}
.numbers-reading-row .reading-time {
  color: var(--ink-500);
  font-size: 0.8rem;
  flex-shrink: 0;
  min-width: 60px;
}
.numbers-reading-row .reading-value {
  flex: 1;
  color: var(--ink-900);
}
.numbers-reading-row .reading-delete {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: transparent;
  color: var(--ink-500);
  border: 1px solid var(--cream-200);
  font-family: inherit;
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
  flex-shrink: 0;
  -webkit-tap-highlight-color: transparent;
}
.numbers-reading-row .reading-delete:hover {
  background: var(--rose-50);
  color: var(--rose-700);
  border-color: var(--rose-500, #f87171);
}
.numbers-add-form {
  padding: 0.75rem;
  background: var(--green-50);
  border: 1px dashed var(--green-300);
  border-radius: 10px;
  margin-top: 0.5rem;
}

/* Bigger weight input — it's the marquee field on this card (drives BMI)
   so it earns more visual weight than the inline mini-form numerics. */
#numbers-weight {
  font-size: 1.3rem;
  font-weight: 600;
  padding: 1rem 1rem;
  text-align: center;
  letter-spacing: 0.02em;
}

/* "+ Add BP reading" / "+ Add glucose reading" — these are Add actions
   (not the page's primary CTA), so they get a green-themed pill style
   that matches the rest of the theme palette without competing with
   the diary's main Save button at the bottom. Same treatment family as
   the TOC chips in Settings. */
#numbers-bp-add,
#numbers-glucose-add {
  background: var(--green-50);
  color: var(--green-700);
  border: 2px solid var(--green-500);
  font-weight: 600;
  font-size: 0.95rem;
}
#numbers-bp-add:hover,
#numbers-glucose-add:hover {
  background: var(--green-100);
  transform: translateY(-1px);
}
#numbers-bp-add:active,
#numbers-glucose-add:active {
  transform: translateY(0) scale(0.98);
}

/* ============================================================
   Past months — auto-saved health reports
   ============================================================ */
.past-month-row {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.6rem 0;
  border-top: 1px solid var(--cream-100);
}
.past-month-row:first-child { border-top: none; padding-top: 0.2rem; }
.past-month-meta { flex: 1; min-width: 0; }
.past-month-label { margin: 0; font-weight: 700; color: var(--ink-900); }
.past-month-stats { margin: 0.1rem 0 0; }
.past-month-actions {
  display: flex;
  gap: 0.35rem;
  flex-shrink: 0;
}
.past-month-actions .btn {
  padding: 0.4rem 0.7rem;
  font-size: 0.85rem;
  min-height: 36px;
}

/* ============================================================
   Caregiver mode ribbon
   ============================================================ */
/* Slim coral bar pinned to the top of the viewport whenever 2+ profiles
   exist. Pillar 8 (Caregiver Dignity) — Marisol always knows whose body
   the grade reflects, regardless of which screen she's on. body padding
   shifts to accommodate the ribbon so the topbar isn't covered. */
body.has-caregiver-ribbon { padding-top: 38px; }
#caregiver-ribbon {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 9999;   /* above topbar (z:10) and modals' overlay */
  height: 38px;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0 0.85rem;
  background: linear-gradient(135deg, var(--green-500), var(--green-700));
  color: white;
  font-size: 0.85rem;
  font-weight: 600;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
  box-shadow: 0 1px 3px rgba(0,0,0,0.12);
}
#caregiver-ribbon .cr-avatar {
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: var(--bg-surface);
  color: var(--coral-700);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-weight: 800;
  font-size: 0.8rem;
  flex-shrink: 0;
}
#caregiver-ribbon .cr-text {
  flex: 1;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
#caregiver-ribbon .cr-text strong { font-weight: 800; }
#caregiver-ribbon .cr-action {
  font-size: 0.75rem;
  opacity: 0.9;
  padding-left: 0.5rem;
  border-left: 1px solid rgba(255,255,255,0.3);
  flex-shrink: 0;
}
#caregiver-ribbon:hover {
  filter: brightness(1.08);
}

/* ============================================================
   Portrait-only overlay
   ============================================================ */
/* Velrae is portrait-first — the camera viewfinder, grade card, scan-mode
   buttons, and bottom tab bar are all sized for vertical use. When iOS
   Safari auto-rotates the page (e.g. when the user tilts to aim a barcode
   scan), the layout breaks and the camera viewfinder becomes nearly
   unusable. This overlay takes over the screen in landscape so the camera
   stream isn't competing for the user's attention while the phone is
   sideways. Hidden by default; the @media rule below shows it only on
   real phone-shaped landscape (excludes desktop browsers, which are
   permanently landscape but have plenty of height). */
#landscape-block {
  display: none;
  position: fixed;
  inset: 0;
  background: linear-gradient(135deg, var(--health-good-500), var(--health-good-700));
  color: white;
  z-index: 9999;
  align-items: center;
  justify-content: center;
  padding: 2rem;
  text-align: center;
}
.landscape-block-inner { max-width: 320px; }
.landscape-block-icon {
  font-size: 4rem;
  line-height: 1;
  margin-bottom: 1rem;
  animation: rotate-hint 2.2s ease-in-out infinite;
  display: inline-block;
}
#landscape-block h2 {
  font-family: 'Fraunces', Georgia, serif;
  margin: 0 0 0.5rem;
  font-size: 1.5rem;
}
#landscape-block p {
  margin: 0;
  opacity: 0.92;
  line-height: 1.45;
}
.landscape-block-tip {
  margin-top: 1rem !important;
  padding: 0.7rem 0.85rem;
  background: rgba(255,255,255,0.18);
  border-radius: 10px;
  font-size: 0.9rem;
  line-height: 1.4;
}
.landscape-block-tip strong { color: white; }
@keyframes rotate-hint {
  0%, 100% { transform: rotate(0deg); }
  50%      { transform: rotate(-90deg); }
}
/* Only show on phone-shaped landscape — desktop browsers in landscape
   have plenty of vertical room and shouldn't be blocked. */
@media (orientation: landscape) and (max-height: 600px) {
  #landscape-block { display: flex; }
}


.history-row {
  background: var(--bg-surface);
  margin: 0.5rem 1rem;
  padding: 1rem 1.1rem;
  border-radius: var(--radius);
  display: flex;
  align-items: center;
  gap: 0.85rem;
  box-shadow: var(--shadow-sm);
  cursor: pointer;
  transition: transform 0.12s ease, box-shadow 0.18s ease;
}
.history-row:hover { transform: translateY(-1px); box-shadow: var(--shadow-md); }

/* ============================================================
   Eaten tab — day-grouped collapsible pills (v2.38)
   ============================================================
   Each pill is a card whose header is a button (whole-pill tap target
   for Rae). The entries block underneath uses the existing .history-row
   markup but resets margin/shadow since the pill itself provides the
   card frame. */
.eaten-day-pill {
  margin: 0.75rem 1rem;
  background: var(--bg-surface);
  border: 1px solid var(--cream-200);
  border-radius: 14px;
  overflow: hidden;
  box-shadow: var(--shadow-sm);
}
.eaten-day-pill-today {
  background: linear-gradient(135deg, var(--green-50), white 65%);
  border-color: var(--green-100);
}
.eaten-day-pill-header {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.9rem 1rem;
  background: transparent;
  border: none;
  cursor: pointer;
  text-align: left;
  color: var(--ink-900);
  font-family: inherit;
  font-size: inherit;
  min-height: 56px;             /* generous tap target for Rae */
}
.eaten-day-pill-header:hover { background: rgba(0,0,0,0.025); }
.eaten-day-pill-label {
  flex: 1;
  font-weight: 700;
  font-size: 1rem;
  font-family: 'Fraunces', Georgia, serif;
  color: var(--ink-900);
  line-height: 1.2;
}
.eaten-day-pill-count {
  color: var(--ink-500);
  font-size: 0.85rem;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
/* v2.87 — Daily grade chip in the day-pill header. Compact mirror
   of .history-grade — same gradient colors per A/B/C/D/F so the
   visual language matches the per-scan grade card. Per user: this
   lets you see "today was an F, tomorrow is a B" patterns at a glance.
   Sized small (32px) so it sits beside the date label without
   dominating the row. Color always reads correctly — health colors
   are theme-locked per the project's grade-color rule. */
.eaten-day-pill-grade {
  flex-shrink: 0;
  width: 32px;
  height: 32px;
  border-radius: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: 'Fraunces', Georgia, serif;
  font-weight: 800;
  font-size: 1.05rem;
  color: white;
  line-height: 1;
}
.eaten-day-pill-grade.grade-A { background: linear-gradient(135deg, var(--health-good-500), var(--health-good-700)); }
.eaten-day-pill-grade.grade-B { background: linear-gradient(135deg, var(--health-lime-500), var(--health-good-500)); }
.eaten-day-pill-grade.grade-C { background: linear-gradient(135deg, var(--health-caution-500), var(--health-caution-700)); }
.eaten-day-pill-grade.grade-D { background: linear-gradient(135deg, var(--health-warn-500), var(--health-warn-700)); }
.eaten-day-pill-grade.grade-F { background: linear-gradient(135deg, var(--health-bad-500), var(--health-bad-700)); }
.eaten-day-pill-grade[data-day-verdict] { cursor: pointer; transition: transform 0.12s ease; }
.eaten-day-pill-grade[data-day-verdict]:hover { transform: scale(1.05); }
.eaten-day-pill-grade[data-day-verdict]:focus-visible { outline: 2px solid var(--primary, #70cbd0); outline-offset: 2px; }

/* ============================================================
   v2.88 → v2.95 — Day overview modal
   Was a full-screen <section> through v2.94. v2.95 converts it to
   a modal overlay that pops up over the Log (user keeps their
   place; just dismiss to return). The grade card / what helped /
   what hurt / nutrition / felt-like sections inside are unchanged;
   only the container chrome flipped from screen to modal.
   ============================================================ */

.day-verdict-modal {
  /* .overlay base provides the backdrop + centering already */
}
.day-verdict-modal-content {
  max-width: 640px;
  width: 100%;
  max-height: 92vh;
  display: flex;
  flex-direction: column;
  padding: 0;
  overflow: hidden;
  background: var(--cream-50, #fefcf8);
}
@media (max-width: 640px) {
  .day-verdict-modal-content {
    max-height: 100vh;
    border-radius: 0;
    margin: 0;
  }
}
.day-verdict-modal-header {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.85rem 1rem 0.7rem;
  background: var(--bg-surface);
  border-bottom: 1px solid var(--cream-200);
}
.day-verdict-modal-title {
  margin: 0;
  font-family: 'Fraunces', Georgia, serif;
  font-size: 1.15rem;
  font-weight: 700;
  color: var(--ink-900);
}
.day-verdict-modal-close {
  background: rgba(0,0,0,0.06);
  color: var(--ink-700);
}
.day-verdict-modal-close:hover { background: rgba(0,0,0,0.12); }

/* Day overview content inside the modal — scrolls inside the body */
.day-verdict-body {
  flex: 1;
  overflow-y: auto;
  padding: 1rem;
}

.day-verdict-nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  padding: 0.6rem 1rem;
  background: var(--cream-50);
  border-bottom: 1px solid var(--cream-200);
}
.day-verdict-nav-btn {
  background: none;
  border: none;
  color: var(--primary, #70cbd0);
  font-weight: 600;
  font-size: 0.92rem;
  cursor: pointer;
  padding: 0.4rem 0.5rem;
  border-radius: 8px;
  font-family: inherit;
}
.day-verdict-nav-btn:hover { background: rgba(112, 203, 208, 0.12); }
.day-verdict-nav-btn:disabled { color: var(--ink-300); cursor: default; }
.day-verdict-nav-btn:disabled:hover { background: none; }
.day-verdict-nav-label {
  font-family: 'Fraunces', Georgia, serif;
  font-weight: 700;
  color: var(--ink-900);
  font-size: 0.95rem;
  text-align: center;
  flex: 1;
}
/* v2.95 — Body padding now defined above in the modal-content layout block.
   This legacy rule remains harmless if any old surface still uses it. */

.day-verdict-card {
  background: var(--bg-surface);
  border: 1px solid var(--cream-200);
  border-radius: var(--radius);
  padding: 1.1rem;
  margin-bottom: 0.85rem;
}
.day-verdict-grade-card {
  display: flex;
  align-items: center;
  gap: 1rem;
}
.day-verdict-grade-big {
  flex-shrink: 0;
  width: 88px;
  height: 88px;
  border-radius: 22px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: 'Fraunces', Georgia, serif;
  font-weight: 800;
  font-size: 3rem;
  color: white;
  line-height: 1;
}
.day-verdict-grade-big.grade-A { background: linear-gradient(135deg, var(--health-good-500), var(--health-good-700)); }
.day-verdict-grade-big.grade-B { background: linear-gradient(135deg, var(--health-lime-500), var(--health-good-500)); }
.day-verdict-grade-big.grade-C { background: linear-gradient(135deg, var(--health-caution-500), var(--health-caution-700)); }
.day-verdict-grade-big.grade-D { background: linear-gradient(135deg, var(--health-warn-500), var(--health-warn-700)); }
.day-verdict-grade-big.grade-F { background: linear-gradient(135deg, var(--health-bad-500), var(--health-bad-700)); }
.day-verdict-grade-meta { flex: 1; min-width: 0; }
.day-verdict-grade-score {
  margin: 0;
  font-family: 'Fraunces', Georgia, serif;
  font-weight: 700;
  font-size: 1.4rem;
  color: var(--ink-900);
}
.day-verdict-grade-sub {
  margin: 0.2rem 0 0;
  color: var(--ink-500);
  font-size: 0.88rem;
}

.day-verdict-h3 {
  font-family: 'Fraunces', Georgia, serif;
  font-size: 1.05rem;
  font-weight: 700;
  margin: 0 0 0.6rem;
  color: var(--ink-900);
}
.day-verdict-list { list-style: none; padding: 0; margin: 0; }
.day-verdict-item {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.55rem 0;
  border-bottom: 1px solid var(--cream-100);
  cursor: pointer;
}
.day-verdict-item:last-child { border-bottom: none; }
.day-verdict-item:hover { background: rgba(0,0,0,0.02); }
.day-verdict-item-grade {
  flex-shrink: 0;
  width: 28px;
  height: 28px;
  border-radius: 8px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: 'Fraunces', Georgia, serif;
  font-weight: 800;
  font-size: 0.95rem;
  color: white;
}
.day-verdict-item-grade.grade-A { background: linear-gradient(135deg, var(--health-good-500), var(--health-good-700)); }
.day-verdict-item-grade.grade-B { background: linear-gradient(135deg, var(--health-lime-500), var(--health-good-500)); }
.day-verdict-item-grade.grade-C { background: linear-gradient(135deg, var(--health-caution-500), var(--health-caution-700)); }
.day-verdict-item-grade.grade-D { background: linear-gradient(135deg, var(--health-warn-500), var(--health-warn-700)); }
.day-verdict-item-grade.grade-F { background: linear-gradient(135deg, var(--health-bad-500), var(--health-bad-700)); }
.day-verdict-item-name {
  flex: 1;
  min-width: 0;
  font-weight: 600;
  color: var(--ink-900);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* v3.01 — Featured calorie hero block at the top of the Nutrition card.
   Calories get their own visual treatment because they're the most-
   asked-about daily number. Mirrors the per-scan verdict's
   "514 of 2,000 calories" header pattern. Three color states: on-track,
   under (sparse day), over (above 110% — visual nudge that the day
   ran high without being scoldy). */
.day-verdict-cal-hero {
  margin: 0 0 0.85rem;
  padding: 0.85rem 1rem;
  border-radius: 12px;
  background: var(--cream-100, #faf5ec);
  border-left: 4px solid var(--ink-500);
}
.day-verdict-cal-on-track { border-left-color: var(--health-good-700, #1a5d44); }
.day-verdict-cal-under    { border-left-color: var(--health-caution-700, #6b4a07); }
.day-verdict-cal-over     { border-left-color: var(--health-bad-700, #991b1b); }
.day-verdict-cal-row {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
}
.day-verdict-cal-value {
  font-family: 'Fraunces', Georgia, serif;
  font-size: 1.9rem;
  font-weight: 800;
  color: var(--ink-900);
  line-height: 1;
}
.day-verdict-cal-ref {
  font-size: 0.95rem;
  color: var(--ink-500);
  font-weight: 500;
  margin-left: 0.25rem;
}
.day-verdict-cal-pct {
  margin: 0.3rem 0 0;
  font-size: 0.78rem;
  color: var(--ink-500);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.day-verdict-nut-grid {
  display: grid;
  gap: 0.25rem;
}
.day-verdict-nut-row {
  display: grid;
  grid-template-columns: 1fr auto 3.5rem;
  gap: 0.5rem;
  padding: 0.45rem 0;
  border-bottom: 1px solid var(--cream-100);
  align-items: baseline;
}
.day-verdict-nut-row:last-child { border-bottom: none; }
.day-verdict-nut-label { color: var(--ink-700); font-size: 0.95rem; }
.day-verdict-nut-value { color: var(--ink-900); font-weight: 700; font-variant-numeric: tabular-nums; }
.day-verdict-nut-pct { color: var(--ink-500); font-weight: 600; text-align: right; font-variant-numeric: tabular-nums; }

.day-verdict-felt {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
}
.day-verdict-felt-pill {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.35rem 0.65rem;
  background: var(--cream-50);
  border: 1px solid var(--cream-200);
  border-radius: 10px;
  font-size: 0.88rem;
}
.day-verdict-felt-emoji { font-size: 1rem; }
.day-verdict-felt-label { color: var(--ink-700); }
.day-verdict-felt-value { color: var(--ink-900); font-weight: 700; font-variant-numeric: tabular-nums; }
.day-verdict-flare-note { margin: 0.6rem 0 0; color: var(--health-warn-700); font-weight: 600; font-size: 0.9rem; }
.day-verdict-notes { margin: 0.6rem 0 0; color: var(--ink-700); font-style: italic; font-size: 0.92rem; line-height: 1.45; }

/* v3.00 — Collapsible item pills at the bottom of Day Overview.
   The What-helped / What-hurt sections moved from cards-at-the-top
   to expandable pills-at-the-bottom per user feedback: the summary
   is what the user wants to see first; the per-item drill-down stays
   reachable but out of the way. */
.day-verdict-pill-section {
  margin-top: 1.2rem;
  padding-top: 0.85rem;
  border-top: 1px solid var(--cream-200);
}
.day-verdict-pill-section-label {
  margin: 0 0 0.5rem;
  font-size: 0.78rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ink-500);
}
.day-verdict-pill {
  background: var(--bg-surface);
  border: 1px solid var(--cream-200);
  border-radius: 12px;
  margin-bottom: 0.5rem;
  overflow: hidden;
}
.day-verdict-pill-header {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.75rem 0.9rem;
  background: none;
  border: none;
  text-align: left;
  cursor: pointer;
  font-family: inherit;
  transition: background 0.12s ease;
}
.day-verdict-pill-header:hover { background: rgba(0,0,0,0.02); }
.day-verdict-pill-icon {
  flex-shrink: 0;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 800;
  font-size: 0.85rem;
  color: white;
}
.day-verdict-pill-icon-good { background: var(--health-good-700, #1a5d44); }
.day-verdict-pill-icon-bad  { background: var(--health-bad-700, #991b1b); }
.day-verdict-pill-label {
  flex: 1;
  font-weight: 700;
  color: var(--ink-900);
  font-size: 0.95rem;
}
.day-verdict-pill-count {
  flex-shrink: 0;
  padding: 0.15rem 0.5rem;
  background: var(--cream-100);
  border-radius: 999px;
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--ink-700);
  font-variant-numeric: tabular-nums;
}
.day-verdict-pill-arrow {
  flex-shrink: 0;
  color: var(--ink-500);
  font-size: 0.78rem;
  width: 1.2em;
  text-align: center;
}
.day-verdict-pill-body {
  padding: 0 0.9rem 0.7rem;
  border-top: 1px solid var(--cream-100);
}
.day-verdict-pill-body .day-verdict-list { padding-top: 0.5rem; }
.eaten-day-pill-arrow {
  color: var(--ink-500);
  font-size: 0.8rem;
  width: 1.5em;
  text-align: center;
  flex-shrink: 0;
}
.eaten-day-pill-entries {
  border-top: 1px solid var(--cream-200);
  padding: 0.3rem 0 0.5rem;
}
/* Inside a day pill the rows lose their card frame — the pill is the
   card. Reset margin, shadow, and hover lift so rows feel like items
   in a list, not stacked cards. */
.eaten-day-pill-entries .history-row {
  margin: 0.25rem 0.5rem;
  box-shadow: none;
  border-radius: 10px;
  background: var(--cream-100);
}
.eaten-day-pill-entries .history-row:hover {
  transform: none;
  box-shadow: none;
  background: var(--cream-200);
}
.history-grade {
  width: 48px;
  height: 48px;
  border-radius: 14px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 800;
  font-family: 'Fraunces', Georgia, serif;
  color: white;
  font-size: 1.4rem;
  flex-shrink: 0;
  box-shadow: var(--shadow-sm);
}
/* History row grade chips — same theme-proof health colors as the main
   grade card so the Log shows the right color regardless of theme. */
.history-grade.grade-A { background: linear-gradient(135deg, var(--health-good-500), var(--health-good-700)); }
.history-grade.grade-B { background: linear-gradient(135deg, var(--health-lime-500), var(--health-good-500)); }
.history-grade.grade-C { background: linear-gradient(135deg, var(--health-caution-500), var(--health-caution-700)); }
.history-grade.grade-D { background: linear-gradient(135deg, var(--health-warn-500), var(--health-warn-700)); }
.history-grade.grade-F { background: linear-gradient(135deg, var(--health-bad-500), var(--health-bad-700)); }
.history-meta { flex: 1; min-width: 0; }
.history-title {
  font-weight: 600;
  margin: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  color: var(--ink-900);
}
.history-when { font-size: var(--text-secondary); color: var(--ink-500); margin: 0.15rem 0 0; }
.history-tag {
  display: inline-flex;
  align-items: center;
  gap: 0.2rem;
  font-size: var(--text-pill);          /* was 0.7rem — too small */
  padding: 0.2rem 0.6rem;
  border-radius: 999px;
  margin-left: 0.35rem;
  font-weight: 700;
  letter-spacing: 0.02em;
}
.history-tag.fav  { background: var(--amber-50); color: var(--amber-700); }
/* "Safe" tag uses health-good, not brand-green — so a slate theme doesn't
   make a safe-for-me tag look like a gray neutral chip. */
.history-tag.safe { background: var(--health-good-50); color: var(--health-good-700); }
/* SVG icons inside row tags or the grade slot were unsized — defaulted
   to their viewBox dimensions and blew the rows up vertically. Constrain
   them to readable inline icon sizes. */
.history-tag svg {
  width: 13px;
  height: 13px;
  flex-shrink: 0;
}
.history-grade > svg {
  width: 22px;
  height: 22px;
}

/* ============================================================
   Empty states
   ============================================================ */
.empty-state {
  text-align: center;
  padding: 2.75rem 1.5rem;
  color: var(--ink-500);
}
.empty-state .empty-illust {
  margin: 0 auto 0.75rem;
  width: 96px;
  height: 96px;
  opacity: 0.85;
}
.empty-state p { margin: 0.3rem 0; line-height: 1.45; }
.empty-state strong { color: var(--ink-900); font-family: 'Fraunces', Georgia, serif; font-size: 1.15rem; }

/* ============================================================
   Insights cards
   ============================================================ */
.insight-card {
  background: var(--bg-surface);
  margin: 0.5rem 1rem;
  padding: 1.15rem 1.25rem;
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
  border-left: 5px solid var(--ink-300);
}
.insight-card.trigger  { border-left-color: var(--rose-500); }
.insight-card.watching { border-left-color: var(--amber-500); }
.insight-card.safe     { border-left-color: var(--green-500); }
.insight-name {
  font-weight: 700;
  font-family: 'Fraunces', Georgia, serif;
  margin: 0 0 0.2rem;
  font-size: 1.1rem;
  letter-spacing: -0.01em;
}
.insight-meta { font-size: 0.85rem; color: var(--ink-500); margin: 0 0 0.5rem; }
.insight-detail { font-size: 0.92rem; color: var(--ink-700); margin: 0.3rem 0; line-height: 1.45; }
.insight-actions { display: flex; gap: 0.5rem; margin-top: 0.85rem; }
.insight-actions .btn { padding: 0.5rem 0.85rem; font-size: 0.85rem; }
/* Vote confirmation pill — replaces Feels right / Not me buttons after
   the user votes. Same vertical footprint as the buttons so the card
   doesn't reflow on tap. Muted by design — it's an acknowledgement,
   not a primary action. */
.insight-vote-pill {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  margin-top: 0.85rem;
  padding: 0.5rem 0.85rem;
  font-size: 0.85rem;
  color: var(--ink-700);
  background: var(--cream-100);
  border-radius: 999px;
  line-height: 1.3;
}
.insight-vote-pill svg { width: 16px; height: 16px; flex-shrink: 0; color: var(--green-500); }
.confidence-bar {
  height: 6px;
  background: var(--cream-100);
  border-radius: 999px;
  overflow: hidden;
  margin-top: 0.65rem;
}
.confidence-fill {
  height: 100%;
  background: linear-gradient(to right, var(--amber-500), var(--green-500));
  border-radius: 999px;
  transition: width 0.6s cubic-bezier(0.2, 0.7, 0.2, 1);
}

/* ============================================================
   Patterns rewrite (v2.41)
   ============================================================
   Four pieces: snapshot radar card at top, summary line, symptom-
   grouped collapsible pills for the watching list, plain-English
   insight cards with strength chips. All previewed and approved
   in chat before push. */

/* Snapshot card — radar chart of symptom averages */
.snapshot-card {
  text-align: center;
}
.snapshot-chart-wrap {
  margin: 0.5rem auto 0.25rem;
  max-width: 320px;
}
.snapshot-example-badge {
  display: inline-block;
  padding: 0.25rem 0.7rem;
  background: var(--cream-100);
  color: var(--ink-700);
  border-radius: 999px;
  font-size: 0.78rem;
  font-weight: 600;
  margin: 0 0 0.5rem;
  letter-spacing: 0.02em;
}
.snapshot-summary {
  margin: 0.4rem 0 0;
  color: var(--ink-900);
  font-weight: 600;
  font-size: 0.95rem;
}

/* One-line stats summary directly under the snapshot */
.insights-summary-line {
  margin: 0.75rem 1rem;
  padding: 0.8rem 1rem;
  background: var(--green-50);
  border-left: 4px solid var(--green-500);
  border-radius: 10px;
  color: var(--ink-900);
  font-size: 0.95rem;
  line-height: 1.45;
}
.insights-summary-line strong { color: var(--green-700); }

/* Watching list — collapsible symptom-area groups. Same shape as the
   v2.38 day-pills in the Eaten log, intentional — repeated UI patterns
   are easier to learn. */
.watching-symptom-group {
  margin: 0.75rem 1rem;
  background: var(--bg-surface);
  border: 1px solid var(--cream-200);
  border-radius: 14px;
  overflow: hidden;
  box-shadow: var(--shadow-sm);
}
.watching-symptom-header {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.9rem 1rem;
  background: transparent;
  border: none;
  cursor: pointer;
  text-align: left;
  color: var(--ink-900);
  font-family: inherit;
  font-size: inherit;
  min-height: 56px;
}
.watching-symptom-header:hover { background: rgba(0,0,0,0.025); }
.watching-symptom-label {
  flex: 1;
  font-size: 0.98rem;
  color: var(--ink-900);
  line-height: 1.25;
}
.watching-symptom-label strong { color: var(--amber-700); font-weight: 700; }
.watching-symptom-count {
  color: var(--ink-500);
  font-size: 0.85rem;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.watching-symptom-arrow {
  color: var(--ink-500);
  font-size: 0.8rem;
  width: 1.5em;
  text-align: center;
  flex-shrink: 0;
}
.watching-symptom-entries {
  border-top: 1px solid var(--cream-200);
  padding: 0.3rem 0;
}
/* Inside a symptom group, insight cards drop their card frame — the
   group pill is the card. Same treatment as v2.38 nested rows. */
.watching-symptom-entries .insight-card {
  margin: 0.25rem 0.5rem;
  box-shadow: none;
  border-radius: 10px;
  background: var(--cream-50, var(--cream-100));
}

/* v3.09 — Date sub-pills nested inside an expanded symptom group.
   Same shape as the parent watching-symptom-header, one level deeper.
   The cream background distinguishes "this is a child of the symptom
   pill" from the white parent. */
.watching-date-group {
  margin: 0.4rem 0.6rem;
  background: var(--cream-50, var(--cream-100));
  border: 1px solid var(--cream-200);
  border-radius: 10px;
  overflow: hidden;
}
.watching-date-header {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.65rem 0.8rem;
  background: transparent;
  border: none;
  cursor: pointer;
  text-align: left;
  color: var(--ink-900);
  font-family: inherit;
  font-size: inherit;
  min-height: 44px;
}
.watching-date-header:hover { background: rgba(0,0,0,0.025); }
.watching-date-label {
  flex: 1;
  font-size: 0.92rem;
  font-weight: 600;
  color: var(--ink-900);
}
.watching-date-count {
  color: var(--ink-500);
  font-size: 0.82rem;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.watching-date-arrow {
  color: var(--ink-500);
  font-size: 0.75rem;
  width: 1.5em;
  text-align: center;
  flex-shrink: 0;
}
.watching-date-entries {
  border-top: 1px solid var(--cream-200);
  padding: 0.2rem 0;
  background: var(--bg-surface);
}
.watching-date-empty {
  margin: 0.6rem 1rem;
  color: var(--ink-500);
  font-size: 0.88rem;
  font-style: italic;
}

/* v3.17 — Early Patterns reveal card. Sits at the top of the Patterns
   screen during trial days 7-13 only. Teal accent + bold eyebrow label
   so it reads as a "you've reached a milestone" highlight rather than
   ambient content. */
.early-patterns-card {
  border-left: 4px solid var(--teal-500, #70cbd0);
  background: linear-gradient(180deg, var(--teal-50, #e6f7f8) 0%, white 60%);
}
.early-patterns-header { display: flex; flex-direction: column; gap: 0.1rem; }
.early-patterns-eyebrow {
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  color: var(--teal-700, #1e6a6f);
}

/* v3.21 — Right-time Pro pill on Today screen. Sits just under the
   "Save today" button so the user sees it right after they've logged
   a symptom — the moment they're most invested in the journal. */
.today-pro-pill {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  width: 100%;
  margin-top: 0.75rem;
  padding: 0.7rem 0.95rem;
  background: linear-gradient(135deg, var(--teal-50, #e6f7f8), white);
  border: 1px solid var(--teal-300, #9ddee2);
  border-radius: 12px;
  color: var(--ink-900);
  font-family: inherit;
  font-size: 0.92rem;
  cursor: pointer;
  text-align: left;
}
.today-pro-pill:active { transform: scale(0.98); }
.today-pro-pill-text { flex: 1; line-height: 1.3; }
.today-pro-pill-text strong { color: var(--teal-700, #1e6a6f); }
.today-pro-pill-arrow {
  flex-shrink: 0;
  font-size: 1.1rem;
  color: var(--teal-700, #1e6a6f);
  font-weight: 700;
}

/* v3.16 — Trial-only feature-discovery nudge toast. Slides up from the
   bottom of the screen, sits above the tab bar. Single instance, fired
   by Nudges.fire() in nudges.js. Teal-on-white card with two-button
   action row: "Got it" (acknowledges, won't re-fire) and "Not for me"
   (dismisses permanently). */
.nudge-toast {
  position: fixed;
  left: 0.75rem;
  right: 0.75rem;
  bottom: calc(env(safe-area-inset-bottom, 0px) + 76px);
  padding: 0.9rem 1rem;
  background: var(--bg-surface);
  border: 1px solid var(--teal-300, #9ddee2);
  border-radius: 14px;
  box-shadow: 0 12px 36px rgba(0,0,0,0.18);
  z-index: 9000;
  transform: translateY(120%);
  opacity: 0;
  transition: transform 220ms ease, opacity 220ms ease;
  max-width: 540px;
  margin: 0 auto;
}
.nudge-toast.visible {
  transform: translateY(0);
  opacity: 1;
}
.nudge-toast-body {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
}
.nudge-toast-title {
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--teal-700, #1e6a6f);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}
.nudge-toast-text {
  font-size: 0.95rem;
  line-height: 1.4;
  color: var(--ink-900);
}
.nudge-toast-actions {
  display: flex;
  gap: 0.5rem;
  margin-top: 0.75rem;
}
.nudge-toast-actions .btn {
  flex: 1;
  padding: 0.55rem 0.7rem;
  font-size: 0.9rem;
}

/* v3.15 — Trial countdown pill on Home. Persistent visual scarcity nudge.
   Teal-on-cream so it reads as informational, not alarming. */
.trial-countdown-pill {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  width: calc(100% - 2rem);
  margin: 0.5rem 1rem 0;
  padding: 0.6rem 0.85rem;
  background: linear-gradient(135deg, var(--teal-50, #e6f7f8), var(--cream-50, #fbf9f5));
  border: 1px solid var(--teal-300, #9ddee2);
  border-radius: 999px;
  color: var(--ink-900);
  font-family: inherit;
  font-size: 0.92rem;
  font-weight: 600;
  cursor: pointer;
  text-align: left;
  box-shadow: 0 1px 3px rgba(0,0,0,0.04);
}
.trial-countdown-pill:active { transform: scale(0.98); }
.trial-countdown-icon { font-size: 1rem; flex-shrink: 0; }
.trial-countdown-text { flex: 1; line-height: 1.2; }
.trial-countdown-cta {
  flex-shrink: 0;
  padding: 0.25rem 0.7rem;
  font-size: 0.8rem;
  font-weight: 700;
  background: var(--teal-700, #1e6a6f);
  color: white;
  border-radius: 999px;
}

/* v3.10 — Velrae Pro feature list rows + Restaurant add-on row */
.pro-feature-ul { list-style: none; padding: 0; margin: 0; }
.pro-feature-row {
  display: flex;
  align-items: flex-start;
  gap: 0.5rem;
  padding: 0.35rem 0;
  font-size: 0.95rem;
  line-height: 1.35;
}
.pro-feature-check {
  color: var(--green-700, #1b5e20);
  font-weight: 700;
  flex-shrink: 0;
  margin-top: 0.05rem;
}
.pro-addon-row strong { font-size: 1rem; }
.addon-status-pill { font-weight: 600; letter-spacing: 0.02em; text-transform: uppercase; }

/* Insight card layout (v2.41 rewrite) — name + strength chip on top
   row, plain-English sentence under it, optional secondary line for
   strong patterns, then vote buttons or confirmation pill, then a
   muted "We notice — you decide." footer. */
.insight-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  margin-bottom: 0.4rem;
}
.insight-header .insight-name {
  margin: 0;
  flex: 1;
  min-width: 0;
}
.insight-chip {
  flex-shrink: 0;
  padding: 0.2rem 0.6rem;
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  border-radius: 999px;
  white-space: nowrap;
}
.insight-chip-trigger  { background: var(--rose-50, #ffe4e6); color: var(--rose-700, #be123c); }
.insight-chip-watching { background: var(--amber-50, #fef3c7); color: var(--amber-700, #b45309); }
.insight-chip-safe     { background: var(--green-50);          color: var(--green-700); }
.insight-sentence {
  margin: 0;
  font-size: 0.95rem;
  color: var(--ink-900);
  line-height: 1.45;
}
.insight-sentence strong { color: var(--ink-900); font-weight: 700; }
.insight-detail-secondary {
  margin: 0.5rem 0 0;
  font-size: 0.88rem;
  color: var(--ink-700);
  line-height: 1.4;
  font-style: italic;
}
.insight-footer {
  margin: 0.6rem 0 0;
  font-size: 0.75rem;
  color: var(--ink-500);
  font-style: italic;
  text-align: right;
}

/* ============================================================
   Patterns v2.42 — compact watching rows + SO WHAT line + SVG fix
   ============================================================
   Per direct user feedback after living with v2.41: the watching list
   gave the user no SO WHAT, cards took too much vertical space when a
   group had 50+ items, and an unconstrained SVG icon inside the
   Feels right / Not me buttons was rendering huge enough to dominate
   the card. Three coordinated changes below. */

/* SO WHAT to try — actionable green-tinted card at the top of every
   expanded watching symptom group AND at the top of the triggers
   section. Surfaces the top 3 items + a concrete two-week skip
   experiment. */
.so-what-line {
  margin: 0.5rem 0.75rem 0.85rem;
  padding: 0.85rem 1rem;
  background: var(--green-50);
  border-left: 4px solid var(--green-500);
  border-radius: 10px;
}
.so-what-label {
  margin: 0 0 0.35rem;
  font-size: 0.72rem;
  font-weight: 700;
  color: var(--green-700);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}
.so-what-body {
  margin: 0;
  color: var(--ink-900);
  font-size: 0.95rem;
  line-height: 1.45;
}
.so-what-body strong {
  color: var(--green-700);
  font-weight: 700;
}

/* Compact watching rows — replace the v2.41 stacked cards for items
   inside a watching symptom group. One row per ingredient. Sized so
   a 74-item group is ~3 screens of scroll, not 11+. The symptom name
   is omitted from each row (the group header already established it). */
.watching-row {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  padding: 0.6rem 0.8rem;
  margin: 0 0.5rem;
  background: var(--bg-surface);
  border-top: 1px solid var(--cream-100);
  min-height: 48px;
}
.watching-row:first-of-type {
  border-top: none;
}
.watching-row:hover {
  background: var(--cream-50, var(--cream-100));
}
.watching-row-name {
  flex: 1;
  min-width: 0;
  font-weight: 600;
  color: var(--ink-900);
  font-size: 0.93rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.watching-row-meta {
  flex-shrink: 0;
  color: var(--ink-500);
  font-size: 0.82rem;
  font-style: italic;
  white-space: nowrap;
}
.watching-row-actions {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  flex-shrink: 0;
}
.watching-row-vote {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  border: 1px solid var(--cream-200);
  background: var(--bg-surface);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  padding: 0;
  flex-shrink: 0;
  color: var(--ink-500);
  transition: background 0.12s ease, border-color 0.12s ease, color 0.12s ease;
}
.watching-row-vote:hover { background: var(--cream-100); }
.watching-row-vote svg {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
}
.watching-row-vote-yes:hover { color: var(--green-700); border-color: var(--green-200); }
.watching-row-vote-no:hover  { color: var(--rose-700); border-color: var(--rose-200, #fecdd3); }
.watching-row-voted-pill {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  font-size: 0.78rem;
  color: var(--ink-500);
  padding: 0.3rem 0.6rem;
  background: var(--cream-100);
  border-radius: 999px;
  font-style: italic;
}
.watching-row-voted-pill svg {
  width: 12px;
  height: 12px;
  flex-shrink: 0;
  color: var(--green-500);
}
.watching-row-voted-pill-dismissed svg { color: var(--ink-500); }

/* SVG SIZE FIX (v2.42) — the v2.41 "Feels right" / "Not me" buttons
   inside .insight-actions contained an inline <svg> with no explicit
   width/height, and the .btn class didn't constrain it either. The
   icon scaled up to fill its parent button slot, dominating the cell
   and dwarfing the button text. Explicit sizing puts it proportional. */
.insight-actions .btn svg {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
}

/* ============================================================
   Nutrition strip on results (v2.36 — label translator)
   ============================================================
   Sits between the "Grading for..." line and the "Did you eat this?"
   prompt. Muted on purpose — same visual weight as the grading-for
   line. Per Pillar 7 + product boundary: NEVER tier-colored, NEVER
   aggregated, NEVER target-compared. Just label numbers. */
.nutrition-strip {
  margin: 0.75rem 1rem;
  padding: 0.75rem 0.85rem;
  background: var(--cream-100);
  border-radius: 12px;
  border: 1px solid var(--cream-200);
}
.nutrition-strip-header {
  margin: 0 0 0.5rem;
  font-size: 0.78rem;
  color: var(--ink-500);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-weight: 600;
  text-align: center;
}
.nutrition-strip-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0.4rem;
}
.nutrition-strip-cell {
  text-align: center;
  padding: 0.35rem 0.2rem;
}
.nutrition-strip-label {
  margin: 0 0 0.15rem;
  font-size: 0.72rem;
  color: var(--ink-500);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.03em;
}
.nutrition-strip-value {
  margin: 0;
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--ink-900);
  font-variant-numeric: tabular-nums;
}

/* v2.37 — Protein density companion line. Lives directly under the
   nutrition strip when the build_muscle goal is active. Muted enough
   to read as a footnote, not a headline. */
.protein-density-note {
  margin: 0.4rem 1rem 0.75rem;
  padding: 0.45rem 0.85rem;
  font-size: 0.88rem;
  color: var(--ink-700);
  background: var(--green-50);
  border-radius: 10px;
  text-align: center;
}
.protein-density-note strong {
  color: var(--green-700);
  font-weight: 700;
}

/* ============================================================
   "Did you eat this?" prompt on results
   ============================================================ */
.ate-prompt {
  background: linear-gradient(135deg, var(--green-50), var(--cream-100));
  border: 1px solid var(--green-100);
  margin: 1rem;
  padding: 1.1rem 1.25rem;
  border-radius: var(--radius);
  /* v2.75 — Body is now center-aligned (the prior layout had a plate
     icon on the left and the body left-aligned next to it; the icon
     added no information and the alignment looked off-center relative
     to surrounding cards). */
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 0.875rem;
  animation: cardIn 0.4s ease;
}
.ate-prompt-icon {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: var(--bg-surface);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  color: var(--green-700);
  box-shadow: var(--shadow-sm);
}
.ate-prompt-icon svg { width: 24px; height: 24px; }
.ate-prompt-body { flex: 1; }
/* v2.75 — Centered body variant used by the icon-less prompt. */
.ate-prompt-body-centered { text-align: center; }
.ate-prompt-body-centered .ate-prompt-actions,
.ate-prompt-body-centered .ate-prompt-actions-three { justify-content: center; }
.ate-prompt p { margin: 0 0 0.5rem; font-weight: 600; color: var(--ink-900); }
/* v2.76 — Done-state: collapse the prompt into a single short line
   instead of holding the full card padding. User: "this huge window
   pops up with a check mark... takes up a third of the screen."
   Tight padding, inline check icon, no card-sized presence. */
.ate-prompt.ate-prompt-done {
  padding: 0.55rem 0.85rem;
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--green-700);
  background: var(--green-50);
  text-align: center;
}
.ate-prompt.ate-prompt-done svg {
  width: 18px;
  height: 18px;
  flex-shrink: 0;
}
.ate-prompt.ate-prompt-done strong {
  color: var(--ink-900);
}

/* 3-button post-scan prompt — two primary actions side-by-side, plus a
   subtle "Just checking" text link below. Keeps the most-likely answers
   prominent without forcing elderly users to weigh three equal options. */
.ate-prompt-actions {
  display: flex;
  gap: 0.5rem;
  margin-top: 0.75rem;
  flex-wrap: wrap;
}
.ate-prompt-actions .btn { flex: 1; min-width: 130px; }
/* v2.74 — Three-action variant. Tighter padding + smaller min-width so
   "I ate it / Bought it / Add to list" can fit on one row even on
   iPhone SE width. Buttons may wrap to 2 lines on the narrowest
   screens; that's acceptable — saves one full row vs the prior
   "2-up + full-width" layout. */
.ate-prompt-actions-three .btn {
  flex: 1 1 0;
  min-width: 0;
  padding: 0.65rem 0.55rem;
  font-size: 0.92rem;
  line-height: 1.2;
  white-space: normal;
}
.ate-prompt-skip {
  display: block;
  width: 100%;
  background: transparent;
  border: none;
  color: var(--ink-500);
  text-decoration: underline;
  text-underline-offset: 3px;
  font-family: inherit;
  font-size: 0.9rem;
  padding: 0.5rem;
  margin-top: 0.4rem;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
}
.ate-prompt-skip:hover { color: var(--ink-700); }
.ate-prompt .btn-row { margin-top: 0; }
.ate-prompt-done {
  background: var(--green-50);
  color: var(--green-700);
  font-weight: 600;
  text-align: center;
  display: block;
}

/* Mark fav / safe buttons row above grade card */
.scan-action-row {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  margin: 0.5rem 1rem 0;
}
.scan-action-row .btn {
  padding: 0.7rem 1rem;
  font-size: var(--text-secondary);
  background: var(--bg-surface);
  color: var(--ink-700);
  box-shadow: var(--shadow-sm);
  border: 1.5px solid var(--cream-200);
  justify-content: center;
}
.scan-action-row .btn.active {
  background: var(--green-50);
  color: var(--green-700);
  border-color: var(--green-300);
  font-weight: 700;
}

/* ============================================================
   Footer
   ============================================================ */
.footer {
  text-align: center;
  padding: 1.5rem 1rem;
  color: var(--ink-500);
  font-size: 0.78rem;
}

/* ============================================================
   Responsive
   ============================================================ */
@media (min-width: 640px) {
  .screen { max-width: 720px; margin: 0 auto; box-shadow: 0 0 28px rgba(40,30,20,0.06); background: transparent; min-height: 100vh; }
  .hero h1 { font-size: 3rem; }
  .tab-bar { max-width: 720px; margin: 0 auto; border-radius: 0 0 var(--radius-lg) var(--radius-lg); }
}


/* ============================================================
   Shopping list — big readable rows for in-store use
   ============================================================ */
.shopping-row {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  background: var(--bg-surface);
  border: 2px solid var(--cream-200);
  border-radius: 14px;
  padding: 1rem;
  margin-bottom: 0.6rem;
  min-height: 64px;
  cursor: pointer;
  transition: transform 0.08s ease, border-color 0.12s ease, background 0.12s ease;
}
.shopping-row:hover { border-color: var(--coral-100); background: var(--cream-100); }
.shopping-row:active { transform: scale(0.99); }

.shopping-row .shopping-query {
  flex: 1;
  font-size: 1.15rem;
  font-weight: 700;
  color: var(--ink-700);
  text-transform: uppercase;
  letter-spacing: 0.02em;
  word-break: break-word;
}
.shopping-row .shopping-scan-cta {
  background: var(--coral-50);
  color: var(--coral-700);
  font-weight: 700;
  padding: 0.5rem 0.85rem;
  border-radius: 999px;
  font-size: 0.9rem;
  white-space: nowrap;
}
.shopping-row .shopping-remove {
  background: transparent;
  border: none;
  color: var(--ink-500);
  font-size: 1.3rem;
  line-height: 1;
  padding: 0.25rem 0.5rem;
  cursor: pointer;
}
.shopping-row .shopping-remove:hover { color: var(--rose-700); }

/* "Got it" row — checked off, dimmed, with the brand they chose */
.shopping-row.got {
  background: var(--green-50);
  border-color: var(--green-200);
  cursor: default;
  opacity: 0.85;
}
.shopping-row.got .shopping-query { color: var(--green-700); }
.shopping-row.got .shopping-check {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--green-500);
  color: white;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.shopping-row.got .shopping-check svg { width: 16px; height: 16px; }
.shopping-row .shopping-product-meta {
  font-size: 0.85rem;
  color: var(--ink-700);
  font-weight: 500;
  letter-spacing: 0;
  text-transform: none;
  margin-top: 0.15rem;
  display: block;
}

/* Accept/try-again/skip block on the shopping result screen — big stacked
   buttons so an elderly person at the store can't miss them. */
.shopping-decision-card {
  background: linear-gradient(135deg, var(--coral-50), var(--cream-100));
  border: 1px solid var(--coral-100);
  border-radius: 14px;
  padding: 1rem;
  margin: 0 0 1rem;
}
.shopping-decision-card .shopping-decision-title {
  font-family: 'Fraunces', Georgia, serif;
  font-size: 1.05rem;
  font-weight: 700;
  margin: 0 0 0.15rem;
  color: var(--coral-700);
}
.shopping-decision-card .shopping-decision-sub {
  font-size: 0.92rem;
  color: var(--ink-700);
  margin: 0 0 0.75rem;
}
.shopping-decision-card .btn {
  width: 100%;
  min-height: 56px;
  font-size: 1.05rem;
  margin-bottom: 0.5rem;
}
.shopping-decision-card .btn:last-child { margin-bottom: 0; }
/* The Yes button is the primary intent — make it visually dominant so the
   user never wonders which to tap. Pillar 1: in-store, one obvious action. */
.shopping-decision-card .btn-primary {
  min-height: 64px;
  font-size: 1.15rem;
  font-weight: 700;
  box-shadow: 0 4px 14px rgba(45, 134, 98, 0.25);
}

/* ============================================================
   Update banner — appears when a new version is ready
   ============================================================ */
/* Non-intrusive bottom banner. Replaces the prior "instantly reload the
   page when the SW changes" behavior, which yanked elderly users back
   to the home screen mid-task. User taps Update Now when they're at a
   good stopping point — or Later to keep using the current version. */
.update-banner {
  position: fixed;
  left: 0;
  right: 0;
  bottom: calc(env(safe-area-inset-bottom, 0px) + 4.5rem);   /* sits above the tab bar */
  margin: 0 0.75rem;
  background: linear-gradient(135deg, var(--green-50) 0%, var(--cream-100) 100%);
  border: 1.5px solid var(--green-300);
  border-radius: 14px;
  padding: 0.85rem 1rem;
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  z-index: 200;
  box-shadow: 0 6px 18px rgba(40, 30, 20, 0.18);
  animation: updateBannerSlideUp 0.3s ease-out;
}
@keyframes updateBannerSlideUp {
  from { transform: translateY(20px); opacity: 0; }
  to   { transform: translateY(0);    opacity: 1; }
}
body.reduce-motion .update-banner { animation: none; }
.update-banner-body { display: flex; flex-direction: column; gap: 0.15rem; }
.update-banner-body strong { font-size: var(--text-body); color: var(--green-700); }
.update-banner-body span   { font-size: var(--text-secondary); color: var(--ink-700); }
.update-banner-actions { display: flex; gap: 0.5rem; }
.update-banner-actions .btn { flex: 1; min-height: 44px; padding: 0.55rem 0.9rem; font-size: var(--text-secondary); }
@media (min-width: 640px) {
  .update-banner { max-width: 720px; margin: 0 auto; left: 0; right: 0; }
}

/* ============================================================
   Scan-mode compact layout (small phones)
   ============================================================ */
/* When the user picks Camera or Barcode on a small-screen phone, the
   viewfinder is often pushed below the fold by the diary nudge banner,
   the mode-picker buttons, and the meal-entry card. Setting body class
   "scan-mode-visual" lets us collapse those non-essentials to give the
   viewfinder maximum vertical room. Tab bar at the bottom stays put. */
body.scan-mode-visual #diary-banner            { display: none !important; }
body.scan-mode-visual #scanning-for-meal-banner,
body.scan-mode-visual #shopping-context-banner { margin: 0.4rem 0.75rem !important; padding: 0.55rem 0.85rem !important; }
body.scan-mode-visual .scan-modes-compact      { gap: 0.4rem !important; }
body.scan-mode-visual .scan-modes-compact .mode-btn { min-height: 60px; padding: 0.45rem 0.25rem; }
body.scan-mode-visual .scan-modes-compact .mode-icon { width: 30px; height: 30px; margin-bottom: 0.15rem; }
body.scan-mode-visual .scan-modes-compact .mode-icon svg { width: 16px; height: 16px; }
body.scan-mode-visual #meal-entry-card { display: none !important; }
/* Slim the scan-type tabs (Food / Cosmetics / Recipe) since they take up
   space at the top of the scan card. They're still reachable, just smaller. */
body.scan-mode-visual .scan-type-toggle .tab-strip-btn { padding: 0.4rem 0.6rem; font-size: var(--text-secondary); }

/* Swipe-grab handle on top of the update banner — visual cue that it's dismissable */
.update-banner-grab {
  width: 44px;
  height: 5px;
  background: rgba(0,0,0,0.15);
  border-radius: 999px;
  margin: -0.2rem auto 0.35rem;
}
.update-banner-hint {
  font-size: var(--text-caption);
  color: var(--ink-500);
  margin-top: 0.15rem;
  font-style: italic;
}
.update-banner { transition: transform 0.18s ease-out, opacity 0.18s ease-out; }

/* When an update is pending but the banner was dismissed, mark the Settings
   gear with a coral dot so the user can find their way back. */
#open-settings { position: relative; }
body.update-pending #open-settings::after {
  content: '';
  position: absolute;
  top: 6px;
  right: 6px;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--coral-500);
  border: 2px solid white;
  box-shadow: 0 1px 4px rgba(0,0,0,0.25);
}

/* "Update is ready" card pinned at the top of Settings when applicable */
.settings-update-card {
  margin: 0 1rem 1rem;
  padding: 1rem;
  background: linear-gradient(135deg, var(--green-50) 0%, var(--cream-100) 100%);
  border: 1.5px solid var(--green-300);
  border-radius: 14px;
  box-shadow: var(--shadow-md);
}
.settings-update-card h3 { margin: 0 0 0.25rem; color: var(--green-700); font-size: var(--text-large); }
.settings-update-card p  { margin: 0 0 0.75rem; color: var(--ink-700); font-size: var(--text-secondary); }
.settings-update-card .btn { width: 100%; min-height: 56px; font-size: var(--text-large); }

/* ============================================================
   Ingredients-at-a-glance block (Results)
   ============================================================ */
/* Sits above the detailed per-ingredient rows on Results. Shows every
   recognized ingredient as a small chip, in label order, color-coded by
   tier — the way reading the ingredient panel on the box would look if
   the personalized grading were baked into the typography. */
.ingredient-glance-card {
  margin: 0 1rem 1rem;
  padding: 0.9rem 1rem 0.75rem;
  background: var(--bg-surface);
  border: 1px solid var(--cream-200);
  border-radius: 14px;
  box-shadow: var(--shadow-sm);
}
.ingredient-glance-heading {
  margin: 0 0 0.6rem;
  font-size: var(--text-secondary);
  color: var(--ink-700);
}
.ingredient-glance-heading strong { color: var(--ink-900); }
.ingredient-glance-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin-bottom: 0.7rem;
}
.ingredient-glance-chip {
  display: inline-block;
  font-size: var(--text-secondary);
  font-weight: 600;
  padding: 0.3rem 0.7rem;
  border-radius: 999px;
  border: 1.5px solid;
  line-height: 1.2;
}
.ingredient-glance-chip.tier-good           { background: var(--health-good-50);    color: var(--health-good-700);    border-color: var(--health-good-500); }
.ingredient-glance-chip.tier-moderate_good  { background: #f7fee7;                  color: #4d7c0f;                   border-color: var(--health-lime-500); }
.ingredient-glance-chip.tier-neutral        { background: var(--health-caution-50); color: var(--health-caution-700); border-color: var(--health-caution-500); }
.ingredient-glance-chip.tier-moderate_bad   { background: var(--health-warn-50);    color: var(--health-warn-700);    border-color: var(--health-warn-500); }
.ingredient-glance-chip.tier-bad            { background: var(--health-bad-50);     color: var(--health-bad-700);     border-color: var(--health-bad-500); }

.ingredient-glance-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 0.85rem;
  font-size: var(--text-caption);
  color: var(--ink-700);
  padding-top: 0.6rem;
  border-top: 1px solid var(--cream-100);
}
/* Legend rows mirror the chip prefix: same icon, same color, no wrapper
   circle. The shape itself IS the mark — a person can match legend to
   chip by silhouette alone, no decoding required. */
.ingredient-glance-legend .legend-row {
  display: inline-flex; align-items: center; gap: 0.35rem;
}
.legend-row.tier-good          { color: var(--health-good-700); }
.legend-row.tier-moderate_good { color: #4d7c0f; }
.legend-row.tier-neutral       { color: var(--health-caution-700); }
.legend-row.tier-moderate_bad  { color: var(--health-warn-700); }
.legend-row.tier-bad           { color: var(--health-bad-700); }

/* Tier icon — shared by chips and the legend. Sized to fill the chip
   vertically so it's actually legible from arm's length. Color comes
   from the parent tier-* class via currentColor inside the SVG. */
.tier-icon {
  width: 20px;
  height: 20px;
  flex-shrink: 0;
  vertical-align: -5px;
  margin-right: 0.25rem;
}
.ingredient-glance-chip .tier-icon {
  width: 22px;
  height: 22px;
  vertical-align: -6px;
}

/* ============================================================
   v4.00 — Personal care skin-first result card
   ============================================================
   A deliberately DIFFERENT look from the food grade card: softer, calmer,
   more whitespace, a self-care feel — so the user senses they've switched
   from "kitchen" to "bathroom." Condition is the headline; product is
   secondary; NO big A-F letter grade (a giant "F" on a moisturizer reads as
   fear-mongering — the trap our research said to avoid). All colors use brand
   tokens (--ink-*, --bg-surface, --coral-*) so dark mode flips automatically.
   Inert until the cosmetics-v2 flag renders .personal-care-result. */
.personal-care-result {
  display: flex;
  flex-direction: column;
  gap: 0.9rem;
  padding: 0.25rem 0 1rem;
}
.personal-care-header {
  text-align: center;
  padding: 0.5rem 0.5rem 0.25rem;
}
.personal-care-eyebrow {
  display: inline-block;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--coral-700);   /* brand purple — the cosmetics accent */
  margin-bottom: 0.35rem;
}
.personal-care-headline {
  font-family: 'Fraunces', Georgia, serif;
  font-size: 1.5rem;
  line-height: 1.2;
  margin: 0 0 0.3rem;
  color: var(--ink-900);
}
.personal-care-product {
  margin: 0;
  font-size: 0.95rem;
  color: var(--ink-500);
}
.personal-care-buckets {
  display: flex;
  flex-direction: column;
  gap: 0.7rem;
}
/* Soft, rounded, airy cards — the self-care signature. */
.personal-care-bucket {
  background: var(--bg-surface);
  border: 1px solid var(--cream-200);
  border-radius: 16px;
  padding: 1rem 1.1rem;
  box-shadow: var(--shadow-sm);
}
.personal-care-bucket-watch    { border-left: 4px solid var(--health-warn-500, #ea580c); }
.personal-care-bucket-supports { border-left: 4px solid var(--health-good-500, #2d8662); }
.personal-care-bucket-clear    { border-left: 4px solid var(--cream-300); }
.personal-care-bucket-title {
  margin: 0 0 0.4rem;
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--ink-900);
}
.personal-care-bucket-kind {
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-500);
  background: var(--cream-100);
  padding: 0.1rem 0.45rem;
  border-radius: 999px;
  vertical-align: middle;
  margin-left: 0.35rem;
}
.personal-care-bucket-status {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  margin: 0;
  font-size: 0.92rem;
  font-weight: 600;
}
.personal-care-bucket-status svg { width: 18px; height: 18px; flex-shrink: 0; }
.personal-care-watch    { color: var(--health-warn-700, #9a3412); }
.personal-care-supports { color: var(--health-good-700, #1a5d44); }
.personal-care-clear    { color: var(--ink-500); }
.personal-care-hits {
  list-style: none;
  margin: 0.55rem 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
}
.personal-care-hits li {
  font-size: 0.92rem;
  color: var(--ink-700);
  line-height: 1.35;
}
.personal-care-axis {
  font-size: 0.78rem;
  color: var(--ink-500);
  display: block;
}
.personal-care-overall {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  text-align: center;
  padding: 0.6rem 0.5rem 0;
  border-top: 1px solid var(--cream-200);
  margin-top: 0.2rem;
}
.personal-care-overall-verdict {
  font-size: 1rem;
  font-weight: 700;
  color: var(--ink-900);
}
.personal-care-overall-name {
  font-size: 0.85rem;
  color: var(--ink-500);
}
.personal-care-note {
  text-align: center;
  margin: 0.2rem 0.5rem 0;
  line-height: 1.4;
}
/* v4.00 — Dark-mode: the soft accent eyebrow brightens (matches the v3.99
   fine-detail sweep so it never lands dark-on-dark). The bucket cards already
   use --bg-surface / --ink-* which flip; only the accent needs lifting. */
:root:not([data-color-mode="light"]) .personal-care-eyebrow { color: #c9a8e0; }
:root:not([data-color-mode="light"]) .personal-care-watch    { color: #f0a878; }
:root:not([data-color-mode="light"]) .personal-care-supports { color: #74d99b; }
:root[data-color-mode="dark"] .personal-care-eyebrow { color: #c9a8e0; }
:root[data-color-mode="dark"] .personal-care-watch    { color: #f0a878; }
:root[data-color-mode="dark"] .personal-care-supports { color: #74d99b; }

/* ===== v4.14 — Personal-care "Aura" skin-first results card =====
   A deliberately non-food look: gradient verdict hero + soft peach/mint tiles.
   Body text uses app --ink-*/--bg-surface/--cream-* tokens (theme-aware). The
   peach/mint tints are local vars, flipped for dark mode below. */
.pc-aura{ border-radius:24px; overflow:hidden; box-shadow:0 18px 48px rgba(40,20,60,.16);
  --pca-peach-bg:#fcebe1; --pca-peach-ink:#9a3412; --pca-peach-line:#f0c4ab;
  --pca-mint-bg:#e4f3ea; --pca-mint-ink:#1a5d44; --pca-mint-line:#b9ddc8;
  --pca-neu:#8a8594; --pca-neu-bg:#efecf1; }
.pc-aura-hero{ position:relative; padding:30px 24px 26px; color:#fff;
  background:linear-gradient(152deg,#7a4bb0 0%,#562a86 52%,#3c1f5e 100%); }
.pc-aura-hero:before{ content:""; position:absolute; inset:0; pointer-events:none;
  background:radial-gradient(120% 80% at 12% 0%, rgba(255,255,255,.26), rgba(255,255,255,0) 60%); }
.pc-aura-hero > *{ position:relative; }
.pc-aura-eyebrow{ font-size:.7rem; font-weight:700; letter-spacing:.2em; text-transform:uppercase; opacity:.85; }
.pc-aura-verdict{ font-family:'Fraunces',Georgia,serif; font-weight:600; font-size:1.95rem; line-height:1.13; margin:.5rem 0 .45rem; letter-spacing:-.015em; }
.pc-aura-prod{ font-size:.95rem; opacity:.92; }
.pc-aura-read{ font-size:.74rem; opacity:.74; margin-top:.5rem; }
.pc-aura-chips{ display:flex; flex-wrap:wrap; gap:.4rem; margin-top:1.05rem; align-items:center; }
.pc-aura-chips-lab{ font-size:.74rem; opacity:.82; }
.pc-aura-chip{ font-size:.78rem; font-weight:600; color:#fff; background:rgba(255,255,255,.2); border:1px solid rgba(255,255,255,.46); padding:.22rem .7rem; border-radius:999px; }
.pc-aura-body{ background:var(--bg-surface,#fff); padding:20px 20px 22px; }
.pc-aura-seclab{ display:flex; align-items:center; gap:.4rem; font-size:.72rem; font-weight:800; letter-spacing:.12em; text-transform:uppercase; margin:0 2px 11px; }
.pc-aura-seclab-like{ margin-top:20px; color:var(--pca-mint-ink); }
.pc-aura-seclab-watch{ color:var(--pca-peach-ink); }
.pc-aura-n{ font-weight:700; opacity:.6; }
.pc-aura-tile{ border-radius:16px; padding:13px 15px; margin-bottom:9px; border:1px solid transparent; }
.pc-aura-watch{ background:var(--pca-peach-bg); border-color:var(--pca-peach-line); }
.pc-aura-like{ background:var(--pca-mint-bg); border-color:var(--pca-mint-line); }
.pc-aura-clear{ background:var(--pca-neu-bg); }
.pc-aura-tile-row{ display:flex; align-items:center; gap:.5rem; }
.pc-aura-name{ font-size:1rem; font-weight:700; color:var(--ink-900,#1f1d1a); }
.pc-aura-tag{ margin-left:auto; font-size:.66rem; font-weight:700; letter-spacing:.03em; text-transform:uppercase; padding:.17rem .52rem; border-radius:999px; white-space:nowrap; }
.pc-aura-watch .pc-aura-tag{ color:var(--pca-peach-ink); background:rgba(154,52,18,.13); }
.pc-aura-like .pc-aura-tag{ color:var(--pca-mint-ink); background:rgba(26,93,68,.14); }
.pc-aura-why{ font-size:.86rem; line-height:1.42; color:var(--ink-700,#3d3a36); margin-top:.4rem; }
.pc-aura-allwrap{ margin-top:20px; border-top:1px solid var(--cream-200,#ede4d3); padding-top:15px; }
.pc-aura-allhead{ font-size:.72rem; font-weight:800; letter-spacing:.1em; text-transform:uppercase; color:var(--ink-500,#5c574e); margin-bottom:10px; }
.pc-aura-ings{ display:flex; flex-wrap:wrap; gap:7px; }
.pc-aura-ig{ font-size:.8rem; font-weight:600; padding:.27rem .6rem; border-radius:9px; display:inline-flex; align-items:center; gap:.4rem; }
.pc-aura-ig:before{ content:""; width:7px; height:7px; border-radius:50%; }
.pc-aura-ig-bad{ color:var(--pca-peach-ink); background:var(--pca-peach-bg); } .pc-aura-ig-bad:before{ background:#c2410c; }
.pc-aura-ig-cau{ color:var(--pca-peach-ink); background:var(--pca-peach-bg); } .pc-aura-ig-cau:before{ background:#e8763e; }
.pc-aura-ig-good{ color:var(--pca-mint-ink); background:var(--pca-mint-bg); } .pc-aura-ig-good:before{ background:#2d8662; }
.pc-aura-ig-neu{ color:var(--pca-neu); background:var(--pca-neu-bg); } .pc-aura-ig-neu:before{ background:var(--pca-neu); }
.pc-aura-note{ text-align:center; font-size:.74rem; color:var(--ink-500,#5c574e); line-height:1.45; margin-top:16px; padding:0 4px; }
:root[data-color-mode="dark"] .pc-aura, :root:not([data-color-mode="light"]) .pc-aura{
  --pca-peach-bg:#3a241b; --pca-peach-ink:#f0a878; --pca-peach-line:#5a3526;
  --pca-mint-bg:#1c3328; --pca-mint-ink:#74d99b; --pca-mint-line:#2c4a3a;
  --pca-neu:#9a93a6; --pca-neu-bg:#2b2435; }
/* v4.21 — decision-first additions */
.pc-aura-reason{ font-size:.95rem; line-height:1.45; opacity:.95; margin-top:.15rem; }
.pc-aura-reason b{ font-weight:700; }
.pc-aura-chip-goal{ background:rgba(255,255,255,.1); border-style:dashed; }
.pc-aura-factor{ background:var(--pca-peach-bg); border:1px solid var(--pca-peach-line); border-radius:16px; padding:13px 15px; margin-bottom:9px; }
.pc-aura-factor-top{ display:flex; align-items:center; gap:.4rem; flex-wrap:wrap; }
.pc-aura-fav{ background:var(--pca-mint-bg); border:1px solid var(--pca-mint-line); border-radius:16px; padding:13px 15px; }
.pc-aura-fav-line{ font-size:.92rem; color:var(--ink-900,#1f1d1a); margin-bottom:.5rem; line-height:1.4; }
.pc-aura-fav-line:last-child{ margin-bottom:0; }
.pc-aura-fav-line b{ color:var(--pca-mint-ink); }
.pc-aura-more{ font-size:.8rem; color:var(--ink-500,#5c574e); margin:.3rem 2px 0; }
.pc-aura-details{ margin:14px 4px 4px; }
.pc-aura-details summary{ font-size:.86rem; font-weight:600; color:#15565a; cursor:pointer; }
:root[data-color-mode="dark"] .pc-aura-details summary, :root:not([data-color-mode="light"]) .pc-aura-details summary{ color:#7ed3d7; }
.pc-aura-details .pc-aura-ings{ margin-top:11px; }
/* v4.25 — visible, colour-coded full ingredient list on the verdict card */
.pc-aura-allcard{ background:var(--bg-surface,#fff); border:1px solid var(--cream-200,#ede4d3); border-radius:18px; margin:12px .25rem 0; padding:14px 16px; box-shadow:var(--shadow-sm,0 1px 2px rgba(40,30,20,.05)); }
.pc-aura-allcard .pc-aura-allhead{ margin-bottom:6px; }
.pc-aura-ingrow{ display:flex; align-items:center; gap:.6rem; padding:.45rem 0; border-bottom:1px solid var(--cream-100,#f6f0e6); }
.pc-aura-ingrow:last-child{ border-bottom:0; }
.pc-aura-ingdot{ width:11px; height:11px; border-radius:50%; flex-shrink:0; }
.pc-aura-ingnm{ flex:1; font-size:.92rem; color:var(--ink-900,#1f1d1a); }
.pc-aura-ingtl{ font-size:.78rem; font-weight:700; white-space:nowrap; }
.pc-aura-ingtl-unk{ color:var(--ink-500,#5c574e); font-weight:600; }

/* v4.47 — Personal-care Skin Score (3 tiers, distinct from food A-F) */
.pc-skin-score{display:inline-flex;align-items:center;gap:0.6rem;margin:0.2rem 0 0.55rem;padding:0.45rem 0.9rem;border-radius:14px;color:#fff}
.pc-skin-good{background:#2e9e6b}.pc-skin-ok{background:#caa12a}.pc-skin-bad{background:#d1495b}.pc-skin-unk{background:#8a8594}
.pc-skin-num{font-family:'Fraunces',Georgia,serif;font-size:2.1rem;font-weight:800;line-height:1}
.pc-skin-out{font-size:0.85rem;font-weight:600;opacity:0.8;margin-left:1px}
.pc-skin-tier{font-size:1.05rem;font-weight:700}
.history-skin{flex-shrink:0;width:46px;height:46px;border-radius:12px;display:flex;align-items:center;justify-content:center;font-weight:800;font-size:1.2rem;color:#fff}
.history-skin-out{font-size:0.5em;font-weight:600;opacity:0.85;margin-left:1px}
.history-skin.skin-good{background:#2e9e6b}.history-skin.skin-ok{background:#caa12a}.history-skin.skin-bad{background:#d1495b}.history-skin.skin-unk{background:#8a8594}

/* v4.48 — AI-estimate badge for unknown personal-care ingredients */
.pc-ai-badge{display:inline-block;font-size:0.62rem;font-weight:700;text-transform:uppercase;letter-spacing:0.04em;background:#efe7fb;color:#5a2b8c;padding:0.05rem 0.4rem;border-radius:999px;vertical-align:middle;margin-left:0.25rem}

/* v4.49 — Prominent Skin Score hero + food-parity ingredient detail rows */
.pc-score2{display:flex;flex-direction:column;align-items:center;gap:6px;margin:.35rem 0 .5rem}
.pc-score2-pill{display:inline-flex;align-items:baseline;gap:2px;background:var(--pcsc,#8a8594);color:#fff;border-radius:16px;padding:.45rem 1.15rem;box-shadow:0 4px 14px rgba(0,0,0,.16)}
.pc-score2-num{font-family:'Fraunces',Georgia,serif;font-size:2.9rem;font-weight:800;line-height:1}
.pc-score2-out{font-size:1rem;font-weight:700;opacity:.85}
.pc-score2-meta{text-align:center}
.pc-score2-cap{font-size:.66rem;font-weight:800;letter-spacing:.14em;text-transform:uppercase;color:#8a8594}
.pc-score2-tier{font-size:1.15rem;font-weight:800;color:var(--pcsc,#444);margin-top:1px}
.pc-aura-mix{display:flex;gap:.5rem;align-items:flex-start;background:#fff7e6;border:1px solid #f0d79a;color:#6b4a07;border-radius:14px;padding:10px 13px;margin:10px .25rem 0;font-size:.86rem;line-height:1.4}
.pc-aura-mix svg{width:16px;height:16px;flex:none;margin-top:1px}
.pc-aura-ainote{font-size:.8rem;color:var(--ink-500,#5c574e);margin:.1rem .25rem .5rem;line-height:1.4}
/* v4.74 — "still researching" card, surfaced at the top of the PC verdict */
.pc-research{margin:12px .25rem 4px;padding:11px 13px;border:1px solid #e7ddf2;border-radius:14px;background:#faf7fd}
.pc-research-msg{color:#4b246b;font-size:.88rem;font-weight:600;line-height:1.4;margin:0 0 .35rem}
.pc-ai-wrap{display:block}
.pc-ing{border:1px solid var(--cream-200,#ede4d3);border-radius:14px;margin:8px .25rem 0;background:var(--bg-surface,#fff);overflow:hidden}
.pc-ing-head{display:flex;align-items:center;gap:.6rem;width:100%;background:none;border:0;padding:11px 13px;text-align:left;cursor:pointer;font:inherit;color:inherit}
.pc-ing-head .tier-badge{flex:none}
.pc-ing-main{flex:1;min-width:0}
.pc-ing-name{display:block;font-weight:700;font-size:.95rem;color:var(--ink-900,#1f1d1a)}
.pc-ing-sub{display:flex;flex-wrap:wrap;align-items:center;gap:.4rem .6rem;margin-top:2px;font-size:.8rem}
.pc-ing-tierlab{font-weight:700}
.pc-ing-flag{display:inline-flex;align-items:center;gap:.2rem;color:#9a3412;font-weight:600}
.pc-ing-flag-good{color:#1a5d44}
.pc-ing-flag svg{width:13px;height:13px;flex:none}
.pc-ing-chev{flex:none;color:var(--ink-500,#8a8594);transition:transform .18s ease}
.pc-ing.open .pc-ing-chev{transform:rotate(180deg)}
.pc-ing-detail{display:none;padding:0 13px 12px 13px;font-size:.88rem;line-height:1.5;color:var(--ink-800,#33302b)}
.pc-ing.open .pc-ing-detail{display:block}
.pc-ing-detail p{margin:.2rem 0 .45rem}
.pc-ing-d-what{color:var(--ink-700,#5c574e)}
.pc-ing-d-caveat{color:var(--ink-600,#6b6577);font-style:italic}
.pc-ing-d-flag,.pc-ing-d-good{display:flex;gap:.35rem;align-items:flex-start}
.pc-ing-d-flag{color:#9a3412}
.pc-ing-d-good{color:#1a5d44}
.pc-ing-d-flag svg,.pc-ing-d-good svg{width:15px;height:15px;flex:none;margin-top:2px}
.pc-ing-d-src{font-size:.78rem;color:var(--ink-500,#8a8594)}
.pc-ing-pending .pc-ing-chev{opacity:.4}

/* v4.50 — personal-care identity (purple), square score badge, subscript
   for-your line, bottom fav/safe icons */
.pc-mode .section-heading{}
.pc-aura-foryou{font-size:.8rem;opacity:.9;margin-top:.95rem;line-height:1.4}
.pc-sq{position:relative;width:128px;height:128px;margin:.45rem auto .15rem}
.pc-sq-svg{width:100%;height:100%;display:block}
.pc-sq-track{fill:#fff;stroke:rgba(20,10,30,.10);stroke-width:9}
.pc-sq-fill{fill:none;stroke:var(--pcsq,#8a8594);stroke-width:9;stroke-linecap:round;transition:stroke-dashoffset .9s cubic-bezier(.2,.7,.2,1)}
.pc-sq-inner{position:absolute;inset:0;display:flex;align-items:center;justify-content:center}
.pc-sq-num{font-family:'Fraunces',Georgia,serif;font-size:2.7rem;font-weight:800;line-height:1;color:var(--pcsq,#444)}
.pc-sq-out{font-size:1.05rem;font-weight:700;color:#8a8594;align-self:flex-end;margin:0 0 .6rem 2px}
.pc-sq-tier{text-align:center;color:#fff;font-weight:800;font-size:1.2rem;margin-top:3px;letter-spacing:.01em}
.scan-action-row.pc-favsafe{display:flex;gap:.6rem;justify-content:center;margin:16px .25rem 4px}
.pc-favsafe-btn{display:inline-flex;align-items:center;gap:.4rem;border:1.5px solid var(--cream-200,#ede4d3);background:var(--bg-surface,#fff);color:var(--ink-700,#5c574e);border-radius:999px;padding:.5rem 1rem;font-size:.84rem;font-weight:700;cursor:pointer}
.pc-favsafe-btn svg{width:16px;height:16px}
.pc-favsafe-btn.active{border-color:#4b246b;color:#4b246b;background:#f3edf9}

/* v4.51 — personal-care verdict = food grade card clone, SQUARE ring */
.pc-ring-wrap svg{transform:none}
.pc-card-actions{position:absolute;top:14px;right:14px;display:flex;gap:8px;z-index:2}
.pc-cardact-btn{display:inline-flex;align-items:center;justify-content:center;width:42px;height:42px;border-radius:999px;border:1.5px solid rgba(255,255,255,.55);background:rgba(255,255,255,.16);color:#fff;cursor:pointer;padding:0}
.pc-cardact-btn svg{width:20px;height:20px}
.pc-cardact-btn.active{background:#fff;color:#3a2f2f;border-color:#fff}

/* v4.52 — collapsible "pill" sections (ingredients, better picks) */
.pc-collapse{margin:8px .25rem 0;border:1px solid var(--cream-200,#ede4d3);border-radius:14px;background:var(--bg-surface,#fff);overflow:hidden}
.pc-collapse-head{display:flex;align-items:center;justify-content:space-between;gap:.6rem;width:100%;background:none;border:0;padding:14px 16px;text-align:left;cursor:pointer;font:inherit;font-weight:700;font-size:1rem;color:var(--ink-900,#1f1d1a)}
.pc-collapse-label{flex:1;min-width:0}
.pc-collapse-chev{flex:none;color:var(--ink-500,#8a8594);transition:transform .18s ease}
.pc-collapse.open .pc-collapse-chev{transform:rotate(180deg)}
.pc-collapse-body{display:none;padding:2px 12px 12px}
.pc-collapse.open .pc-collapse-body{display:block}
.pc-collapse-body .pc-ing{margin-left:0;margin-right:0}
.pc-collapse-body .alternatives-card{margin:8px 0 0}
.pc-collapse-body .pc-aura-ainote{margin:6px 2px 4px}

/* v4.53 — fixed brand-color frame on the personal-care verdict card
   (purple). Inset ring => noticeable but no change to card dimensions.
   Brand colors never bend to the theme. Food card gets teal next. */
.grade-card.pc-grade{box-shadow:inset 0 0 0 10px #4b246b, var(--shadow-md)}

/* v4.55 — "Personal Care" identifier on the verdict card (so you always
   know which check you are looking at) + clearer ate-prompt option pills */
.pc-card-eyebrow{margin:0 0 .35rem;text-align:center;font-size:.72rem;font-weight:800;letter-spacing:.16em;text-transform:uppercase;color:rgba(255,255,255,.88)}
.ate-prompt-actions .btn-secondary{border:1.5px solid var(--cream-300,#d8d2c4);background:var(--bg-surface,#fff)}

/* v4.57 — fixed teal brand frame on the FOOD verdict card (matches the
   purple on personal care). Inset ring => noticeable, no dimension change. */
.grade-card.food-grade{box-shadow:inset 0 0 0 10px #70cbd0, var(--shadow-md)}

/* v4.58 — note shown on the grade card when AI-identified items adjusted it */
.grade-ai-note{margin:.5rem 0 0;font-size:.72rem;opacity:.85;color:#fff}
