/* ---------------------------------------------------------------------------
   Design tokens. The light palette is defined on :root so no colour is ever
   only defined inside a media query; dark overrides follow.
   --------------------------------------------------------------------------- */
:root {
  color-scheme: light;
  --bg: #f4f7f3;
  --surface: #ffffff;
  --surface-2: #f7faf7;
  --text: #16211a;
  --text-muted: #5c6b62;
  --accent: #1f6b48;
  --accent-hover: #185639;
  --accent-contrast: #ffffff;
  --accent-soft: #dcf0e5;
  --accent-soft-text: #134f33;
  --line: #dbe4dd;
  --line-strong: #c3d0c7;
  --carb: #a2661f;
  --carb-soft: #fbeed8;
  --fat: #6b53a1;
  --fat-soft: #ece6f8;
  --info-bg: #eef4fb;
  --info-text: #234668;
  --warn-bg: #fdf3dc;
  --warn-text: #6b4d10;
  --danger: #a3372c;
  --danger-bg: #fbeceb;
  --focus: #0b63c5;
  /* Quick-action menu: one circle per kind of entry, so a row is recognised
     before it is read. */
  --action-meal: #1f6b48;
  --action-recipe: #5c47a0;
  --action-activity: #1f5fa8;
  --action-body: #a2661f;
  --action-contrast: #ffffff;
  --shadow: 0 6px 24px rgba(31, 63, 45, 0.08);
  --radius: 18px;
  --radius-sm: 10px;
}

:root[data-theme="dark"],
:root[data-theme="system"] {
  color-scheme: light;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --bg: #0f1512;
    --surface: #172019;
    --surface-2: #1d2822;
    --text: #e9f2ec;
    --text-muted: #a0b0a6;
    --accent: #5cc490;
    --accent-hover: #79d3a6;
    --accent-contrast: #0b1a12;
    --accent-soft: #1e3a2b;
    --accent-soft-text: #a7e6c5;
    --line: #2a382f;
    --line-strong: #3a4c41;
    --carb: #e0aa63;
    --carb-soft: #372a17;
    --fat: #b19ce4;
    --fat-soft: #2b2340;
    --info-bg: #16283a;
    --info-text: #b7d5f2;
    --warn-bg: #3a2f14;
    --warn-text: #f0d79a;
    --danger: #f0938a;
    --danger-bg: #3a1f1c;
    --focus: #7fb6ff;
    --action-meal: #5cc490;
    --action-recipe: #b19ce4;
    --action-activity: #7fb6ff;
    --action-body: #e0aa63;
    --action-contrast: #0b1a12;
    --shadow: none;
  }
}

:root[data-theme="dark"] {
  color-scheme: dark;
  --bg: #0f1512;
  --surface: #172019;
  --surface-2: #1d2822;
  --text: #e9f2ec;
  --text-muted: #a0b0a6;
  --accent: #5cc490;
  --accent-hover: #79d3a6;
  --accent-contrast: #0b1a12;
  --accent-soft: #1e3a2b;
  --accent-soft-text: #a7e6c5;
  --line: #2a382f;
  --line-strong: #3a4c41;
  --carb: #e0aa63;
  --carb-soft: #372a17;
  --fat: #b19ce4;
  --fat-soft: #2b2340;
  --info-bg: #16283a;
  --info-text: #b7d5f2;
  --warn-bg: #3a2f14;
  --warn-text: #f0d79a;
  --danger: #f0938a;
  --danger-bg: #3a1f1c;
  --focus: #7fb6ff;
  --action-meal: #5cc490;
  --action-recipe: #b19ce4;
  --action-activity: #7fb6ff;
  --action-body: #e0aa63;
  --action-contrast: #0b1a12;
  --shadow: none;
}

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", sans-serif;
  font-size: 15px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

.admin-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 20px;
}

.plain-list {
  list-style: none;
  padding: 0;
  margin: 0;
}

.plain-list li {
  padding: 10px 0;
  border-bottom: 1px solid var(--line);
}

.ai-badge,
.ai-state {
  display: inline-flex;
  align-items: center;
  border-radius: 999px;
  padding: 3px 9px;
  font-size: 12px;
  font-weight: 700;
  background: var(--info-bg);
  color: var(--info-text);
}

.ai-completed {
  background: var(--accent-soft);
  color: var(--accent-soft-text);
}

.ai-failed {
  background: var(--danger-bg);
  color: var(--danger);
}

.button-row {
  display: flex;
  gap: 10px;
  margin-top: 18px;
  flex-wrap: wrap;
}

.provenance {
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  padding: 12px;
  background: var(--surface-2);
  border-radius: var(--radius-sm);
  font-size: 12px;
}

.copy-field {
  display: flex;
  gap: 8px;
  align-items: center;
  flex-wrap: wrap;
}

.copy-field input {
  flex: 1 1 260px;
  font-family: var(--font-mono, ui-monospace, monospace);
  font-size: 13px;
}

button,
input,
select,
textarea {
  font: inherit;
  color: inherit;
}

a {
  color: var(--accent);
  text-decoration: none;
}

a:hover {
  text-decoration: underline;
}

/* A single visible focus ring for every interactive element. */
:where(a, button, input, select, textarea, [tabindex]):focus-visible {
  outline: 3px solid var(--focus);
  outline-offset: 2px;
  border-radius: 6px;
}

@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;
  }
}

/* Visually hidden but available to assistive technology. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* --------------------------------------------------------------------- Layout */

.shell {
  max-width: 1180px;
  margin: 0 auto;
  padding: 24px 20px;
}

/* Only pages that actually render the floating action button need extra
   bottom clearance for it; everyone else should stop scrolling right after
   the last panel. */
.shell--with-fab {
  padding-bottom: 100px;
}

.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 28px;
  flex-wrap: wrap;
}

.brand {
  display: flex;
  align-items: center;
  gap: 10px;
  font-weight: 700;
  font-size: 19px;
  color: var(--text);
}

.brand:hover {
  text-decoration: none;
}

.brand-mark {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: var(--radius-sm);
  background: var(--accent);
  color: var(--accent-contrast);
  font-weight: 800;
}

.nav {
  display: flex;
  gap: 4px;
  background: var(--surface);
  padding: 5px;
  border-radius: 14px;
  border: 1px solid var(--line);
}

.nav a {
  padding: 8px 13px;
  border-radius: var(--radius-sm);
  color: var(--text-muted);
  font-size: 14px;
  font-weight: 500;
}

.nav a:hover {
  background: var(--surface-2);
  color: var(--text);
  text-decoration: none;
}

.nav a[aria-current="page"] {
  background: var(--accent-soft);
  color: var(--accent-soft-text);
  font-weight: 600;
}

.topbar-actions {
  display: flex;
  align-items: center;
  gap: 8px;
}

.back-button {
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  padding: 0;
  border-radius: 50%;
}

.page-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  gap: 16px;
  margin-bottom: 22px;
  flex-wrap: wrap;
}

.page-head h1 {
  font-size: clamp(24px, 4vw, 32px);
  line-height: 1.2;
  margin: 0 0 4px;
  letter-spacing: -0.02em;
}

.muted {
  color: var(--text-muted);
}

.grid-main {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) minmax(0, 0.6fr);
  gap: 20px;
  align-items: start;
}

.stack {
  display: grid;
  gap: 20px;
}

/* ---------------------------------------------------------------------- Cards */

.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 20px;
  box-shadow: var(--shadow);
}

.card h2 {
  font-size: 16px;
  margin: 0 0 14px;
  letter-spacing: -0.01em;
}

.card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 14px;
}

.card-head h2 {
  margin: 0;
}

.meal-card {
  scroll-margin-top: 24px;
}

.nutrition-subtitle { margin: -8px 0 16px; }
.progress-tabs { display: flex; gap: 6px; margin-bottom: 14px; overflow-x: auto; }
.card > summary { cursor: pointer; color: var(--text); }
.card > summary h2 { display: inline; margin: 0; }
.card[open] > summary { margin-bottom: 18px; }
.target-fields { margin: 20px 0; padding: 16px; border: 1px solid var(--line); border-radius: var(--radius-sm); }
.target-fields legend { padding: 0 6px; font-weight: 700; }
.progress-tabs .btn { padding: 7px 13px; }
.progress-tabs [aria-selected="true"], .progress-tabs [aria-pressed="true"] { background: var(--accent-soft); border-color: var(--accent); color: var(--accent-soft-text); }
.progress-filters { display: flex; flex-wrap: wrap; gap: 7px; margin-bottom: 14px; }
.progress-chip { display: inline-flex; align-items: center; gap: 7px; padding: 6px 10px; border: 1px solid var(--line); border-radius: 999px; background: var(--surface); color: var(--text-muted); cursor: pointer; font-size: 13px; }
.progress-chip[aria-pressed="true"] { border-color: var(--line-strong); background: var(--surface-2); color: var(--text); }
.series-mark { width: 9px; height: 9px; border-radius: 50%; }
.progress-chip[aria-pressed="false"] .series-mark { background: transparent !important; border: 2px solid var(--text-muted); }
.progress-score { display: flex; justify-content: space-between; gap: 8px 18px; flex-wrap: wrap; padding: 10px 12px; margin: 0 0 10px; border-radius: var(--radius-sm); background: var(--accent-soft); color: var(--accent-soft-text); font-size: 13px; }
.nutrition-chart { margin: 0; }
.nutrition-chart circle { cursor: pointer; }
.chart-detail { min-height: 48px; display: grid; gap: 2px; padding-top: 8px; color: var(--text-muted); font-size: 13px; }
.chart-detail strong { color: var(--text); }

/* ------------------------------------------------------------------- Controls */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  border: 1px solid var(--line-strong);
  background: var(--surface);
  color: var(--text);
  border-radius: var(--radius-sm);
  padding: 9px 15px;
  font-size: 14px;
  font-weight: 550;
  cursor: pointer;
  transition: background 0.15s ease, border-color 0.15s ease;
}

.btn:hover {
  background: var(--surface-2);
  border-color: var(--text-muted);
}

.btn-primary {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-contrast);
}

.btn-primary:hover {
  background: var(--accent-hover);
  border-color: var(--accent-hover);
}

.btn-danger {
  color: var(--danger);
  border-color: var(--danger);
  background: var(--surface);
}

.btn-danger:hover {
  background: var(--danger-bg);
}

.btn-quiet {
  border-color: transparent;
  background: transparent;
  color: var(--text-muted);
  padding: 7px 10px;
}

.btn-quiet:hover {
  background: var(--surface-2);
  color: var(--text);
}

.btn:disabled {
  opacity: 0.55;
  cursor: not-allowed;
}

.btn-block {
  width: 100%;
}

.icon-btn {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  flex: 0 0 34px;
  border-radius: 50%;
  border: 1px solid transparent;
  background: var(--accent-soft);
  color: var(--accent-soft-text);
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
}

.icon-btn:hover {
  background: var(--accent);
  color: var(--accent-contrast);
}

.field {
  display: grid;
  gap: 6px;
  margin-bottom: 14px;
}

.field label,
.field .label {
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
}

.field .hint {
  font-size: 12.5px;
  color: var(--text-muted);
}

input[type="text"],
input[type="email"],
input[type="password"],
input[type="number"],
input[type="date"],
input[type="search"],
select,
textarea {
  width: 100%;
  padding: 9px 12px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text);
}

input::placeholder,
textarea::placeholder {
  color: var(--text-muted);
  opacity: 1;
}

.field-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 14px;
}

/* A count belongs next to its label, not under it: the field is three
   characters wide and a full-width row above it wastes a whole line. */
.servings-field {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}

.servings-field .hint {
  flex-basis: 100%;
  margin: 0;
}

.servings-label {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.servings-label label {
  margin: 0;
}

/* An explanation that only shows when it is asked for. The bubble is faded
   rather than removed, so `aria-describedby` still finds its text; the marker
   is a button so a tap or the keyboard opens it, since a phone has no hover. */
.field-tip {
  display: inline-flex;
}

/* The bubble hangs off the whole row, not off the marker: anchored to a marker
   sitting halfway across a narrow screen it would run off the right edge. */
.servings-field {
  position: relative;
}

.field-tip-mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  position: relative;
  width: 20px;
  height: 20px;
  border: 1px solid var(--line);
  border-radius: 50%;
  padding: 0;
  background: none;
  font-size: 12px;
  font-style: italic;
  font-weight: 600;
  line-height: 1;
  color: var(--text-muted);
  cursor: help;
}

/* A finger is wider than the marker; the hit area is grown without growing
   the mark itself. */
.field-tip-mark::after {
  content: "";
  position: absolute;
  inset: -11px;
}

.field-tip-bubble {
  position: absolute;
  top: calc(100% + 8px);
  left: 0;
  z-index: 20;
  width: max-content;
  max-width: min(360px, 100%);
  padding: 8px 10px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--surface);
  box-shadow: var(--shadow);
  font-size: 13px;
  font-weight: 400;
  line-height: 1.4;
  color: var(--text-muted);
  text-align: left;
  white-space: normal;
  opacity: 0;
  pointer-events: none;
  transition: opacity 120ms ease;
}

.field-tip:hover .field-tip-bubble,
.field-tip-mark:focus + .field-tip-bubble {
  opacity: 1;
}

.servings-control {
  display: flex;
  align-items: center;
  gap: 6px;
}

.servings-control input {
  width: 5.5rem;
  text-align: center;
}

/* The stepper buttons replace the native spinner, which is invisible until
   hover on a desktop browser and absent from the installed PWA. Two sets of
   arrows in one field would be worse than none, so the native one goes. */
.servings-control input::-webkit-outer-spin-button,
.servings-control input::-webkit-inner-spin-button {
  appearance: none;
  margin: 0;
}

.servings-control input[type="number"] {
  -moz-appearance: textfield;
  appearance: textfield;
}

.servings-step {
  min-width: 42px;
  min-height: 42px;
  padding: 0;
  font-size: 19px;
  line-height: 1;
}

.checkbox {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  margin-bottom: 12px;
}

.checkbox input {
  margin-top: 3px;
  width: 17px;
  height: 17px;
  accent-color: var(--accent);
}

fieldset {
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: 14px;
  margin: 0 0 14px;
}

.barcode-scan-button {
  display: inline-flex;
  align-items: center;
  gap: 7px;
}

.search-with-action { position: relative; }
.search-with-action input { padding-right: 48px; }
.search-with-action .barcode-scan-button {
  position: absolute;
  inset: 4px 4px 4px auto;
  width: 36px;
  padding: 0;
  border-color: transparent;
  background: var(--accent-soft);
}

.scanner-backdrop {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: grid;
  place-items: center;
  padding: 18px;
  background: rgb(0 0 0 / 72%);
}

.scanner-dialog {
  width: min(100%, 520px);
  padding: 18px;
  border-radius: var(--radius);
  background: var(--surface);
  box-shadow: 0 20px 70px rgb(0 0 0 / 35%);
}

.scanner-header {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 14px;
}

.scanner-header h2,
.scanner-header p {
  margin: 0;
}

.scanner-preview {
  position: relative;
  overflow: hidden;
  min-height: 260px;
  margin-bottom: 14px;
  border-radius: var(--radius-sm);
  background: #090909;
}

.scanner-preview video {
  display: block;
  width: 100%;
  min-height: 260px;
  max-height: 65vh;
  object-fit: cover;
}

.scanner-guide {
  position: absolute;
  top: 50%;
  left: 10%;
  width: 80%;
  height: 34%;
  transform: translateY(-50%);
  border: 2px solid #fff;
  border-radius: 10px;
  box-shadow: 0 0 0 999px rgb(0 0 0 / 22%);
}

legend {
  font-size: 13px;
  font-weight: 600;
  padding: 0 6px;
}

/* -------------------------------------------------------------------- Energy */

.energy {
  display: grid;
  grid-template-columns: 168px minmax(0, 1fr);
  gap: 24px;
  align-items: center;
}

/* The hole is positioned against the ring, which must therefore be a
   positioned ancestor. Without this the pseudo-element escapes its parent. */
.ring {
  position: relative;
  width: 168px;
  height: 168px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: conic-gradient(var(--accent) 0 var(--progress, 0%), var(--line) var(--progress, 0%) 100%);
}

.ring::after {
  content: "";
  position: absolute;
  inset: 18px;
  border-radius: 50%;
  background: var(--surface);
}

.ring-text {
  position: relative;
  z-index: 1;
  text-align: center;
  font-size: 25px;
  font-weight: 700;
  letter-spacing: -0.02em;
}

.ring-text small {
  display: block;
  font-size: 12px;
  font-weight: 500;
  color: var(--text-muted);
  letter-spacing: 0;
  margin-top: 2px;
}

.macro {
  margin: 14px 0;
}

.macro-head {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  font-size: 13.5px;
}

.bar {
  height: 8px;
  background: var(--line);
  border-radius: 8px;
  margin-top: 6px;
  overflow: hidden;
}

.bar > i {
  display: block;
  height: 100%;
  background: var(--accent);
  border-radius: 8px;
}

.bar.carb > i {
  background: var(--carb);
}

.bar.fat > i {
  background: var(--fat);
}

/* ---------------------------------------------------------- Micronutrients */

.micro-panel-toggle {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  cursor: pointer;
  list-style: none;
}

.micro-panel-toggle::-webkit-details-marker {
  display: none;
}

.card .micro-panel-toggle h2 {
  margin: 0;
}

.micro-panel-chevron {
  width: 12px;
  height: 12px;
  margin: 0 5px 5px 0;
  border-right: 3px solid var(--accent);
  border-bottom: 3px solid var(--accent);
  transform: rotate(45deg);
  transition: transform 160ms ease, margin 160ms ease;
}

.micro-panel:not([open]) .micro-panel-chevron {
  margin-top: 6px;
  margin-bottom: 0;
  transform: rotate(-135deg);
}

.micro-panel-content {
  margin-top: 14px;
}

.micro-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1px;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--line);
}

.micro-item {
  min-width: 0;
  min-height: 76px;
  padding: 12px 14px;
  background: var(--surface-2);
}

.micro-item > span,
.micro-item > strong {
  display: block;
}

.micro-item > span {
  overflow: hidden;
  color: var(--text-muted);
  font-size: 12.5px;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.micro-item > strong {
  margin-top: 4px;
  font-size: 16px;
}

.micro-item > strong small {
  color: var(--text-muted);
  font-size: 12px;
  font-weight: 500;
}

.micro-indicator {
  display: block;
  width: 100%;
  height: 5px;
  margin-top: 8px;
  overflow: hidden;
  appearance: none;
  border: 0;
  border-radius: 999px;
  background: var(--line);
}

.micro-indicator::-webkit-progress-bar {
  border-radius: 999px;
  background: var(--line);
}

.micro-indicator::-webkit-progress-value {
  border-radius: 999px;
  background: var(--accent);
}

.micro-indicator::-moz-progress-bar {
  border-radius: 999px;
  background: var(--accent);
}

.micro-coverage {
  display: block;
  margin-top: 3px;
  color: var(--warn-text);
  font-size: 11px;
}

.micro-hint {
  margin: 10px 0 0;
  color: var(--text-muted);
  font-size: 12px;
}

/* --------------------------------------------------------------------- Lists */

.row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 0;
  border-top: 1px solid var(--line);
}

.row:first-of-type {
  border-top: 0;
}

.row-body {
  flex: 1;
  min-width: 0;
}

.row-body strong {
  display: block;
  font-weight: 600;
  overflow-wrap: anywhere;
}

.row-body span {
  display: block;
  font-size: 12.5px;
  color: var(--text-muted);
  margin-top: 2px;
}

.row-value {
  font-weight: 650;
  white-space: nowrap;
}

.row-actions {
  display: flex;
  gap: 4px;
}

.clickable-row { transition: background 0.15s ease; }
.clickable-row:hover { background: var(--surface-2); }
.row-main-link {
  display: flex;
  flex: 1;
  min-width: 0;
  align-items: center;
  gap: 12px;
  color: inherit;
  text-decoration: none;
}
.row-main-link:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; }

.activity-form { display: grid; grid-template-columns: 2fr 1.4fr 1fr auto; gap: 12px; align-items: end; padding: 14px 0; border-top: 1px solid var(--border); }
.activity-form-actions { display: flex; gap: 6px; padding-bottom: 1px; }
.activity-total { display: flex; justify-content: space-between; gap: 16px; border-top: 1px solid var(--border); padding-top: 16px; margin-top: 10px; }
@media (max-width: 700px) { .activity-form { grid-template-columns: 1fr; } .activity-form-actions { padding-bottom: 0; } }
.add-food-button { min-width: 44px; min-height: 44px; padding: 9px; font-size: 20px; }
.recent-food-list {
  /* Keep four complete result rows visible while leaving older foods nearby. */
  max-height: 304px;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-gutter: stable;
}

.avatar {
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: var(--accent-soft);
  color: var(--accent-soft-text);
  display: grid;
  place-items: center;
  font-weight: 700;
  font-size: 13px;
}

/* -------------------------------------------------------------------- Badges */

.badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  padding: 3px 7px;
  border-radius: 6px;
  background: var(--surface-2);
  color: var(--text-muted);
  border: 1px solid var(--line);
  white-space: nowrap;
}

.badge-off {
  background: var(--accent-soft);
  color: var(--accent-soft-text);
  border-color: transparent;
}

.badge-usda {
  background: var(--info-bg);
  color: var(--info-text);
  border-color: transparent;
}

.badge-user,
.badge-recipe {
  background: var(--carb-soft);
  color: var(--carb);
  border-color: transparent;
}

/* The bundled German reference database, and the optional external fallback.
   The badge always carries the source's name as text and a full name for a
   screen reader, so these only ever help someone scan a list - they never
   carry the meaning on their own. FatSecret keeps the neutral badge and is
   set apart by weight alone, because it is the one source that is off in
   almost every installation. */
.badge-bls {
  background: var(--fat-soft);
  color: var(--fat);
  border-color: transparent;
}

.badge-fatsecret {
  border-style: dashed;
}

/* An AI estimate is marked by text and an icon, never by colour alone. */
.badge-ai {
  background: var(--warn-bg);
  color: var(--warn-text);
  border-color: transparent;
}

/* An entry standing in for an AI run that has not finished. Dashed, so it reads
   as not-yet-real at a glance without relying on its colour alone. */
.ai-placeholder {
  border-top: 1px dashed var(--line);
  border-bottom: 1px dashed var(--line);
}

.ai-placeholder + .ai-placeholder {
  border-top: 0;
}

.ai-placeholder .row-body strong {
  color: var(--text-muted);
}

.ai-placeholder-tags {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
}

/* A run that failed. Marked by its own state text and this line, never by the
   colour alone, and kept dashed like every other stand-in for a missing entry. */
.ai-placeholder-failed .row-body strong {
  color: var(--text);
}

.ai-placeholder-failed .row-body .ai-placeholder-reason {
  color: var(--danger);
}

/* The failure tag carries the run's own error line as its tooltip, so it points
   at something the rest of the row does not say. */
.ai-placeholder .ai-state[title] {
  cursor: help;
}

/* Re-run and discard, as icons: wide enough to hit on a phone, and quiet
   enough not to compete with the row's own text. */
.ai-placeholder-actions {
  flex-shrink: 0;
  align-items: center;
}

.ai-placeholder-actions .btn {
  min-width: 40px;
  min-height: 40px;
  padding: 6px 10px;
  font-size: 19px;
  line-height: 1;
}

/* Throwing the run away is the destructive one of the two, so its hover says
   so. Never the colour alone: the button's name and tooltip say "discard". */
.ai-placeholder-actions .ai-discard:hover {
  background: var(--danger-bg);
  color: var(--danger);
}

/* On a phone the row has no width to spare for buttons beside the text: the
   tags, the state and the two actions drop onto their own line rather than
   squeezing the submitted input down to one letter per line. */
@media (max-width: 700px) {
  .ai-placeholder-failed {
    flex-wrap: wrap;
  }

  .ai-placeholder-failed .row-main-link {
    flex: 1 1 100%;
    flex-wrap: wrap;
  }

  .ai-placeholder-failed .row-body {
    flex-basis: 100%;
  }

  .ai-placeholder-actions {
    margin-left: auto;
  }
}

/* ------------------------------------------------------------------ Messages */

.notice {
  border-radius: var(--radius-sm);
  padding: 12px 14px;
  font-size: 13px;
  display: flex;
  gap: 9px;
  align-items: flex-start;
  background: var(--info-bg);
  color: var(--info-text);
}

.notice-warn {
  background: var(--warn-bg);
  color: var(--warn-text);
}

.notice-error {
  background: var(--danger-bg);
  color: var(--danger);
}

.notice-icon {
  flex: 0 0 auto;
  font-weight: 700;
}

.empty {
  text-align: center;
  padding: 28px 16px;
  color: var(--text-muted);
  font-size: 14px;
}

/* --------------------------------------------------------------------- Misc */

.quick-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px;
}

.quick-grid .btn {
  flex-direction: column;
  gap: 5px;
  padding: 14px 6px;
  font-size: 12.5px;
  text-align: center;
}

.quick-grid .btn span[aria-hidden] {
  font-size: 18px;
}

.date-nav {
  display: flex;
  align-items: center;
  gap: 4px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 4px;
}

.date-nav strong {
  padding: 0 10px;
  font-size: 14px;
  font-weight: 600;
  white-space: nowrap;
}

.table {
  width: 100%;
  border-collapse: collapse;
  font-size: 14px;
}

.table th,
.table td {
  text-align: left;
  padding: 9px 10px;
  border-bottom: 1px solid var(--line);
}

.table th {
  font-size: 12.5px;
  color: var(--text-muted);
  font-weight: 600;
}

.table td.num,
.table th.num {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

/* The nutrient table carries a second value column for the entered portion.
   Values stay on one line so the two columns line up and stay comparable; the
   surrounding .table-scroll takes the width on a narrow screen. */
.nutrient-table td.num,
.nutrient-table th.num {
  white-space: nowrap;
}

.table-scroll {
  overflow-x: auto;
}

/* Roughly seven rows plus the header: longer tables scroll instead of growing. */
.table-scroll-y {
  max-height: 316px;
  overflow-y: auto;
}

.table-scroll-y thead th {
  position: sticky;
  top: 0;
  background: var(--surface);
}

.auth-shell {
  min-height: 100dvh;
  display: grid;
  place-items: center;
  padding: 24px 18px;
}

.auth-card {
  width: 100%;
  max-width: 420px;
}

.fab {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: var(--accent);
  color: var(--accent-contrast);
  border: 0;
  border-radius: 16px;
  padding: 14px 19px;
  font-weight: 650;
  font-size: 14px;
  cursor: pointer;
  box-shadow: 0 8px 22px rgba(15, 60, 40, 0.35);
}

.fab:hover {
  background: var(--accent-hover);
  text-decoration: none;
}

/* The quick-action menu. The button is round and unlabelled - it opens a list
   whose rows name themselves - so nothing has to line up with a heading beside
   it, which is what the labelled pill never managed on a narrow screen. */
.fab-stack {
  position: fixed;
  right: 22px;
  bottom: 22px;
  /* Above the bottom navigation, which the menu and its backdrop cover. */
  z-index: 7;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 14px;
}

.fab-toggle {
  width: 60px;
  height: 60px;
  justify-content: center;
  border-radius: 50%;
  padding: 0;
  font-size: 26px;
  line-height: 1;
}

.fab-backdrop {
  position: fixed;
  inset: 0;
  z-index: 6;
  background: rgba(8, 18, 12, 0.45);
}

.fab-menu {
  display: flex;
  max-width: calc(100vw - 32px);
  flex-direction: column;
  align-items: flex-end;
  gap: 10px;
  padding: 14px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 22px;
  box-shadow: var(--shadow), 0 10px 30px rgba(8, 18, 12, 0.18);
}

.fab-action {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 14px;
  width: 100%;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--text);
  font: inherit;
  text-align: right;
  cursor: pointer;
}

.fab-action:hover {
  text-decoration: none;
}

.fab-action-label {
  font-size: 15px;
  font-weight: 650;
}

.fab-action-icon {
  display: grid;
  place-items: center;
  flex: none;
  width: 48px;
  height: 48px;
  border-radius: 50%;
  font-size: 20px;
  color: var(--action-contrast);
  background: var(--action-meal);
}

.fab-action-icon[data-tone="recipe"] { background: var(--action-recipe); }
.fab-action-icon[data-tone="activity"] { background: var(--action-activity); }
.fab-action-icon[data-tone="body"] { background: var(--action-body); }

.fab-action:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 4px;
  border-radius: 26px;
}

.quick-meal-dialog {
  width: min(720px, calc(100% - 28px));
  max-height: calc(100dvh - 28px);
  overflow: auto;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 22px;
  box-shadow: var(--shadow);
}

.quick-meal-dialog::backdrop {
  background: rgba(8, 18, 12, 0.55);
  backdrop-filter: blur(2px);
}

.bottom-nav {
  display: none;
}

/* ----------------------------------------------------------------- Responsive */

@media (max-width: 900px) {
  .grid-main {
    grid-template-columns: minmax(0, 1fr);
  }
}

@media (max-width: 720px) {
  .micro-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .shell {
    /* Clears the fixed bottom navigation, so the last row of a list is never
       permanently hidden behind it. */
    padding: 18px 14px 90px;
  }

  .shell--with-fab {
    /* Also clears the floating action button, which sits just above the
       bottom navigation on pages that render one. */
    padding-bottom: 150px;
  }

  .nav {
    display: none;
  }

  .energy {
    grid-template-columns: 128px minmax(0, 1fr);
    gap: 16px;
  }

  .ring {
    width: 128px;
    height: 128px;
  }

  .ring::after {
    inset: 15px;
  }

  .ring-text {
    font-size: 20px;
  }

  .fab-stack {
    bottom: 82px;
    right: 16px;
  }

  .bottom-nav {
    display: flex;
    position: fixed;
    inset: auto 0 0 0;
    z-index: 5;
    background: var(--surface);
    border-top: 1px solid var(--line);
    justify-content: space-around;
    padding: 8px 4px calc(8px + env(safe-area-inset-bottom));
  }

  .bottom-nav a {
    flex: 1;
    text-align: center;
    font-size: 11px;
    color: var(--text-muted);
    padding: 4px 2px;
    border-radius: var(--radius-sm);
  }

  .bottom-nav a:hover {
    text-decoration: none;
  }

  .bottom-nav a[aria-current="page"] {
    color: var(--accent);
    font-weight: 650;
  }

  .bottom-nav span[aria-hidden] {
    display: block;
    font-size: 17px;
    margin-bottom: 1px;
  }
}

/* ------------------------------------------------------- Admin: AI job queue */

.job-filters {
  display: flex;
  flex-wrap: wrap;
  gap: 7px;
  margin-bottom: 12px;
}

.job-filters a {
  text-decoration: none;
}

.job-filters a[aria-current="page"] {
  border-color: var(--line-strong);
  background: var(--surface-2);
  color: var(--text);
}

.job-toolbar {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 18px;
  align-items: center;
  padding: 10px 12px;
  margin-bottom: 14px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
}

.job-toolbar-group {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  align-items: center;
}

.job-toolbar-label {
  font-size: 12.5px;
  color: var(--text-muted);
  font-weight: 600;
}

.job-toolbar .btn {
  padding: 6px 11px;
  font-size: 13px;
}

.job-reason {
  display: flex;
  flex-direction: column;
  gap: 5px;
  max-width: 44ch;
}

.job-reason-message {
  font-size: 13px;
}

.job-reason-hint {
  margin: 0;
  font-size: 12.5px;
  line-height: 1.45;
}

/* What a finished job produced: label above value, so a long list of nutrient
   keys wraps under its own heading instead of pushing the column wide. */
.job-result {
  display: grid;
  gap: 4px;
  margin: 0;
  font-size: 12.5px;
}

.job-result dt {
  color: var(--text-muted);
  font-weight: 600;
}

.job-result dd {
  margin: 0;
  overflow-wrap: anywhere;
}

/* Three tracks so the page status stays centred whether or not both arrows
   are shown - a pager that shifts sideways on the first page reads as a bug. */
.job-pager {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 12px;
  margin-top: 14px;
  font-size: 13px;
}

.job-pager > :first-child { justify-self: start; }
.job-pager > :last-child { justify-self: end; }
/* Keeps the grid track and takes the link out of the tab order in one go. */
.job-pager .is-hidden { visibility: hidden; }

.job-details summary {
  cursor: pointer;
  font-size: 12.5px;
  color: var(--text-muted);
}

.job-detail-list {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 3px 12px;
  margin: 8px 0;
  font-size: 12.5px;
}

.job-detail-list dt {
  color: var(--text-muted);
  font-weight: 600;
}

.job-detail-list dd {
  margin: 0;
}

/* A cause chain and a URL are both long and unbreakable; let them wrap. */
.job-detail-break {
  overflow-wrap: anywhere;
}

.job-detail-heading {
  margin: 10px 0 6px;
  font-size: 12.5px;
  color: var(--text-muted);
}

.job-attempts {
  margin: 0;
  padding-left: 18px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  font-size: 12.5px;
}

.job-attempts code {
  overflow-wrap: anywhere;
}

/* ------------------------------------------ AI review: choosing a food source */

.choice-set {
  border: 0;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 22ch;
}

.choice {
  display: flex;
  gap: 8px;
  align-items: flex-start;
  padding: 6px 8px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  cursor: pointer;
  font-size: 13px;
  line-height: 1.4;
}

.choice:hover {
  background: var(--surface-2);
}

.choice:has(input:checked) {
  border-color: var(--accent);
  background: var(--accent-soft);
  color: var(--accent-soft-text);
}

.choice input {
  margin-top: 2px;
  flex: 0 0 auto;
}

.choice a {
  overflow-wrap: anywhere;
}

/* ----------------------------------------- Proposals waiting for a decision */

.pending-proposal {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 16px;
  align-items: flex-start;
  justify-content: space-between;
}

.pending-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  align-items: center;
}

.pending-actions .btn {
  padding: 6px 11px;
  font-size: 13px;
}

/* Shared editor dialogs */
.app-dialog {
  width: min(720px, calc(100% - 28px)); max-height: calc(100dvh - 28px);
  color: var(--text); background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 0; box-shadow: var(--shadow); overflow: hidden;
}
.app-dialog::backdrop { background: rgba(8, 18, 12, 0.55); backdrop-filter: blur(2px); }
.app-dialog-head { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 20px 22px 14px; border-bottom: 1px solid var(--line); }
.app-dialog-head h2 { margin: 0; }
.app-dialog-body { padding: 18px 22px 22px; max-height: calc(100dvh - 110px); overflow: auto; }
.dialog-hint { margin: 0 0 16px; }
.dialog-toolbar, .editor-actions { display: flex; justify-content: flex-end; align-items: center; gap: 12px; margin-bottom: 8px; }
.dialog-toolbar { justify-content: space-between; }
.row-main-button { display: flex; flex: 1; min-width: 0; align-items: center; gap: 12px; padding: 14px 0; border: 0; background: transparent; color: inherit; text-align: left; cursor: pointer; font: inherit; }
.row-main-button:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.copy-previous-action { display: flex; justify-content: center; padding: 12px 0 4px; }
.copy-previous-action .btn { min-height: 44px; box-shadow: 0 2px 8px rgba(10, 30, 20, .08); }
@media (max-width: 600px) { .app-dialog-head { padding: 16px; } .app-dialog-body { padding: 14px 16px 18px; } }

/* Compact combobox used in meal dialogs. The panel overlays diary rows rather than
   reflowing them, while its own scrolling keeps it usable on small screens. */
.dialog-toolbar > .food-search-dropdown { flex: 1; min-width: 0; }
.food-search-dropdown { position: relative; z-index: 4; }
.food-search-panel { position: absolute; z-index: 20; top: calc(100% + 5px); right: 0; left: 0; min-width: min(100%, 320px); max-height: min(50dvh, 360px); overflow-y: auto; background: var(--surface); border: 1px solid var(--line); border-radius: 12px; box-shadow: var(--shadow); }
.food-search-option { display: flex; align-items: center; gap: 10px; min-height: 44px; padding: 9px 12px; color: inherit; text-decoration: none; border-bottom: 1px solid var(--line); }
.food-search-option:hover, .food-search-option[aria-selected="true"] { background: var(--surface-soft); }
.food-search-message, .food-search-group { margin: 0; padding: 10px 12px; }
.food-search-group { color: var(--muted); font-size: 12px; font-weight: 700; text-transform: uppercase; }
.food-search-actions { display: flex; align-items: center; gap: 10px; padding: 10px; flex-wrap: wrap; font-size: 13px; }
/* The dialog body scrolls, so it also clips: a meal with nothing in it yet is
   shorter than the panel and cut the results off. While the panel is up the
   body keeps room for it. */
.app-dialog-body:has(.food-search-panel) { min-height: min(430px, 62dvh); }
/* On a phone the panel takes the whole toolbar rather than just the input, so
   it gains the width of the calorie total beside it. Measured against the
   toolbar and not by a fixed offset: an offset wide enough for "1.234 kcal"
   pushes the panel outside the dialog, which clips it, when the total is still
   "0 kcal". */
@media (max-width: 600px) {
  .dialog-toolbar { align-items: center; position: relative; }
  .dialog-toolbar > strong { white-space: nowrap; }
  .dialog-toolbar > .food-search-dropdown { position: static; }
  .food-search-panel { left: 0; right: 0; }
}

/* --------------------------------------------- Body progress (design preview)
   Prototype styles for /progress/body-preview. Everything below reuses the
   existing tokens, so light and dark mode need no second palette. Removing the
   preview means removing this block. */

/* The metric chips scroll rather than wrap, so their row has a wide minimum.
   Without an explicit zero-minimum track that minimum would size the whole
   column and push the page sideways on a phone. */
.body-progress-stack {
  grid-template-columns: minmax(0, 1fr);
}

/* The title and the two actions wrap rather than squeezing each other on a
   narrow screen. */
.body-card-head {
  flex-wrap: wrap;
}

/* The picker and the check-in sit together in the card head. */
.body-card-actions {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

.shareable-panel { position: relative; min-width: 0; }
.share-control { position: absolute; z-index: 3; top: 14px; right: 14px; }
.share-trigger { color: var(--accent); background: color-mix(in srgb, var(--surface) 88%, transparent); }
.shareable-panel > .card > h2:first-child,
.shareable-panel > .card > .card-head { padding-right: 42px; }
.body-hero-panel.shareable-panel { padding-top: 4px; }
.body-hero-panel.shareable-panel .share-control { top: 0; right: 0; }
.share-intro { margin-top: 0; }
.share-options { display: grid; gap: 10px; }
.share-options .btn { justify-content: center; width: 100%; }
.share-options .badge { margin-left: 6px; }
.share-status { margin: 14px 0 0; color: var(--muted); font-size: 14px; }

/* Recording a measurement and starting a scan are two separate decisions, so
   the buttons are not allowed to touch. */
.body-checkin-actions {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

/* Three builds side by side, each showing the figure it produces. */
.body-figure-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 10px;
}

.body-figure-option {
  display: grid;
  gap: 6px;
  justify-items: center;
  padding: 10px 6px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text-muted);
  font: inherit;
  font-size: 13px;
  cursor: pointer;
}

.body-figure-option svg {
  display: block;
  width: 100%;
  max-width: 120px;
  height: auto;
}

.body-figure-option:hover {
  border-color: var(--line-strong);
  background: var(--surface-2);
}

.body-figure-option[aria-checked="true"] {
  border-color: var(--accent);
  background: var(--accent-soft);
  color: var(--accent-soft-text);
  font-weight: 600;
}

/* Before the first check-in: the figure beside what a session records. */
.body-empty {
  display: grid;
  grid-template-columns: minmax(0, 160px) minmax(0, 1fr);
  gap: 24px;
  align-items: center;
}

/* Without the figure there is no first column to reserve room for. */
.body-empty-single {
  grid-template-columns: minmax(0, 1fr);
}

.body-empty-figure svg {
  display: block;
  width: 100%;
  height: auto;
}

@media (max-width: 620px) {
  .body-empty {
    grid-template-columns: minmax(0, 1fr);
    gap: 16px;
    justify-items: center;
    text-align: center;
  }

  .body-empty-figure {
    max-width: 140px;
  }
}

.body-preview-head {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}

/* Disclosures. By default they exist only below the breakpoint: the toggle is
   hidden above it and the content always shows, so the desktop layout is
   unchanged. Same chevron and rhythm as the weight log so the two read as one
   pattern. The look lives here; only whether the toggle shows is a question of
   width. */
.body-fold-toggle {
  display: none;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  width: 100%;
  padding: 12px 0 0;
  border: 0;
  background: transparent;
  color: var(--text-muted);
  font: inherit;
  font-size: 13.5px;
  font-weight: 600;
  text-align: left;
  cursor: pointer;
}

.body-fold-chevron {
  width: 9px;
  height: 9px;
  margin: 0 4px 4px 0;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: rotate(45deg);
  transition: transform 160ms ease, margin 160ms ease;
}

.body-fold-toggle[aria-expanded="true"] .body-fold-chevron {
  margin: 4px 4px 0 0;
  transform: rotate(-135deg);
}

/* A fold that stays folded at every width, for a block that is the detail
   behind a card rather than the reason to open it. */
.body-fold-always {
  margin-top: 14px;
  border-top: 1px solid var(--line);
}

.body-fold-always .body-fold-toggle {
  display: flex;
}

.body-fold-always .body-fold-content {
  padding-top: 12px;
}

.body-fold-always .body-fold-content[data-open="false"] {
  display: none;
}

/* The change list is a new block under the figure, not a continuation of its
   caption, so it needs air above it. */
.body-change-block {
  margin-top: 22px;
}

.body-micro-head {
  display: flex;
  align-items: center;
  gap: 7px;
  margin: 0 0 10px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--text-muted);
}

.body-ref-bar {
  display: flex;
  align-items: flex-end;
  gap: 14px 18px;
  flex-wrap: wrap;
  padding-bottom: 16px;
  margin-bottom: 18px;
  border-bottom: 1px solid var(--line);
}

.body-ref-field {
  display: grid;
  gap: 5px;
  min-width: 0;
}

.body-ref-field > .label {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--text-muted);
}

.body-ref-field select {
  width: auto;
  min-width: 168px;
}

.body-ref-current {
  padding: 9px 12px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  font-variant-numeric: tabular-nums;
}

.body-ref-quick {
  display: flex;
  gap: 7px;
  flex-wrap: wrap;
  margin-left: auto;
}

.body-ref-quick .progress-chip {
  padding: 5px 11px;
  font-size: 12.5px;
}

/* 45 / 55 split: composition reads first, the silhouette gets the extra room. */
.body-hero {
  display: grid;
  grid-template-columns: minmax(0, 45fr) minmax(0, 55fr);
  gap: 24px;
}

/* One panel switched off in settings. The survivor is centred rather than left
   in its 45 % or 55 % column, but stays capped near the width it had beside its
   neighbour: both drawings scale to their container, and a full-width card
   turns the diamond and the figure into posters. */
.body-hero-single {
  grid-template-columns: minmax(0, 1fr);
  justify-items: center;
}

.body-hero-single .body-hero-panel {
  width: 100%;
  max-width: 560px;
}

.body-hero-panel {
  min-width: 0;
}

.body-hero-panel + .body-hero-panel {
  padding-left: 24px;
  border-left: 1px solid var(--line);
}

.body-figure {
  margin: 0;
}

.body-figure svg {
  display: block;
  width: 100%;
  height: auto;
}

.body-diamond-wrap {
  margin: 0 auto;
}

.body-series-chart {
  max-width: 780px;
  margin: 0 auto;
}

/* Height follows width so the chart never sits letterboxed inside a taller
   box, which is what a fixed height does once the card is narrower or wider
   than the view box. */
.body-series-chart svg {
  height: auto;
}

/* Measurement names are two words; a chip that wraps mid-name is unreadable,
   so the row scrolls instead. */
.body-metric-tabs .btn {
  flex: 0 0 auto;
  white-space: nowrap;
}

/* A chip that would need a third scale stays in place and stops responding,
   so the limit is visible where it applies rather than only once it is hit. */
.body-metric-tabs .btn:disabled {
  cursor: not-allowed;
}

/* Says the row is a multiple choice before anyone has to discover it. */
.body-series-note {
  margin: -6px 0 14px;
  color: var(--text-muted);
  font-size: 12.5px;
}

/* Which line is which, and which edge it is read against. */
.body-series-legend {
  list-style: none;
  padding: 0;
}

.body-series-legend .muted {
  font-size: 12px;
}

.body-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 18px;
  margin: 10px 0 0;
  font-size: 12.5px;
  color: var(--text-muted);
}

.body-legend-item {
  display: inline-flex;
  align-items: center;
  gap: 7px;
}

.body-legend-line {
  width: 22px;
  border-top: 2.5px solid var(--accent);
}

.body-legend-line-reference {
  border-top: 1.5px dashed var(--text-muted);
}

/* The reference marks on a caliper, as they appear in the legend. */
.body-legend-tick {
  width: 22px;
  height: 11px;
  border-left: 1.6px solid var(--text-muted);
  border-right: 1.6px solid var(--text-muted);
}

.body-shape-wrap {
  max-width: 460px;
  margin: 0 auto;
}

/* Wider than the silhouette: the measure figure carries its labels beside it,
   so the same body has to fit in a narrower share of the box. */
.body-measure-wrap {
  max-width: 560px;
  margin: 0 auto;
}

/* Same live-region pattern as the nutrition chart: the hovered value is text. */
.body-detail {
  min-height: 54px;
  display: grid;
  gap: 2px;
  padding-top: 10px;
  color: var(--text-muted);
  font-size: 13px;
}

.body-detail strong {
  color: var(--text);
  font-variant-numeric: tabular-nums;
}

.body-caption {
  margin: 8px 0 0;
  font-size: 12px;
  color: var(--text-muted);
}

/* --------------------------------------------------------- Stat blocks */

.body-stat-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
  margin-top: 14px;
}

.body-stat {
  display: grid;
  gap: 3px;
  padding: 10px 12px;
  text-align: left;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  color: inherit;
  font: inherit;
  cursor: pointer;
}

.body-stat:hover,
.body-stat[aria-pressed="true"] {
  border-color: var(--line-strong);
  background: var(--surface);
}

.body-stat-name {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--text-muted);
}

.body-stat-value {
  font-size: 17px;
  font-weight: 700;
  letter-spacing: -0.01em;
  font-variant-numeric: tabular-nums;
}

.body-delta {
  font-size: 12.5px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--text-muted);
}

/* Direction is carried by the sign in the text; the tint only reinforces it and
   is deliberately not a good/bad green-versus-red pair. */
.body-delta-up {
  color: var(--carb);
}

.body-delta-down {
  color: var(--info-text);
}

/* --------------------------------------------------------------- KPI strip */

.body-kpi-strip {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 10px;
}

.body-kpi {
  display: grid;
  gap: 3px;
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
}

.body-kpi-name {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--text-muted);
}

.body-kpi-value {
  font-size: 20px;
  font-weight: 700;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
}

/* ------------------------------------------------------------ Info toggles */

.body-info {
  display: grid;
  place-items: center;
  width: 18px;
  height: 18px;
  flex: 0 0 18px;
  padding: 0;
  border: 1px solid var(--line-strong);
  border-radius: 50%;
  background: transparent;
  color: var(--text-muted);
  font-size: 11px;
  font-weight: 700;
  line-height: 1;
  cursor: pointer;
}

.body-info:hover,
.body-info[aria-expanded="true"] {
  border-color: var(--accent);
  color: var(--accent);
}

.body-info-text {
  grid-column: 1 / -1;
  margin: 6px 0 0;
  font-size: 12.5px;
  color: var(--text-muted);
}

/* ------------------------------------------------------------ Change list */

.body-region-list {
  display: grid;
  gap: 4px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.body-region-row {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 7px 9px;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  background: transparent;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.body-region-row:hover,
.body-region-row[aria-pressed="true"] {
  border-color: var(--line);
  background: var(--surface-2);
}

.body-region-name {
  flex: 1 1 auto;
  min-width: 0;
  font-size: 13.5px;
}

.body-region-value,
.body-region-delta {
  font-size: 13px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.body-region-value {
  color: var(--text-muted);
}

.body-region-delta {
  font-weight: 650;
  min-width: 74px;
  text-align: right;
}

/* Pattern, not colour, is what distinguishes the two directions. */
.body-swatch {
  flex: 0 0 14px;
  width: 14px;
  height: 14px;
  border: 1px solid var(--line-strong);
  border-radius: 4px;
}

.body-swatch-up {
  background: var(--carb-soft);
  border-color: var(--carb);
}

.body-swatch-down {
  background: repeating-linear-gradient(45deg, var(--info-bg) 0 3px, var(--info-text) 3px 5px);
  border-color: var(--info-text);
}

.body-swatch-flat {
  background: var(--surface-2);
}

/* ------------------------------------------------------------ Check-in form */

.body-checkin-section {
  margin-bottom: 16px;
}

.body-checkin-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(132px, 1fr));
  gap: 12px;
}

/* Fields in a row are as tall as the tallest of them, and the spare height went
   into the input: one box beside another was visibly taller whenever its label
   wrapped or something sat under it. The label and the box keep their own
   heights and the row's spare height stays at the bottom. */
.body-checkin-grid .field {
  margin-bottom: 0;
  align-content: start;
}

/* A date input asks for a little more height than a number input, which is
   visible as soon as the two sit side by side, so both are told what to be. */
.body-checkin-grid input {
  height: 44px;
}

/* Two ways in, one per button. A phone opening its camera when someone meant
   to reach for a photo they already have is a dead end, so the choice is made
   before the picker opens rather than inside it. */
.scan-source {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}

.scan-source .btn {
  flex: 1 1 140px;
  min-height: 44px;
}

/* A file name is arbitrary text and often long; it wraps rather than pushing
   the dialog sideways. */
.scan-source-file {
  overflow-wrap: anywhere;
}

.body-advanced summary {
  cursor: pointer;
  font-size: 13px;
  font-weight: 600;
  padding: 8px 0;
}

.body-advanced[open] summary {
  margin-bottom: 10px;
}

/* ---------------------------------------------------------------- Responsive */

@media (max-width: 900px) {
  .body-hero {
    grid-template-columns: minmax(0, 1fr);
  }

  .body-hero-panel + .body-hero-panel {
    padding-left: 0;
    padding-top: 22px;
    border-left: 0;
    border-top: 1px solid var(--line);
  }
}

@media (max-width: 620px) {
  .body-ref-quick {
    margin-left: 0;
  }

  .body-ref-field select,
  .body-ref-current {
    width: 100%;
  }

  .body-fold {
    margin-top: 14px;
    border-top: 1px solid var(--line);
  }

  .body-fold-toggle {
    display: flex;
  }

  .body-fold-content {
    padding-top: 12px;
  }

  .body-fold-content[data-open="false"] {
    display: none;
  }

  /* The toggle carries this heading on small screens. */
  .body-change-block {
    margin-top: 0;
  }

  .body-change-block > .body-micro-head {
    display: none;
  }

  /* Four stats across one line rather than four stacked rows: the panel is a
     glanceable strip under the diamond, not a list. */
  .body-stat-grid {
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 6px;
    margin-top: 0;
  }

  .body-stat {
    padding: 8px 7px;
    gap: 2px;
  }

  .body-stat-name {
    flex-wrap: wrap;
    gap: 3px;
    font-size: 9.5px;
    letter-spacing: 0.04em;
  }

  /* A source badge does not fit a cell this narrow in either language, so it
     is read out rather than drawn. The same provenance stays visible in the
     detail line under the strip. */
  .body-stat-name .badge {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
  }

  /* Four narrow cells only line up if none of them wraps, so the value keeps
     its unit on the same line. */
  .body-stat-value {
    font-size: 14px;
    white-space: nowrap;
  }

  .body-stat .body-delta {
    font-size: 11px;
  }
}

/* Presets sit above the four percentage fields as chips: picking one fills the
   fields rather than replacing them, so a preset stays a starting point. */
.meal-split-presets { display: flex; flex-wrap: wrap; gap: 7px; }
/* A meal beside the share of the day it was given. The warning colour is a
   second cue only: `MealTotal` also states the overage in text. */
.meal-total.over { color: var(--warn-text); }
