/* ===================================================================
 * design-system.css — Apple-cinematic last-mile polish.
 *
 * This file layers on top of the existing index.html <style> block
 * (which already implements the design-system primitives for buttons,
 * cards, inputs, and badges against design/design-tokens.json).
 *
 * Scope here: global rhythm that's hard to apply per-component
 *   1. Tabular numerals everywhere numbers live (spec requirement)
 *   2. Toast — 4px colored left-accent stripe per spec
 *   3. Pre / code / OCR raw-text blocks → SF Mono 13px
 *   4. Sidebar active-item gets the Apple accent indicator
 *   5. Confidence badges auto-prepend ✓ / ! / ⚠ glyphs
 *      (spec rule: never encode confidence in colour alone)
 *   6. Low-confidence input helper stroke (for aria-invalid="true"
 *      paired with aria-describedby)
 *   7. Global focus-visible hardening
 *
 * This stylesheet is linked last in <head> so its declarations win
 * the cascade against the main <style> block.
 * =================================================================== */

/* ---------- 1. Tabular numerals for money / counts -------------- */
.stat-value,
.stat-number,
.amount,
.cash-total,
.ledger-row,
.ledger-total,
.budget-amount,
.budget-remaining,
.price,
.price-value,
.receipt-total,
.tabular,
.monetary,
.duration,
.confidence-value,
td.num,
td[data-type="number"],
td[data-type="currency"],
table.data-table td,
table.numeric td {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}

/* ---------- 2. Toast — 4px left-accent stripe ------------------ */
#toast {
  border: 1px solid var(--color-border);
  border-left-width: 4px;
  box-shadow: var(--shadow-3);
  font-family: var(--font-text);
  font-size: var(--font-body);
  letter-spacing: var(--font-body-tracking);
  line-height: 1.4;
  color: var(--color-text-primary);
  background: var(--color-surface);
}
#toast.success {
  border-left-color: var(--color-success);
  border-top-color: var(--color-border);
  border-right-color: var(--color-border);
  border-bottom-color: var(--color-border);
}
#toast.error {
  border-left-color: var(--color-error);
  border-top-color: var(--color-border);
  border-right-color: var(--color-border);
  border-bottom-color: var(--color-border);
}
#toast.warning,
#toast.warn {
  border-left-color: var(--color-warning);
  border-top-color: var(--color-border);
  border-right-color: var(--color-border);
  border-bottom-color: var(--color-border);
}
#toast.info {
  border-left-color: var(--color-info);
  border-top-color: var(--color-border);
  border-right-color: var(--color-border);
  border-bottom-color: var(--color-border);
}

/* Action-toast — same stripe treatment */
#action-toast {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-left: 4px solid var(--color-brand);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-3);
}
#action-toast.success  { border-left-color: var(--color-success); }
#action-toast.error    { border-left-color: var(--color-error); }
#action-toast.warning  { border-left-color: var(--color-warning); }
.action-toast-message {
  font-family: var(--font-text);
  font-size: var(--font-body);
  letter-spacing: var(--font-body-tracking);
  color: var(--color-text-primary);
}
.action-toast-button {
  font-family: var(--font-text);
  color: var(--color-link);
  font-weight: 600;
}

/* ---------- 3. Pre / code / OCR raw text → SF Mono 13px ------- */
pre,
code,
kbd,
samp,
.mono,
.ocr-text,
.ocr-raw,
.raw-ocr,
.receipt-raw,
.text-mono {
  font-family: var(--font-mono);
  font-size: 13px;
  line-height: 1.5;
  letter-spacing: 0;
}
pre {
  background: var(--color-surface-3);
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-sm);
  overflow-x: auto;
}
code:not(pre code) {
  background: var(--color-surface-3);
  padding: 1px 6px;
  border-radius: 4px;
}

/* ---------- 4. Sidebar active indicator ------------------------ */
/* The left rail active state gets a sharper accent — consistent
 * with the "one accent only" rule in SKILL.md. */
.nav-item.active {
  position: relative;
}
.nav-item.active::after {
  content: "";
  position: absolute;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
  width: 3px;
  height: 22px;
  background: var(--color-brand);
  border-radius: 2px;
  box-shadow: 0 0 0 1px rgba(0, 113, 227, 0.18);
}

/* ---------- 5. Confidence badges: auto-glyph ------------------- */
/* Spec rule: never encode confidence in colour alone.
 * Auto-prepend ✓ / ! / ⚠ unless the markup already has one. */
.badge--confidence-high::before,
.badge--confidence-medium::before,
.badge--confidence-low::before {
  margin-right: 3px;
  font-weight: 700;
  font-feature-settings: normal;
}
.badge--confidence-high:not([data-no-glyph])::before   { content: "✓"; }
.badge--confidence-medium:not([data-no-glyph])::before { content: "!"; }
.badge--confidence-low:not([data-no-glyph])::before    { content: "⚠"; }

/* ---------- 6. Input invalid helper line ---------------------- */
input[aria-invalid="true"] + .form-helper,
select[aria-invalid="true"] + .form-helper,
textarea[aria-invalid="true"] + .form-helper,
input[aria-invalid="true"] ~ .form-helper,
.form-group[data-invalid="true"] .form-helper {
  color: var(--color-error);
  font-size: var(--font-xs);
  letter-spacing: var(--font-xs-tracking);
  margin-top: var(--space-1);
  display: flex;
  align-items: center;
  gap: 4px;
}
.form-group[data-invalid="true"] .form-helper::before {
  content: "⚠";
  color: var(--color-error);
}

/* ---------- 7. Global focus-visible hardening ----------------- */
:where(button, a, input, select, textarea, [tabindex]):focus-visible {
  outline: var(--stroke-2) solid var(--color-focus);
  outline-offset: 2px;
}

/* ---------- 8. Body: SF Pro optical-sizing body rhythm -------- */
body {
  font-family: var(--font-text);
  font-size: var(--font-body);
  line-height: var(--font-body-lh);
  letter-spacing: var(--font-body-tracking);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
h1, h2 { font-family: var(--font-display); letter-spacing: -0.4px; }
h3, h4, h5, h6 { font-family: var(--font-display); letter-spacing: -0.2px; }

/* ---------- 9. Scrollbars — subtle Apple-style ---------------- */
@media (pointer: fine) {
  ::-webkit-scrollbar { width: 10px; height: 10px; }
  ::-webkit-scrollbar-track { background: transparent; }
  ::-webkit-scrollbar-thumb {
    background: var(--color-border);
    border-radius: 10px;
    border: 2px solid transparent;
    background-clip: content-box;
  }
  ::-webkit-scrollbar-thumb:hover { background: var(--color-border-strong); background-clip: content-box; border: 2px solid transparent; }
}

/* ---------- 10. Reduced motion -------------------------------- */
@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;
    /* Clay relies on transform hover/press — strip it when the user
       asks for reduced motion so tilt/lift doesn't fire. */
    transform: none !important;
  }
}

/* ===================================================================
 * CLAY THEME — opt-in component layer (data-theme="clay" | "clay-dark")
 *
 * These rules activate ONLY when the root element carries a clay
 * data-theme. Apple themes are unaffected. Spec:
 * design/Design System Inspired by Clay.md
 * =================================================================== */

/* Global feature-set + Roobert fallback stack. */
:root[data-theme="clay"],
:root[data-theme="clay-dark"] {
  font-feature-settings: "kern", "liga", "ss01", "ss03", "ss10", "ss11", "ss12";
  --font-display:
    "Roobert", "Inter var", -apple-system, BlinkMacSystemFont,
    "Helvetica Neue", Helvetica, Arial, sans-serif;
  --font-text:
    "Roobert", "Inter var", -apple-system, BlinkMacSystemFont,
    "Helvetica Neue", Helvetica, Arial, sans-serif;
}

/* ---------- Clay: Buttons -------------------------------------- */
/* Chunky ink-bordered tiles with hard offset shadow. Tilt on hover,
   collapse on press. No blur anywhere. */
:root[data-theme="clay"] .btn,
:root[data-theme="clay-dark"] .btn {
  border: 2px solid var(--color-border-strong);
  border-radius: var(--radius-sm);
  padding: 12px 24px;
  font-weight: 600;
  letter-spacing: 0;
  box-shadow: var(--shadow-2);
  transition:
    transform var(--duration-fast) var(--ease-spring),
    box-shadow var(--duration-fast) var(--ease-spring),
    background-color var(--duration-fast) var(--ease-standard);
}
:root[data-theme="clay"] .btn.btn-sm,
:root[data-theme="clay-dark"] .btn.btn-sm {
  padding: 8px 14px;
  border-radius: 10px;
  box-shadow: var(--shadow-1);
}
:root[data-theme="clay"] .btn-primary,
:root[data-theme="clay-dark"] .btn-primary {
  background: var(--color-brand);
  color: var(--color-brand-contrast);
  border-color: var(--color-border-strong);
}
:root[data-theme="clay"] .btn-secondary,
:root[data-theme="clay-dark"] .btn-secondary {
  background: var(--color-surface);
  color: var(--color-text-primary);
}
:root[data-theme="clay"] .btn-ghost,
:root[data-theme="clay-dark"] .btn-ghost {
  background: transparent;
  color: var(--color-text-primary);
  box-shadow: var(--shadow-1);
}
:root[data-theme="clay"] .btn-danger,
:root[data-theme="clay-dark"] .btn-danger {
  background: var(--color-error);
  color: #ffffff;
}
/* Hover: tilt + bigger shadow. */
:root[data-theme="clay"] .btn:hover,
:root[data-theme="clay-dark"] .btn:hover {
  transform: rotate(-8deg) translateY(-2px);
  box-shadow: var(--shadow-4);
}
:root[data-theme="clay"] .btn-ghost:hover,
:root[data-theme="clay-dark"] .btn-ghost:hover {
  transform: rotate(-4deg) translateY(-2px);
  box-shadow: -5px 5px 0 0 var(--color-border-strong);
  background: var(--color-surface-2);
}
/* Active: collapse to pressed state. */
:root[data-theme="clay"] .btn:active,
:root[data-theme="clay-dark"] .btn:active {
  transform: translate(-2px, 2px);
  box-shadow: var(--shadow-1);
}
/* Focus-visible: crisp matcha ring. */
:root[data-theme="clay"] .btn:focus-visible,
:root[data-theme="clay-dark"] .btn:focus-visible {
  outline: 3px solid var(--color-focus);
  outline-offset: 3px;
}
:root[data-theme="clay"] .btn:disabled,
:root[data-theme="clay-dark"] .btn:disabled {
  opacity: 0.55;
  transform: none;
  box-shadow: var(--shadow-1);
  cursor: not-allowed;
}

/* ---------- Clay: Cards --------------------------------------- */
:root[data-theme="clay"] .card,
:root[data-theme="clay-dark"] .card {
  background: var(--color-surface);
  border: 2px solid var(--color-border-strong);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-3);
  transition:
    transform var(--duration-base) var(--ease-spring),
    box-shadow var(--duration-base) var(--ease-spring);
}
/* Clickable cards lift on hover (no rotate — cards are too big). */
:root[data-theme="clay"] .card[role="button"]:hover,
:root[data-theme="clay"] .card.card--interactive:hover,
:root[data-theme="clay"] a .card:hover,
:root[data-theme="clay"] button .card:hover,
:root[data-theme="clay-dark"] .card[role="button"]:hover,
:root[data-theme="clay-dark"] .card.card--interactive:hover,
:root[data-theme="clay-dark"] a .card:hover,
:root[data-theme="clay-dark"] button .card:hover {
  transform: translate(-2px, -2px);
  box-shadow: var(--shadow-4);
}

/* ---------- Clay: Nav items ----------------------------------- */
/* The Apple underline indicator is replaced by a full matcha pill. */
:root[data-theme="clay"] .nav-item,
:root[data-theme="clay-dark"] .nav-item {
  border-radius: 999px;
  padding: 10px 18px;
  transition: background-color var(--duration-fast) var(--ease-standard),
              color var(--duration-fast) var(--ease-standard);
}
:root[data-theme="clay"] .nav-item:hover,
:root[data-theme="clay-dark"] .nav-item:hover {
  background: var(--color-surface-2);
}
:root[data-theme="clay"] .nav-item.active,
:root[data-theme="clay-dark"] .nav-item.active {
  background: var(--color-brand);
  color: var(--color-brand-contrast);
  font-weight: 600;
}
/* Kill the Apple accent-bar ::after indicator under Clay. */
:root[data-theme="clay"] .nav-item.active::after,
:root[data-theme="clay-dark"] .nav-item.active::after {
  display: none;
}

/* ---------- Clay: Chips --------------------------------------- */
:root[data-theme="clay"] .chip,
:root[data-theme="clay-dark"] .chip {
  border-radius: 999px;
  border: 1.5px solid var(--color-border-strong);
  padding: 4px 10px;
  font-weight: 500;
  transition: transform var(--duration-fast) var(--ease-spring);
}
:root[data-theme="clay"] .chip:hover,
:root[data-theme="clay-dark"] .chip:hover {
  transform: scale(1.05);
}

/* ---------- Clay: Inputs / selects / textareas ---------------- */
:root[data-theme="clay"] input[type="text"],
:root[data-theme="clay"] input[type="email"],
:root[data-theme="clay"] input[type="password"],
:root[data-theme="clay"] input[type="number"],
:root[data-theme="clay"] input[type="search"],
:root[data-theme="clay"] input[type="date"],
:root[data-theme="clay"] input[type="tel"],
:root[data-theme="clay"] input[type="url"],
:root[data-theme="clay"] select,
:root[data-theme="clay"] textarea,
:root[data-theme="clay-dark"] input[type="text"],
:root[data-theme="clay-dark"] input[type="email"],
:root[data-theme="clay-dark"] input[type="password"],
:root[data-theme="clay-dark"] input[type="number"],
:root[data-theme="clay-dark"] input[type="search"],
:root[data-theme="clay-dark"] input[type="date"],
:root[data-theme="clay-dark"] input[type="tel"],
:root[data-theme="clay-dark"] input[type="url"],
:root[data-theme="clay-dark"] select,
:root[data-theme="clay-dark"] textarea {
  background: var(--color-surface);
  border: 2px solid var(--color-border-strong);
  border-radius: var(--radius-sm);
  padding: 10px 14px;
  box-shadow: inset 0 2px 0 rgba(26, 26, 26, 0.05);
  transition: box-shadow var(--duration-fast) var(--ease-standard);
}
:root[data-theme="clay"] input:focus-visible,
:root[data-theme="clay"] select:focus-visible,
:root[data-theme="clay"] textarea:focus-visible,
:root[data-theme="clay-dark"] input:focus-visible,
:root[data-theme="clay-dark"] select:focus-visible,
:root[data-theme="clay-dark"] textarea:focus-visible {
  outline: 3px solid var(--color-focus);
  outline-offset: 2px;
  box-shadow: var(--shadow-1);
}

/* ---------- Clay: Sidebar/page background -------------------- */
/* Make sure the page canvas is cream (not gray/white) even when old
   rules reference hardcoded backgrounds. */
:root[data-theme="clay"] body,
:root[data-theme="clay-dark"] body {
  background: var(--color-bg);
  color: var(--color-text-primary);
}

/* ---------- Clay: dedup pair card exit animation ------------- */
/* When renderDedupPair dismisses a card, JS adds .clay-dedup-dismissed
   which triggers this playful tilt-out before removeChild(). */
@keyframes clay-dedup-exit {
  0%   { transform: rotate(0) translateX(0); opacity: 1; }
  60%  { transform: rotate(6deg) translateX(20px); opacity: 0.6; }
  100% { transform: rotate(6deg) translateX(40px); opacity: 0; }
}
:root[data-theme="clay"] .clay-dedup-dismissed,
:root[data-theme="clay-dark"] .clay-dedup-dismissed {
  animation: clay-dedup-exit 400ms var(--ease-spring) forwards;
  pointer-events: none;
}

/* ---------- Clay: toast stripe widens ------------------------ */
:root[data-theme="clay"] #toast,
:root[data-theme="clay-dark"] #toast,
:root[data-theme="clay"] #action-toast,
:root[data-theme="clay-dark"] #action-toast {
  border-width: 2px;
  border-left-width: 6px;
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-3);
}

/* ---------- Clay: dedup pair card — Lemon left border -------- */
/* Give duplicate pairs a playful Lemon accent stripe so they stand
   out from regular receipt rows under Clay. The element still uses
   its inline border styles for Apple; we override under Clay only. */
:root[data-theme="clay"] .dedup-pair-card,
:root[data-theme="clay-dark"] .dedup-pair-card {
  border: var(--stroke-2) solid var(--color-border) !important;
  border-left: 6px solid var(--color-swatch-lemon) !important;
  border-radius: var(--radius-md) !important;
  background: var(--color-surface);
  box-shadow: var(--shadow-1);
  transition: box-shadow var(--duration-base) var(--ease-spring),
              transform var(--duration-base) var(--ease-spring);
}
:root[data-theme="clay"] .dedup-pair-card:hover,
:root[data-theme="clay-dark"] .dedup-pair-card:hover {
  box-shadow: var(--shadow-2);
  transform: translate(-1px, -1px);
}

/* ---------- Clay: Upload dropzone — cream-deep canvas -------- */
/* Swap the gray-surface dropzone for a warm cream-deep canvas, bump
   the radius to 40px, thicken the dashed ink border, and replace the
   shake/invalid animations with a Matcha pulse on drag-over. */
:root[data-theme="clay"] .drop-zone,
:root[data-theme="clay-dark"] .drop-zone {
  background: var(--color-cream-deep);
  border: var(--stroke-2) dashed var(--color-text-primary);
  border-radius: var(--radius-xl);
  color: var(--color-text-secondary);
}
:root[data-theme="clay"] .drop-zone:hover,
:root[data-theme="clay"] .drop-zone:focus-visible,
:root[data-theme="clay-dark"] .drop-zone:hover,
:root[data-theme="clay-dark"] .drop-zone:focus-visible {
  background: var(--color-swatch-matcha-soft);
  border-color: var(--color-swatch-matcha);
  color: var(--color-text-primary);
  box-shadow: var(--shadow-2);
}
@keyframes clay-dropzone-pulse {
  0%, 100% { box-shadow: 0 0 0 0 var(--color-swatch-matcha-soft); }
  50%      { box-shadow: 0 0 0 12px transparent; }
}
:root[data-theme="clay"] .drop-zone[data-state="dragover"],
:root[data-theme="clay-dark"] .drop-zone[data-state="dragover"] {
  background: var(--color-swatch-matcha-soft);
  border-color: var(--color-swatch-matcha);
  color: var(--color-text-primary);
  animation: clay-dropzone-pulse 900ms var(--ease-spring) infinite;
}
:root[data-theme="clay"] .drop-zone[data-state="invalid"],
:root[data-theme="clay-dark"] .drop-zone[data-state="invalid"] {
  background: var(--color-swatch-pomegranate-soft);
  border-color: var(--color-swatch-pomegranate);
  color: var(--color-swatch-pomegranate);
}

/* ---------- Clay: Dashboard KPI cards — swatch tints --------- */
/* Paint the first three stat cards in Slushie / Lemon / Matcha soft
   tints to bring playfulness onto the dashboard without touching
   Apple styling. `.dashboard-stats-grid` scope keeps this from
   leaking into other stat grids. */
:root[data-theme="clay"] .dashboard-stats-grid > .stat-card,
:root[data-theme="clay-dark"] .dashboard-stats-grid > .stat-card {
  border: var(--stroke-2) solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-2);
  transition: box-shadow var(--duration-base) var(--ease-spring),
              transform var(--duration-base) var(--ease-spring);
}
:root[data-theme="clay"] .dashboard-stats-grid > .stat-card:nth-child(1),
:root[data-theme="clay-dark"] .dashboard-stats-grid > .stat-card:nth-child(1) {
  background: var(--color-swatch-slushie-soft);
}
:root[data-theme="clay"] .dashboard-stats-grid > .stat-card:nth-child(2),
:root[data-theme="clay-dark"] .dashboard-stats-grid > .stat-card:nth-child(2) {
  background: var(--color-swatch-lemon-soft);
}
:root[data-theme="clay"] .dashboard-stats-grid > .stat-card:nth-child(3),
:root[data-theme="clay-dark"] .dashboard-stats-grid > .stat-card:nth-child(3) {
  background: var(--color-swatch-matcha-soft);
}
:root[data-theme="clay"] .dashboard-stats-grid > .stat-card:nth-child(4),
:root[data-theme="clay-dark"] .dashboard-stats-grid > .stat-card:nth-child(4) {
  background: var(--color-swatch-ube-soft);
}
:root[data-theme="clay"] .dashboard-stats-grid > .stat-card:hover,
:root[data-theme="clay-dark"] .dashboard-stats-grid > .stat-card:hover {
  box-shadow: var(--shadow-3);
  transform: translate(-2px, -2px);
}

/* ---------- Shopping: Ready-to-Bill reconcile field ---------- */
/* Inline variant (desktop table cell): compact, clear label. */
.shopping-actual-field {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 0.85rem;
  margin-top: 6px;
}
.shopping-actual-field label {
  color: var(--muted, #666);
  font-weight: 600;
  white-space: nowrap;
}
.shopping-actual-input-wrap {
  position: relative;
  display: inline-flex;
  align-items: center;
}
.shopping-actual-prefix {
  position: absolute;
  left: 8px;
  color: var(--muted, #666);
  font-weight: 600;
  pointer-events: none;
}
.shopping-actual-field input {
  padding-left: 18px;
  width: 96px;
  font-weight: 600;
}
.shopping-actual-check {
  color: #2fa36b;
  font-weight: 700;
  margin-left: 6px;
}
.shopping-actual-hint {
  color: var(--muted, #666);
  font-size: 0.78rem;
  margin-left: auto;
}

/* Strip variant (mobile): full-width band between summary and detail,
   always visible when in ready-to-bill mode. */
.shopping-actual-field--strip {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  margin: 0;
  border-top: 1px solid var(--color-border, #e5e5e5);
  background: rgba(0, 0, 0, 0.02);
}
.shopping-actual-field--strip label {
  flex: 0 0 auto;
  font-size: 0.82rem;
}
.shopping-actual-field--strip .shopping-actual-input-wrap {
  flex: 1 1 auto;
}
.shopping-actual-field--strip input {
  width: 100%;
  min-height: 38px;
  font-size: 1rem;
  padding-left: 22px;
}
.shopping-actual-field--strip .shopping-actual-prefix {
  left: 10px;
  font-size: 1rem;
}

/* Empty state — gently pull attention. */
.shopping-actual-field--strip.is-empty {
  background: rgba(245, 216, 110, 0.10);
}
.shopping-actual-field--strip.is-filled {
  background: rgba(47, 163, 107, 0.08);
}

/* Clay theme: louder, friendlier. */
:root[data-theme="clay"] .shopping-actual-field--strip,
:root[data-theme="clay-dark"] .shopping-actual-field--strip {
  border-top: var(--stroke-2) solid var(--color-border);
  padding: 12px 16px;
  gap: 12px;
}
:root[data-theme="clay"] .shopping-actual-field--strip.is-empty,
:root[data-theme="clay-dark"] .shopping-actual-field--strip.is-empty {
  background: var(--color-swatch-lemon-soft);
}
:root[data-theme="clay"] .shopping-actual-field--strip.is-filled,
:root[data-theme="clay-dark"] .shopping-actual-field--strip.is-filled {
  background: var(--color-swatch-matcha-soft);
}
:root[data-theme="clay"] .shopping-actual-field--strip input,
:root[data-theme="clay-dark"] .shopping-actual-field--strip input {
  border-radius: var(--radius-md);
  border: var(--stroke-2) solid var(--color-border);
  background: var(--color-bg-primary, #fff);
}
:root[data-theme="clay"] .shopping-actual-field--strip label,
:root[data-theme="clay-dark"] .shopping-actual-field--strip label {
  font-weight: 700;
  color: var(--color-text);
}

/* ---------- Shopping: Past Trips card ---------- */
#shopping-past-trips-card {
  margin-top: 12px;
}
.shopping-past-trips-header {
  cursor: pointer;
  user-select: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
.shopping-past-trips-header #shopping-past-trips-chevron {
  color: var(--muted, #666);
  font-size: 0.9rem;
}
.shopping-past-trip {
  border-top: 1px solid var(--color-border, #e5e5e5);
}
.shopping-past-trip:first-child {
  border-top: none;
}
/* Past Trips — friendly block layout, with a fixed-column grid on the
   totals line so the dollar amounts line up vertically across rows. */
.shopping-past-trip-summary {
  width: 100%;
  background: transparent;
  border: none;
  padding: 12px 14px;
  display: flex;
  align-items: center;
  gap: 10px;
  text-align: left;
  cursor: pointer;
  color: inherit;
  font: inherit;
}
.shopping-past-trip-summary:hover {
  background: rgba(0, 0, 0, 0.03);
}
.shopping-past-trip-meta {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.shopping-past-trip-date {
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* Header row: date on the left, variance pill on the right, so the
   totals line below is free to hold just Est + Actual. */
.pt-headrow {
  display: flex;
  align-items: baseline;
  gap: 8px;
}
.pt-headrow .shopping-past-trip-date {
  flex: 1 1 auto;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.pt-headrow .shopping-past-trip-variance {
  margin-left: auto;
  flex: 0 0 auto;
}

/* Totals row — inline Est / Actual. The tabular-nums + fixed min-width
   on .pt-v puts every dollar value in the same-width slot, so "Actual"
   (and therefore the Actual value) line up vertically across rows. */
.shopping-past-trip-totals {
  display: flex;
  gap: 14px;
  align-items: baseline;
  font-size: 0.9rem;
  color: var(--muted, #666);
}
.pt-kv {
  white-space: nowrap;
}
.pt-v {
  color: var(--color-text, inherit);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  display: inline-block;
  min-width: 58px;
  text-align: right;
  margin-left: 3px;
}
.shopping-past-trip-variance {
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 0.78rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.shopping-past-trip-variance.over {
  background: rgba(224, 79, 79, 0.12);
  color: #c23030;
}
.shopping-past-trip-variance.under {
  background: rgba(47, 163, 107, 0.14);
  color: #1f7a4e;
}
.shopping-past-trip-variance.flat {
  background: rgba(0, 0, 0, 0.08);
  color: var(--muted, #666);
}
.shopping-past-trip-count {
  font-size: 0.82rem;
  color: var(--muted, #666);
}
.shopping-past-trip-chevron {
  color: var(--muted, #666);
  flex: 0 0 auto;
}
.shopping-past-trip-detail {
  padding: 6px 14px 14px;
  background: rgba(0, 0, 0, 0.02);
}
.shopping-past-trip-items {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.9rem;
}
.shopping-past-trip-items th,
.shopping-past-trip-items td {
  padding: 8px 6px;
  border-bottom: 1px solid var(--color-border, #e5e5e5);
}
.shopping-past-trip-items th {
  color: var(--muted, #666);
  font-weight: 600;
  font-size: 0.82rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.shopping-past-trip-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  margin-top: 10px;
}

/* Clay: warmer panel + soft row hover tied to swatch tokens. */
:root[data-theme="clay"] .shopping-past-trip-detail,
:root[data-theme="clay-dark"] .shopping-past-trip-detail {
  background: var(--color-swatch-slushie-soft);
  border-radius: var(--radius-md);
  padding: 10px 14px 14px;
}
:root[data-theme="clay"] .shopping-past-trip-summary:hover,
:root[data-theme="clay-dark"] .shopping-past-trip-summary:hover {
  background: var(--color-swatch-matcha-soft);
}
:root[data-theme="clay"] .shopping-past-trip-variance.under,
:root[data-theme="clay-dark"] .shopping-past-trip-variance.under {
  background: var(--color-swatch-matcha-soft);
  color: var(--color-swatch-matcha);
}
:root[data-theme="clay"] .shopping-past-trip-variance.over,
:root[data-theme="clay-dark"] .shopping-past-trip-variance.over {
  background: var(--color-swatch-pomegranate-soft);
  color: var(--color-swatch-pomegranate);
}

/* ---------- Inventory: long-press context menu ---------- */
.inv-context-menu {
  position: fixed;
  z-index: 10000;
  min-width: 220px;
  max-width: 280px;
  padding: 6px;
  background: var(--color-surface, var(--surface, #1b1b1d));
  border: 1px solid var(--color-border, rgba(255, 255, 255, 0.1));
  border-radius: 14px;
  box-shadow: 0 18px 44px rgba(0, 0, 0, 0.45);
  animation: inv-ctx-in 0.14s ease-out;
  color: var(--color-text, inherit);
  user-select: none;
  -webkit-user-select: none;
}
@keyframes inv-ctx-in {
  from { opacity: 0; transform: scale(0.96); }
  to { opacity: 1; transform: scale(1); }
}
.inv-context-title {
  padding: 8px 12px 6px;
  font-weight: 700;
  font-size: 0.85rem;
  color: var(--muted, #888);
  border-bottom: 1px solid var(--color-border, rgba(255, 255, 255, 0.08));
  margin-bottom: 4px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.inv-context-item {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 11px 12px;
  background: transparent;
  border: none;
  border-radius: 10px;
  cursor: pointer;
  color: inherit;
  font: inherit;
  font-size: 0.95rem;
  text-align: left;
}
.inv-context-item:hover,
.inv-context-item:active {
  background: rgba(255, 255, 255, 0.08);
}
.inv-context-icon {
  font-size: 1.1rem;
  flex: 0 0 22px;
  text-align: center;
}

.inv-regular-star {
  font-size: 0.95em;
  margin-right: 2px;
}

/* Clay: friendlier context menu matching Clay surface tokens. */
:root[data-theme="clay"] .inv-context-menu,
:root[data-theme="clay-dark"] .inv-context-menu {
  border-width: var(--stroke-2);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-4);
  padding: 8px;
}
:root[data-theme="clay"] .inv-context-item:hover,
:root[data-theme="clay-dark"] .inv-context-item:hover {
  background: var(--color-swatch-matcha-soft);
}

/* === Overscroll Navigation Affordance ===
   Pull past the top/bottom of a page to navigate to the previous/next
   sidebar page. Suppresses iOS browser pull-to-refresh so our handler
   owns the gesture; the trade-off is that page-level rubber-band is
   gone, but the labeled banner gives explicit visual feedback. */
html,
body {
  overscroll-behavior-y: contain;
}

.osn {
  position: fixed;
  left: 50%;
  top: calc(env(safe-area-inset-top, 0px) + 12px);
  transform: translateX(-50%);
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 10px 16px;
  background: var(--surface, #1f2024);
  color: var(--color-text, #fff);
  border: 1px solid var(--color-border, rgba(255, 255, 255, 0.12));
  border-radius: 999px;
  box-shadow: 0 14px 36px rgba(0, 0, 0, 0.32);
  font-size: 0.92rem;
  font-weight: 600;
  pointer-events: none;
  opacity: 0;
  z-index: 9999;
  transition: opacity 140ms ease-out, background 160ms ease-out,
    color 160ms ease-out;
  white-space: nowrap;
  max-width: calc(100vw - 32px);
  overflow: hidden;
  text-overflow: ellipsis;
}
.osn.is-visible {
  opacity: 1;
}
.osn.is-bottom {
  top: auto;
  bottom: calc(env(safe-area-inset-bottom, 0px) + 12px);
}
.osn.is-armed {
  background: rgba(46, 160, 67, 0.18);
  color: #2fa36b;
  border-color: rgba(46, 160, 67, 0.3);
}
.osn.is-disabled {
  opacity: 0.55;
}
.osn.is-snapping {
  transition: opacity 220ms ease-out, transform 240ms cubic-bezier(0.2, 0.9, 0.3, 1.2);
  transform: translateX(-50%) translateY(0) !important;
}
.osn__arrow {
  font-size: 1rem;
  font-weight: 700;
  line-height: 1;
}

/* ---------- Iris page transition (overscroll / wheel commit) ------- */
/* Circle-wipe veil that expands from the pull-origin edge, covers the
   viewport briefly while nav() swaps pages, then contracts out to
   reveal the new page. Origin varies by direction so the motion feels
   anchored to where the gesture happened. Runs on top of the during-pull
   banner's z-index so the banner snaps away cleanly underneath. */
.iris-veil {
  --iris-x: 50%;
  --iris-y: 100%;
  position: fixed;
  inset: 0;
  z-index: 10000;
  /* Solid black so the matrix canvas reads with high contrast. */
  background: #000;
  pointer-events: none;
  clip-path: circle(0% at var(--iris-x) var(--iris-y));
  -webkit-clip-path: circle(0% at var(--iris-x) var(--iris-y));
  will-change: clip-path;
  overflow: hidden;
}
.iris-matrix-canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
}
.iris-veil.is-opening {
  animation: iris-open 240ms cubic-bezier(0.4, 0, 0.2, 1) forwards;
}
.iris-veil.is-closing {
  animation: iris-close 280ms cubic-bezier(0.4, 0, 0.2, 1) forwards;
}
.iris-veil__badge {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%) scale(0.88);
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 12px 20px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.08);
  border: 1px solid rgba(255, 255, 255, 0.22);
  color: #fff;
  font-size: 1.05rem;
  font-weight: 700;
  white-space: nowrap;
  opacity: 0;
  transition: opacity 220ms cubic-bezier(0.2, 0.9, 0.3, 1.2),
    transform 260ms cubic-bezier(0.2, 0.9, 0.3, 1.2);
}
.iris-veil.is-held .iris-veil__badge {
  opacity: 1;
  transform: translate(-50%, -50%) scale(1);
}
@keyframes iris-open {
  from {
    clip-path: circle(0% at var(--iris-x) var(--iris-y));
    -webkit-clip-path: circle(0% at var(--iris-x) var(--iris-y));
  }
  to {
    clip-path: circle(160% at var(--iris-x) var(--iris-y));
    -webkit-clip-path: circle(160% at var(--iris-x) var(--iris-y));
  }
}
@keyframes iris-close {
  from {
    clip-path: circle(160% at var(--iris-x) var(--iris-y));
    -webkit-clip-path: circle(160% at var(--iris-x) var(--iris-y));
  }
  to {
    clip-path: circle(0% at var(--iris-x) var(--iris-y));
    -webkit-clip-path: circle(0% at var(--iris-x) var(--iris-y));
  }
}
@media (prefers-reduced-motion: reduce) {
  .iris-veil {
    clip-path: none;
    -webkit-clip-path: none;
    opacity: 0;
    transition: opacity 180ms linear;
  }
  .iris-veil.is-opening { opacity: 0.92; animation: none; }
  .iris-veil.is-closing { opacity: 0; animation: none; }
}

/* Clay theme: louder armed pill using matcha tokens. */
:root[data-theme="clay"] .osn,
:root[data-theme="clay-dark"] .osn {
  border-width: var(--stroke-2);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-3);
}
:root[data-theme="clay"] .osn.is-armed,
:root[data-theme="clay-dark"] .osn.is-armed {
  background: var(--color-swatch-matcha-soft);
  color: var(--color-swatch-matcha);
  border-color: var(--color-swatch-matcha);
}

@media (prefers-reduced-motion: reduce) {
  .osn {
    transition: opacity 100ms linear;
  }
  .osn.is-snapping {
    transition: opacity 100ms linear;
  }
}


/* ===================================================================
 * NOTION THEME — opt-in component layer (data-theme="notion" | "notion-dark")
 *
 * Apple themes are unaffected. Spec:
 * design/Design System inspired by Notion.md
 *
 * Philosophy (spec §2):
 *   - Warm paper, not cold glass
 *   - Whisper borders (1px), multi-layer sub-0.05 shadows
 *   - Notion Blue (#0075de) is the only saturated chrome color
 *   - Tiny movement (≤4px translate, scale 0.98–1.02), never bouncy
 *   - Differentiation by pill badge + icon, never palette swap
 * =================================================================== */

/* ---------- Notion: page canvas + body ----------------------- */
:root[data-theme="notion"] body,
:root[data-theme="notion-dark"] body {
  background: var(--color-bg);
  color: var(--color-text-primary);
}

/* Tabular numerics for ledger feel — applied to any cell with the
   .num-tabular helper, plus generic .stat-value chrome. (Spec §4 numerics.) */
:root[data-theme="notion"] .num-tabular,
:root[data-theme="notion-dark"] .num-tabular,
:root[data-theme="notion"] .stat-value,
:root[data-theme="notion-dark"] .stat-value {
  font-variant-numeric: tabular-nums lining-nums;
}

/* ---------- Notion: Buttons ---------------------------------- */
/* Spec §5: 8/16 padding, 4px radius, 15px / weight 600. Hover bg
   shift only. Active scale(0.98). Focus 2px outline. */
:root[data-theme="notion"] .btn,
:root[data-theme="notion-dark"] .btn {
  border-radius: var(--radius-xs);
  padding: 8px 16px;
  font-size: 15px;
  font-weight: 600;
  letter-spacing: 0;
  border: 1px solid transparent;
  box-shadow: none;
  transition:
    background-color var(--duration-fast) var(--ease-standard),
    color var(--duration-fast) var(--ease-standard),
    transform var(--duration-fast) var(--ease-standard);
}
:root[data-theme="notion"] .btn.btn-sm,
:root[data-theme="notion-dark"] .btn.btn-sm {
  padding: 6px 12px;
  font-size: 14px;
}

:root[data-theme="notion"] .btn-primary,
:root[data-theme="notion-dark"] .btn-primary {
  background: var(--color-brand);
  color: var(--color-brand-contrast);
}
:root[data-theme="notion"] .btn-primary:hover,
:root[data-theme="notion-dark"] .btn-primary:hover {
  background: var(--color-brand-hover);
}

:root[data-theme="notion"] .btn-secondary,
:root[data-theme="notion-dark"] .btn-secondary {
  background: rgba(0, 0, 0, 0.05);
  color: var(--color-text-primary);
}
:root[data-theme="notion-dark"] .btn-secondary {
  background: rgba(255, 255, 255, 0.07);
}
:root[data-theme="notion"] .btn-secondary:hover {
  background: rgba(0, 0, 0, 0.08);
}
:root[data-theme="notion-dark"] .btn-secondary:hover {
  background: rgba(255, 255, 255, 0.10);
}

:root[data-theme="notion"] .btn-ghost,
:root[data-theme="notion-dark"] .btn-ghost {
  background: transparent;
  color: var(--color-text-primary);
}
:root[data-theme="notion"] .btn-ghost:hover {
  background: rgba(0, 0, 0, 0.04);
}
:root[data-theme="notion-dark"] .btn-ghost:hover {
  background: rgba(255, 255, 255, 0.06);
}

/* Destructive — confirmation modals only per spec §5. */
:root[data-theme="notion"] .btn-danger,
:root[data-theme="notion-dark"] .btn-danger {
  background: var(--color-surface);
  color: #c4002b;
  border-color: #f0c4cc;
}
:root[data-theme="notion-dark"] .btn-danger {
  color: var(--color-error);
  border-color: rgba(240, 88, 110, 0.40);
}
:root[data-theme="notion"] .btn-danger:hover,
:root[data-theme="notion-dark"] .btn-danger:hover {
  background: var(--color-error-soft);
}

:root[data-theme="notion"] .btn:active,
:root[data-theme="notion-dark"] .btn:active {
  transform: scale(0.98);
}

:root[data-theme="notion"] .btn:focus-visible,
:root[data-theme="notion-dark"] .btn:focus-visible {
  outline: 2px solid var(--color-focus);
  outline-offset: 2px;
}

:root[data-theme="notion"] .btn:disabled,
:root[data-theme="notion-dark"] .btn:disabled {
  background: rgba(0, 0, 0, 0.03);
  color: var(--color-text-muted);
  cursor: not-allowed;
  transform: none;
}
:root[data-theme="notion-dark"] .btn:disabled {
  background: rgba(255, 255, 255, 0.04);
}

/* ---------- Notion: Cards ----------------------------------- */
/* Spec §5: white bg, whisper border, 12px radius, --shadow-2. Hover
   intensifies shadow only — no lift, no border color change. */
:root[data-theme="notion"] .card,
:root[data-theme="notion-dark"] .card {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-2);
  transition: box-shadow var(--duration-base) var(--ease-standard);
}
:root[data-theme="notion"] .card[role="button"]:hover,
:root[data-theme="notion"] .card.card--interactive:hover,
:root[data-theme="notion-dark"] .card[role="button"]:hover,
:root[data-theme="notion-dark"] .card.card--interactive:hover {
  box-shadow: var(--shadow-3);
}

/* Featured/hero card — 16px radius + deep shadow + warm-white interior. */
:root[data-theme="notion"] .card.card--featured,
:root[data-theme="notion-dark"] .card.card--featured {
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-3);
  background: var(--color-warm-paper);
}

/* ---------- Notion: Sidebar + nav items --------------------- */
/* Spec §5: 240px sidebar (the existing layout already provides this),
   white bg, right whisper border. Nav items 15px / 500, 8px 12px,
   5px radius. Active = brand-soft bg + brand text + 600. */
:root[data-theme="notion"] .sidebar,
:root[data-theme="notion-dark"] .sidebar {
  background: var(--color-surface);
  border-right: 1px solid var(--color-border);
}
:root[data-theme="notion"] .nav-item,
:root[data-theme="notion-dark"] .nav-item {
  border-radius: var(--radius-sm);
  padding: 8px 12px;
  font-size: 15px;
  font-weight: 500;
  letter-spacing: 0;
  transition:
    background-color var(--duration-fast) var(--ease-standard),
    color var(--duration-fast) var(--ease-standard);
}
:root[data-theme="notion"] .nav-item:hover {
  background: rgba(0, 0, 0, 0.04);
}
:root[data-theme="notion-dark"] .nav-item:hover {
  background: rgba(255, 255, 255, 0.05);
}
:root[data-theme="notion"] .nav-item.active,
:root[data-theme="notion-dark"] .nav-item.active {
  background: var(--color-brand-soft);
  color: var(--color-brand);
  font-weight: 600;
}
/* Disable the Apple accent-bar ::after indicator under Notion. */
:root[data-theme="notion"] .nav-item.active::after,
:root[data-theme="notion-dark"] .nav-item.active::after {
  display: none;
}

/* ---------- Notion: Form inputs ----------------------------- */
/* Spec §5: white bg, 1px #dddddd border, 4px radius, 6px 10px
   padding, 16px / 400. Focus = #097fe8 border + 2px outer ring. */
:root[data-theme="notion"] input[type="text"],
:root[data-theme="notion"] input[type="email"],
:root[data-theme="notion"] input[type="password"],
:root[data-theme="notion"] input[type="number"],
:root[data-theme="notion"] input[type="search"],
:root[data-theme="notion"] input[type="date"],
:root[data-theme="notion"] input[type="tel"],
:root[data-theme="notion"] input[type="url"],
:root[data-theme="notion"] select,
:root[data-theme="notion"] textarea,
:root[data-theme="notion-dark"] input[type="text"],
:root[data-theme="notion-dark"] input[type="email"],
:root[data-theme="notion-dark"] input[type="password"],
:root[data-theme="notion-dark"] input[type="number"],
:root[data-theme="notion-dark"] input[type="search"],
:root[data-theme="notion-dark"] input[type="date"],
:root[data-theme="notion-dark"] input[type="tel"],
:root[data-theme="notion-dark"] input[type="url"],
:root[data-theme="notion-dark"] select,
:root[data-theme="notion-dark"] textarea {
  background: var(--color-surface);
  color: var(--color-text-primary);
  border: 1px solid #dddddd;
  border-radius: var(--radius-xs);
  padding: 6px 10px;
  font-size: 16px;
  font-weight: 400;
  font-family: inherit;
  box-shadow: none;
  transition:
    border-color var(--duration-fast) var(--ease-standard),
    box-shadow var(--duration-fast) var(--ease-standard);
}
:root[data-theme="notion-dark"] input,
:root[data-theme="notion-dark"] select,
:root[data-theme="notion-dark"] textarea {
  border-color: var(--color-border);
}
:root[data-theme="notion"] input::placeholder,
:root[data-theme="notion"] textarea::placeholder,
:root[data-theme="notion-dark"] input::placeholder,
:root[data-theme="notion-dark"] textarea::placeholder {
  color: var(--color-text-muted);
}
:root[data-theme="notion"] input:focus-visible,
:root[data-theme="notion"] select:focus-visible,
:root[data-theme="notion"] textarea:focus-visible,
:root[data-theme="notion-dark"] input:focus-visible,
:root[data-theme="notion-dark"] select:focus-visible,
:root[data-theme="notion-dark"] textarea:focus-visible {
  outline: none;
  border-color: var(--color-focus);
  box-shadow: 0 0 0 2px rgba(9, 127, 232, 0.20);
}

/* Receipt correction editor — numeric inputs right-aligned + tabular. */
:root[data-theme="notion"] .receipt-editor-grid input[type="number"],
:root[data-theme="notion-dark"] .receipt-editor-grid input[type="number"],
:root[data-theme="notion"] input.num-tabular,
:root[data-theme="notion-dark"] input.num-tabular {
  text-align: right;
  font-variant-numeric: tabular-nums lining-nums;
}

/* ---------- Notion: Chips ----------------------------------- */
:root[data-theme="notion"] .chip,
:root[data-theme="notion-dark"] .chip {
  border-radius: var(--radius-pill);
  border: 1px solid var(--color-border);
  background: var(--color-surface);
  color: var(--color-text-secondary);
  padding: 4px 10px;
  font-size: 13px;
  font-weight: 500;
  transition: background-color var(--duration-fast) var(--ease-standard);
}
:root[data-theme="notion"] .chip:hover {
  background: rgba(0, 0, 0, 0.04);
}
:root[data-theme="notion-dark"] .chip:hover {
  background: rgba(255, 255, 255, 0.05);
}
:root[data-theme="notion"] .chip.active,
:root[data-theme="notion-dark"] .chip.active {
  background: var(--color-brand-soft);
  color: var(--color-brand);
  border-color: var(--color-brand);
}

/* ---------- Notion: Pill badges (theme-neutral classes) ----- */
/* Per spec §5 Pill Badges + §11 Three-domain differentiation:
   - 4/8 padding, 9999px radius, 12px / weight 600, +0.125px tracking
   - Always paired with an icon (emoji in markup, or .badge--icon ::before)
   - Tokens fall back to Notion default values so the classes work in
     any theme; Apple/Clay receive the spec colors out of the box. */
.badge--pill {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 4px 8px;
  border-radius: 9999px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.125px;
  white-space: nowrap;
  line-height: 1.33;
  border: none;
}

/* Status / info — "Manual entry", "OCR reviewed", "New", "Live" */
.badge--info {
  background: var(--color-badge-info-bg, #f2f9ff);
  color: var(--color-badge-info-text, #097fe8);
}

/* Domain — paired with shopping-basket / utensils / receipt icon */
.badge--domain.badge--grocery {
  background: var(--color-domain-grocery-bg, #fef5e7);
  color: var(--color-domain-grocery-text, #8a5a00);
}
.badge--domain.badge--restaurant {
  background: var(--color-domain-restaurant-bg, #fde8f0);
  color: var(--color-domain-restaurant-text, #a0216e);
}
.badge--domain.badge--expense {
  background: var(--color-domain-expense-bg, #edf2fb);
  color: var(--color-domain-expense-text, #2a4a99);
}

/* Trusted-device scope — Shared Household / Kitchen Display / Read Only */
.badge--scope {
  background: var(--color-badge-scope-bg, rgba(0, 0, 0, 0.05));
  color: var(--color-badge-scope-text, #615d59);
}
.badge--scope.badge--scope-readonly::before {
  content: "🔒";
  font-size: 11px;
  margin-right: 2px;
}

/* Contribution streak / rank — pink, sparing use */
.badge--streak {
  background: var(--color-badge-streak-bg, #fde8f0);
  color: var(--color-badge-streak-text, #a0216e);
}

/* OCR status — appears at the top of the receipt correction editor.
   Spec §11 calls for "OCR reviewed · 2m ago" tinted info pill. */
.badge--ocr-status {
  background: var(--color-badge-info-bg, #f2f9ff);
  color: var(--color-badge-info-text, #097fe8);
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px;
  border-radius: 9999px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.125px;
}
.badge--ocr-status::before {
  content: "✓";
  font-weight: 700;
}

/* Live-dot (MQTT/HA readouts — spec §11 final paragraph) */
.badge--live-dot {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
  font-size: 12px;
  font-weight: 500;
  background: var(--color-warm-paper, #f6f5f4);
  padding: 4px 10px;
  border-radius: 4px;
  color: var(--color-text-secondary);
}
.badge--live-dot::before {
  content: "";
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--color-text-muted);
}
.badge--live-dot.is-live::before {
  background: var(--color-success, #1aae39);
}

/* ---------- Notion: Stat cards (Dashboard) ------------------ */
/* Spec §5: white bg, whisper border, 12px radius, --shadow-card.
   Spec §12: label 14/500/secondary, value 40/700/near-black with
   tabular-nums, optional trend below. */
:root[data-theme="notion"] .stat-card,
:root[data-theme="notion-dark"] .stat-card {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-2);
  padding: 24px;
}
:root[data-theme="notion"] .stat-card .stat-label,
:root[data-theme="notion-dark"] .stat-card .stat-label {
  font-size: 14px;
  font-weight: 500;
  color: var(--color-text-secondary);
  margin-bottom: 8px;
}
:root[data-theme="notion"] .stat-card .stat-value,
:root[data-theme="notion-dark"] .stat-card .stat-value {
  font-size: 40px;
  font-weight: 700;
  line-height: 1.05;
  color: var(--color-text-primary);
  font-variant-numeric: tabular-nums lining-nums;
  letter-spacing: -0.625px;
}
/* Featured ranking card (top-three Dashboard household ranking). */
:root[data-theme="notion"] .stat-card.stat-card--featured,
:root[data-theme="notion-dark"] .stat-card.stat-card--featured {
  background: var(--color-warm-paper);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-3);
}

/* ---------- Notion: Empty state ----------------------------- */
/* Spec §5: warm-white bg, 64px icon in muted, 22/700 title,
   16/secondary body, optional CTA. */
:root[data-theme="notion"] .empty-state,
:root[data-theme="notion-dark"] .empty-state {
  background: var(--color-warm-paper);
  border-radius: var(--radius-xl);
  padding: 48px 32px;
  text-align: center;
  border: 1px solid var(--color-border);
}
:root[data-theme="notion"] .empty-state .icon,
:root[data-theme="notion-dark"] .empty-state .icon {
  font-size: 64px;
  color: var(--color-text-muted);
  display: block;
  margin: 0 auto 16px;
}
:root[data-theme="notion"] .empty-state h3,
:root[data-theme="notion"] .empty-state .empty-state-title,
:root[data-theme="notion-dark"] .empty-state h3,
:root[data-theme="notion-dark"] .empty-state .empty-state-title {
  font-size: 22px;
  font-weight: 700;
  color: var(--color-text-primary);
  margin-bottom: 8px;
  letter-spacing: -0.25px;
}
:root[data-theme="notion"] .empty-state p,
:root[data-theme="notion-dark"] .empty-state p {
  font-size: 16px;
  color: var(--color-text-secondary);
  line-height: 1.5;
  margin-bottom: 16px;
}

/* ---------- Notion: Section headings ------------------------ */
/* Spec §4 hierarchy: Section Heading 48/700, Sub-heading 26/700,
   Card Title 22/700. The existing h1/h2/h3 in the SPA need a
   theme-scoped re-tuning. */
:root[data-theme="notion"] .page-header h1,
:root[data-theme="notion-dark"] .page-header h1 {
  font-size: 48px;
  font-weight: 700;
  line-height: 1.0;
  letter-spacing: -1.5px;
  color: var(--color-text-primary);
}
:root[data-theme="notion"] .page-header p,
:root[data-theme="notion-dark"] .page-header p {
  font-size: 16px;
  color: var(--color-text-secondary);
  line-height: 1.5;
  margin-top: 8px;
}
:root[data-theme="notion"] .card-title,
:root[data-theme="notion-dark"] .card-title {
  font-size: 22px;
  font-weight: 700;
  letter-spacing: -0.25px;
}

/* ---------- Notion: List rows + alternating warm tint ------- */
/* Spec §5 Data Surfaces: white bg, alternating warm-paper-row tint,
   whisper between rows, 12/16 padding, hover row → 0.03 black wash. */
:root[data-theme="notion"] .list-row,
:root[data-theme="notion-dark"] .list-row,
:root[data-theme="notion"] .table-row,
:root[data-theme="notion-dark"] .table-row {
  padding: 12px 16px;
  border-bottom: 1px solid var(--color-border);
  background: var(--color-surface);
  transition: background-color var(--duration-fast) var(--ease-standard);
}
:root[data-theme="notion"] .list-row:nth-child(even),
:root[data-theme="notion-dark"] .list-row:nth-child(even) {
  background: var(--color-warm-paper-row);
}
:root[data-theme="notion"] .list-row:hover,
:root[data-theme="notion-dark"] .list-row:hover {
  background: rgba(0, 0, 0, 0.03);
}
:root[data-theme="notion-dark"] .list-row:hover {
  background: rgba(255, 255, 255, 0.04);
}

/* ---------- Notion: Receipt correction editor structural --- */
/* Spec §11 receipt correction editor: image-left/editor-right at
   ≥1080px, stacked at <1080. Image lives in a 12px-radius card with
   a whisper internal border so it reads as a framed photo. Sticky
   footer holds Save/Cancel with whisper top border.
   Named .receipt-editor-pane to avoid colliding with the existing
   .receipt-editor-grid (a 3-column field grid inside the editor body
   defined in index.html:6433). */
.receipt-editor-pane {
  display: grid;
  grid-template-columns: 1fr;
  gap: 24px;
}
@media (min-width: 1080px) {
  .receipt-editor-pane {
    grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
    align-items: start;
  }
}

.receipt-editor-image-frame {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  overflow: hidden;
  position: relative;
}
.receipt-editor-image-frame img {
  display: block;
  width: 100%;
  height: auto;
  border-bottom: 1px solid var(--color-border);
}
.receipt-editor-image-tools {
  display: flex;
  gap: 8px;
  padding: 12px 16px;
  justify-content: flex-end;
}

.receipt-editor-sticky-footer {
  position: sticky;
  bottom: 0;
  background: var(--color-surface);
  border-top: 1px solid var(--color-border);
  padding: 12px 16px;
  display: flex;
  gap: 8px;
  justify-content: flex-end;
  z-index: 10;
}

/* Receipt-image card frame (per spec §5 — image fills top half with
   12 12 0 0 radius, internal whisper, body padding 16, white bg). */
.receipt-image-card {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  overflow: hidden;
}
.receipt-image-card .receipt-image-card__photo {
  display: block;
  width: 100%;
  height: auto;
  border-bottom: 1px solid var(--color-border);
}
.receipt-image-card .receipt-image-card__body {
  padding: 16px;
}

/* ---------- Notion: Whisper divider ------------------------- */
.divider-whisper {
  border: none;
  border-top: 1px solid var(--color-border);
  margin: 0;
}

/* ===================================================================
 * NOTION: Kitchen Display layout variant (spec §8 + §11)
 * Activated when `body.trusted-device-kitchen-display` is set by
 * applyTrustedDeviceClasses(). 1.25x base type, ≥56px touch zones,
 * motion reduced or disabled. Also picks up dark surfaces if the
 * household prefers them.
 * =================================================================== */
:root[data-theme="notion"] body.trusted-device-kitchen-display,
:root[data-theme="notion-dark"] body.trusted-device-kitchen-display {
  font-size: 20px;  /* 1.25x of 16px base */
  line-height: 1.45;
}
:root[data-theme="notion"] body.trusted-device-kitchen-display .btn,
:root[data-theme="notion-dark"] body.trusted-device-kitchen-display .btn {
  min-height: 56px;
  padding: 14px 24px;
  font-size: 18px;
}
:root[data-theme="notion"] body.trusted-device-kitchen-display .nav-item,
:root[data-theme="notion-dark"] body.trusted-device-kitchen-display .nav-item {
  min-height: 56px;
  padding: 14px 18px;
  font-size: 18px;
}
:root[data-theme="notion"] body.trusted-device-kitchen-display .stat-card .stat-value,
:root[data-theme="notion-dark"] body.trusted-device-kitchen-display .stat-card .stat-value {
  font-size: 50px;  /* 1.25x of 40px */
}
:root[data-theme="notion"] body.trusted-device-kitchen-display input,
:root[data-theme="notion"] body.trusted-device-kitchen-display select,
:root[data-theme="notion"] body.trusted-device-kitchen-display textarea,
:root[data-theme="notion-dark"] body.trusted-device-kitchen-display input,
:root[data-theme="notion-dark"] body.trusted-device-kitchen-display select,
:root[data-theme="notion-dark"] body.trusted-device-kitchen-display textarea {
  min-height: 56px;
  font-size: 18px;
  padding: 12px 14px;
}
/* Suppress any remaining transition/animation on Kitchen Display so the
   surface stays calm at 10ft viewing distance (spec §8 + §10). */
body.trusted-device-kitchen-display *,
body.trusted-device-kitchen-display *::before,
body.trusted-device-kitchen-display *::after {
  transition-duration: 0ms !important;
  animation-duration: 0ms !important;
}
/* Keep focus rings visible — they're functional feedback, not decoration. */
body.trusted-device-kitchen-display *:focus-visible {
  transition-duration: var(--duration-fast, 150ms) !important;
}

/* ===================================================================
 * NOTION: Read-Only scope (spec §8 + §11)
 * When body.trusted-device-read-only is set, primary CTAs render as
 * disabled ghost buttons with a tooltip. We can't set the title via
 * CSS, but we can style buttons to look unmistakably non-actionable.
 *
 * The recommended path is for write-action buttons to also carry the
 * .btn--readonly-disabled marker class (added at render time when
 * scope is read-only). When that class is present, the rule below
 * forces the disabled appearance regardless of the underlying
 * variant. The blanket body-scoped rules below catch the case where
 * a button hasn't been individually marked.
 * =================================================================== */
:root[data-theme="notion"] body.trusted-device-read-only .btn--readonly-disabled,
:root[data-theme="notion-dark"] body.trusted-device-read-only .btn--readonly-disabled,
:root[data-theme="notion"] .btn--readonly-disabled,
:root[data-theme="notion-dark"] .btn--readonly-disabled {
  background: transparent !important;
  color: var(--color-text-muted) !important;
  border: 1px dashed var(--color-border-strong) !important;
  cursor: not-allowed !important;
  pointer-events: none;
}

/* ===================================================================
 * NOTION: Guest demo banner (spec §11)
 * Theme-neutral pinned banner. Hidden by default; updateGuestDemoBanner()
 * un-hides it when isDemoMode() is true.
 * =================================================================== */
.guest-demo-banner {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 16px;
  background: var(--color-badge-info-bg, #f2f9ff);
  color: var(--color-badge-info-text, #097fe8);
  padding: 8px 16px;
  font-size: 14px;
  font-weight: 500;
  border-bottom: 1px solid var(--color-border, rgba(0, 0, 0, 0.1));
  position: sticky;
  top: 0;
  z-index: 100;
}
.guest-demo-banner[hidden] {
  display: none;
}
.guest-demo-banner__label {
  flex: 0 1 auto;
  text-align: center;
}
.guest-demo-banner__cta {
  flex: 0 0 auto;
}
@media (max-width: 600px) {
  .guest-demo-banner {
    flex-direction: column;
    gap: 8px;
    padding: 10px 12px;
  }
}

/* ---------- Notion: Override existing .badge--cat-* classes ----
   So existing receipt rendering automatically picks up the Notion
   domain palette without markup changes. Spec §11 three-domain
   differentiation insists on the exact #fef5e7/#8a5a00 etc. recipe,
   not a color-mix derivative. */
:root[data-theme="notion"] .badge--cat-grocery,
:root[data-theme="notion-dark"] .badge--cat-grocery {
  color: var(--color-domain-grocery-text);
  background: var(--color-domain-grocery-bg);
}
:root[data-theme="notion"] .badge--cat-restaurant,
:root[data-theme="notion-dark"] .badge--cat-restaurant {
  color: var(--color-domain-restaurant-text);
  background: var(--color-domain-restaurant-bg);
}
:root[data-theme="notion"] .badge--cat-utility,
:root[data-theme="notion-dark"] .badge--cat-utility,
:root[data-theme="notion"] .badge--cat-other,
:root[data-theme="notion-dark"] .badge--cat-other {
  color: var(--color-domain-expense-text);
  background: var(--color-domain-expense-bg);
}
/* All cat-* badges adopt the Notion pill recipe per spec §5: 4/8
   padding, pill radius, 12/600/0.125px tracking. */
:root[data-theme="notion"] .badge,
:root[data-theme="notion-dark"] .badge {
  padding: 4px 8px;
  border-radius: 9999px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.125px;
  line-height: 1.33;
}

/* ---------- Notion: Budget progress bar (spec §5) ----------
   6px tall track, brand fill, color shifts to warning/error as
   spend approaches/crosses target. Existing .progress-bar markup
   gets re-tuned under Notion. */
:root[data-theme="notion"] .progress-bar,
:root[data-theme="notion-dark"] .progress-bar {
  height: 6px;
  background: rgba(0, 0, 0, 0.06);
  border-radius: 9999px;
  overflow: hidden;
}
:root[data-theme="notion-dark"] .progress-bar {
  background: rgba(255, 255, 255, 0.08);
}
:root[data-theme="notion"] .progress-bar__fill,
:root[data-theme="notion-dark"] .progress-bar__fill {
  height: 100%;
  background: var(--color-brand);
  border-radius: 9999px;
  transition: width var(--duration-base) var(--ease-standard);
}
:root[data-theme="notion"] .progress-bar.is-warning .progress-bar__fill,
:root[data-theme="notion-dark"] .progress-bar.is-warning .progress-bar__fill {
  background: var(--color-warning);
}
:root[data-theme="notion"] .progress-bar.is-over .progress-bar__fill,
:root[data-theme="notion-dark"] .progress-bar.is-over .progress-bar__fill {
  background: var(--color-error);
}

/* ---------- Notion: Upload Receipt drop zone (spec §11) -----
   16px radius, 2px dashed border, warm-white bg, icon + prompt
   centered. Existing .drop-zone markup picks this up. */
:root[data-theme="notion"] .drop-zone,
:root[data-theme="notion-dark"] .drop-zone {
  background: var(--color-warm-paper);
  border: 2px dashed #dddddd;
  border-radius: var(--radius-xl);
  padding: 48px 24px;
  text-align: center;
  transition:
    background-color var(--duration-fast) var(--ease-standard),
    border-color var(--duration-fast) var(--ease-standard);
}
:root[data-theme="notion-dark"] .drop-zone {
  border-color: var(--color-border-strong);
}
:root[data-theme="notion"] .drop-zone:hover,
:root[data-theme="notion"] .drop-zone.is-dragover,
:root[data-theme="notion-dark"] .drop-zone:hover,
:root[data-theme="notion-dark"] .drop-zone.is-dragover {
  background: var(--color-brand-soft);
  border-color: var(--color-brand);
}
:root[data-theme="notion"] .drop-zone.is-invalid,
:root[data-theme="notion-dark"] .drop-zone.is-invalid {
  background: var(--color-error-soft);
  border-color: var(--color-error);
}

/* ---------- Notion: Intent picker pills (spec §11 Upload) ----
   4 pills: Auto / Grocery / Restaurant / General Expense.
   9999px radius, selected = brand fill + white text. */
:root[data-theme="notion"] .intent-picker,
:root[data-theme="notion-dark"] .intent-picker {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  margin-bottom: 16px;
}
:root[data-theme="notion"] .intent-pill,
:root[data-theme="notion-dark"] .intent-pill {
  padding: 8px 16px;
  border-radius: 9999px;
  border: 1px solid var(--color-border);
  background: var(--color-surface);
  color: var(--color-text-primary);
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  transition:
    background-color var(--duration-fast) var(--ease-standard),
    color var(--duration-fast) var(--ease-standard),
    border-color var(--duration-fast) var(--ease-standard);
}
:root[data-theme="notion"] .intent-pill:hover {
  background: rgba(0, 0, 0, 0.04);
}
:root[data-theme="notion-dark"] .intent-pill:hover {
  background: rgba(255, 255, 255, 0.05);
}
:root[data-theme="notion"] .intent-pill.is-selected,
:root[data-theme="notion-dark"] .intent-pill.is-selected {
  background: var(--color-brand);
  color: var(--color-brand-contrast);
  border-color: var(--color-brand);
}

/* ---------- Notion: Trusted device card (spec §11 Settings) -
   12px radius, whisper border, warm-white interior, scope badges
   on the right, ghost actions in the footer. The codebase already
   uses .device-card or .trusted-device-card patterns; this re-tunes
   under Notion. */
:root[data-theme="notion"] .device-card,
:root[data-theme="notion-dark"] .device-card,
:root[data-theme="notion"] .trusted-device-card,
:root[data-theme="notion-dark"] .trusted-device-card {
  background: var(--color-warm-paper);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: 16px;
  display: flex;
  align-items: center;
  gap: 12px;
}
:root[data-theme="notion"] .device-card .device-card__actions,
:root[data-theme="notion-dark"] .device-card .device-card__actions,
:root[data-theme="notion"] .trusted-device-card .trusted-device-card__actions,
:root[data-theme="notion-dark"] .trusted-device-card .trusted-device-card__actions {
  margin-left: auto;
  display: flex;
  gap: 6px;
}

/* ===================================================================
 * Inventory — domain grouping layout
 * Default Inventory view groups items by domain (Grocery / Household
 * / Personal Care / Apparel / Other) with a pinned "Running Low"
 * section at the top. Items inside each section are already sorted
 * by (domain, last_purchase_date desc, name) in the JS layer.
 * =================================================================== */
.inventory-mobile-list--grouped {
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.inventory-domain-section {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.inventory-domain-section.is-collapsed .inventory-domain-body {
  display: none;
}
.inventory-domain-header {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 14px 16px;
  background: var(--color-surface-2, rgba(0, 0, 0, 0.04));
  border: 1px solid var(--color-border, rgba(0, 0, 0, 0.12));
  border-radius: 14px;
  cursor: pointer;
  font: inherit;
  color: var(--color-text-primary, inherit);
  text-align: left;
  box-shadow: 0 1px 0 rgba(0, 0, 0, 0.04);
}
.inventory-domain-header:hover {
  background: var(--color-surface-3, rgba(0, 0, 0, 0.06));
}
.inventory-domain-section--low .inventory-domain-header {
  background: rgba(228, 77, 66, 0.14);
  border-color: rgba(228, 77, 66, 0.32);
  color: var(--color-error, #c4002b);
}
.inventory-domain-icon {
  font-size: 1.25rem;
  line-height: 1;
  flex: 0 0 auto;
}
.inventory-domain-title {
  font-weight: 800;
  font-size: 1.1rem;
  letter-spacing: -0.25px;
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.inventory-domain-count {
  flex: 0 0 auto;
  padding: 3px 10px;
  border-radius: 9999px;
  background: var(--color-surface, rgba(255, 255, 255, 0.6));
  border: 1px solid var(--color-border, rgba(0, 0, 0, 0.12));
  font-size: 0.82rem;
  font-weight: 700;
  color: var(--color-text-secondary, inherit);
  font-variant-numeric: tabular-nums;
  line-height: 1.2;
}
.inventory-domain-chevron {
  flex: 0 0 auto;
  color: var(--color-text-muted, var(--muted, #888));
  font-size: 1rem;
  min-width: 14px;
  text-align: center;
}
.inventory-domain-body {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 12px 14px 14px;
  margin-top: 2px;
  background: var(--inv-domain-tint, rgba(0, 0, 0, 0.025));
  border-left: 3px solid var(--inv-domain-accent, var(--color-border, rgba(0, 0, 0, 0.12)));
  border-radius: 0 12px 12px 0;
}

/* Domain-specific accent colors — visible differentiator between
   sections even when all are expanded. Variables are consumed by
   .inventory-domain-body via --inv-domain-accent / --inv-domain-tint. */
.inventory-domain-section[data-domain="__low__"] {
  --inv-domain-accent: rgba(228, 77, 66, 0.55);
  --inv-domain-tint: rgba(228, 77, 66, 0.06);
}
.inventory-domain-section[data-domain="grocery"] {
  --inv-domain-accent: rgba(26, 174, 57, 0.55);
  --inv-domain-tint: rgba(26, 174, 57, 0.05);
}
.inventory-domain-section[data-domain="household"] {
  --inv-domain-accent: rgba(9, 127, 232, 0.50);
  --inv-domain-tint: rgba(9, 127, 232, 0.05);
}
.inventory-domain-section[data-domain="personal_care"] {
  --inv-domain-accent: rgba(160, 33, 110, 0.55);
  --inv-domain-tint: rgba(160, 33, 110, 0.05);
}
.inventory-domain-section[data-domain="apparel"] {
  --inv-domain-accent: rgba(221, 91, 0, 0.55);
  --inv-domain-tint: rgba(221, 91, 0, 0.05);
}
.inventory-domain-section[data-domain="other"] {
  --inv-domain-accent: rgba(128, 128, 128, 0.45);
  --inv-domain-tint: rgba(128, 128, 128, 0.05);
}

/* Dark themes need slightly stronger tint to be visible on black. */
:root[data-theme="dark"] .inventory-domain-body,
:root[data-theme="clay-dark"] .inventory-domain-body,
:root[data-theme="notion-dark"] .inventory-domain-body {
  background: color-mix(in srgb, var(--inv-domain-accent, rgba(255, 255, 255, 0.08)) 14%, transparent);
}

/* Clay: louder section headers matching ink-bordered tile language. */
:root[data-theme="clay"] .inventory-domain-header,
:root[data-theme="clay-dark"] .inventory-domain-header {
  border: var(--stroke-2) solid var(--color-border-strong);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-1);
  background: var(--color-surface-2);
}
:root[data-theme="clay"] .inventory-domain-section--low .inventory-domain-header,
:root[data-theme="clay-dark"] .inventory-domain-section--low .inventory-domain-header {
  background: var(--color-swatch-pomegranate-soft, rgba(232, 93, 106, 0.14));
  border-color: var(--color-swatch-pomegranate, #e85d6a);
  color: var(--color-swatch-pomegranate, #e85d6a);
}

/* Notion: paper-calm headers — warm whisper with muted chevron. */
:root[data-theme="notion"] .inventory-domain-header,
:root[data-theme="notion-dark"] .inventory-domain-header {
  background: var(--color-warm-paper, #f6f5f4);
  border-color: var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-1);
}
:root[data-theme="notion"] .inventory-domain-section--low .inventory-domain-header,
:root[data-theme="notion-dark"] .inventory-domain-section--low .inventory-domain-header {
  background: #fdf2f4;
  border-color: #f0c4cc;
  color: #c4002b;
}

/* ---------- Inventory: category subsections inside domain --- */
/* Category sections sit inside an expanded domain. Visually subordinate
   to domain headers (smaller type, lighter weight) but substantial
   enough to read as real section headers, not captions. */
.inventory-category-section {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 6px;
}
.inventory-category-section.is-collapsed .inventory-category-body {
  display: none;
}
.inventory-category-header {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  background: var(--color-surface-2, rgba(0, 0, 0, 0.03));
  border: 1px solid var(--color-border, rgba(0, 0, 0, 0.10));
  border-radius: 10px;
  cursor: pointer;
  font: inherit;
  color: var(--color-text-primary, inherit);
  text-align: left;
}
.inventory-category-header:hover {
  background: var(--color-surface-3, rgba(0, 0, 0, 0.06));
}
.inventory-category-title {
  font-size: 0.95rem;
  font-weight: 700;
  letter-spacing: -0.125px;
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.inventory-category-count {
  flex: 0 0 auto;
  padding: 2px 8px;
  border-radius: 9999px;
  background: var(--color-surface, rgba(255, 255, 255, 0.6));
  border: 1px solid var(--color-border, rgba(0, 0, 0, 0.10));
  font-size: 0.78rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--color-text-secondary, var(--muted, #615d59));
}
.inventory-category-chevron {
  flex: 0 0 auto;
  font-size: 0.9rem;
  color: var(--color-text-muted, var(--muted, #888));
  min-width: 14px;
  text-align: center;
}
.inventory-category-body {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding-left: 8px;
}

/* Clay: category headers pick up the theme's hard-edged chip accent. */
:root[data-theme="clay"] .inventory-category-header,
:root[data-theme="clay-dark"] .inventory-category-header {
  border: var(--stroke-2) solid var(--color-border-strong);
  border-radius: var(--radius-sm);
}

/* Notion: warm-paper tint + whisper border. */
:root[data-theme="notion"] .inventory-category-header,
:root[data-theme="notion-dark"] .inventory-category-header {
  background: var(--color-warm-paper, #f6f5f4);
  border-color: var(--color-border);
  border-radius: var(--radius-md);
}
:root[data-theme="notion"] .inventory-category-header:hover,
:root[data-theme="notion-dark"] .inventory-category-header:hover {
  background: var(--color-surface-3, var(--color-warm-paper));
}

/* ---------- Shopping: "Identify from Photo" row --------------
   Sits at the top of the manual-add form. The camera button sits
   on the left; the in-flight status and the captured preview
   thumbnail appear inline to its right. */
.shop-identify-row {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 14px;
  padding: 10px 12px;
  background: var(--color-surface-2, rgba(0, 0, 0, 0.03));
  border: 1px dashed var(--color-border, rgba(0, 0, 0, 0.15));
  border-radius: var(--radius-md, 10px);
}
.shop-identify-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex: 0 0 auto;
}
.shop-identify-btn__icon {
  font-size: 1.05rem;
}
.shop-identify-btn[disabled] {
  opacity: 0.6;
  cursor: progress;
}
.shop-identify-status {
  flex: 1 1 auto;
  min-width: 0;
  font-size: 0.85rem;
  color: var(--color-text-secondary, var(--muted, #666));
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.shop-identify-preview {
  flex: 0 0 auto;
  width: 44px;
  height: 44px;
  object-fit: cover;
  border-radius: 6px;
  border: 1px solid var(--color-border, rgba(0, 0, 0, 0.1));
}

/* ---------- Receipt attribution badges + pickers ------------ */
.attr-badge {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 1px 6px;
  border-radius: 9999px;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  vertical-align: middle;
  margin-left: 6px;
  white-space: nowrap;
}
.attr-badge--household {
  background: rgba(9, 127, 232, 0.12);
  color: #097fe8;
  border: 1px solid rgba(9, 127, 232, 0.28);
}
.attr-badge--personal {
  background: rgba(160, 33, 110, 0.12);
  color: #a0216e;
  border: 1px solid rgba(160, 33, 110, 0.28);
}
.receipt-item-attribution {
  min-width: 150px;
  font-size: 0.82rem;
}
.receipt-editor-main-field.field-attribution label {
  font-weight: 700;
}

/* ---------- Receipt attribution filter chips ---------------- */
.receipt-attribution-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.receipt-attribution-chip {
  padding: 4px 10px;
  border-radius: 9999px;
  border: 1px solid var(--color-border, rgba(0, 0, 0, 0.15));
  background: transparent;
  color: var(--color-text-primary, inherit);
  font-size: 0.82rem;
  font-weight: 600;
  cursor: pointer;
  transition: background-color 120ms ease, border-color 120ms ease;
}
.receipt-attribution-chip:hover {
  background: rgba(0, 0, 0, 0.04);
}
.receipt-attribution-chip.active {
  background: rgba(9, 127, 232, 0.14);
  border-color: #097fe8;
  color: #097fe8;
}

/* ---------- Dashboard: Spend-by-person card ----------------- */
.dash-spend-by-person {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.spend-person-row {
  display: grid;
  grid-template-columns: minmax(0, 1.2fr) minmax(60px, 2fr) auto;
  gap: 10px;
  align-items: center;
  font-size: 0.9rem;
}
.spend-person-row__label {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.spend-person-row__bar {
  background: rgba(0, 0, 0, 0.06);
  border-radius: 9999px;
  height: 8px;
  overflow: hidden;
  min-width: 40px;
}
/* Narrow viewports: stack label+value on one line, bar full-width below. */
@media (max-width: 720px) {
  #dash-spend-by-person-card {
    grid-column: 1 / -1;
  }
  .spend-person-row {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas:
      "label value"
      "bar   bar";
    gap: 2px 8px;
  }
  .spend-person-row__label {
    grid-area: label;
  }
  .spend-person-row__value {
    grid-area: value;
  }
  .spend-person-row__bar {
    grid-area: bar;
    height: 6px;
    margin-top: 2px;
  }
}
.spend-person-row__fill {
  height: 100%;
  background: #097fe8;
  border-radius: 9999px;
  transition: width 180ms ease-out;
}
.spend-person-row--household .spend-person-row__fill {
  background: #2a9d99;
}
.spend-person-row--unset .spend-person-row__fill {
  background: rgba(128, 128, 128, 0.55);
}
.spend-person-row__value {
  font-weight: 700;
  font-variant-numeric: tabular-nums lining-nums;
  white-space: nowrap;
}

/* When collapsed, hide the month navigator so only the title remains —
   a single compact row instead of "title + month + empty body". Also
   balance vertical padding so the title sits centered, not jammed to
   the top by the original card padding. */
#dash-spend-by-person-card.dashboard-collapsed .spend-by-person-monthnav {
  display: none;
}
#dash-spend-by-person-card.dashboard-collapsed .card-header {
  margin-bottom: 0;
}
#dash-spend-by-person-card.dashboard-collapsed {
  padding-top: 14px;
  padding-bottom: 14px;
}
/* Match the title weight (700) the Shopping List tile uses so all four
   dashboard tiles read at the same visual density. */
#dash-low-stock-card .card-title,
#dash-recs-card .card-title,
#dash-spend-by-person-card .card-title {
  font-weight: 700;
}

/* ---------- Settings locked-down view ---------------------- */
/* Applied to #page-settings when the user hasn't been granted Settings
   in allowed_pages. Keeps Settings reachable as an escape hatch for
   Sign Out + identity summary, hides the rest of the surface. */
#page-settings.settings-locked .card:not(#settings-session-card) {
  display: none !important;
}
/* Inside the Session card, hide everything that isn't the identity
   summary or the Sign Out button. Avatar editor, "Details" expand,
   password controls, etc. all disappear. */
#page-settings.settings-locked #settings-session-card #session-avatar-wrap,
#page-settings.settings-locked #settings-session-card #session-details-wrap,
#page-settings.settings-locked #settings-session-card .btn[onclick*="toggleSessionAvatar"],
#page-settings.settings-locked #settings-session-card .btn[onclick*="toggleSessionDetails"] {
  display: none !important;
}

/* ---------- Dashboard: Spending by Category + Inventory row --- */
/* Force the inventory row to span a single full-width column; the
   mobile media query at index.html:9368 pins .dashboard-stats-grid
   to 2 columns which was squishing us on both desktop + mobile. */
#page-dashboard > .dashboard-stats-grid.dashboard-inventory-row,
.dashboard-stats-grid.dashboard-inventory-row {
  grid-template-columns: minmax(0, 1fr) !important;
}
.dashboard-spending-row {
  margin-bottom: 20px;
}
.dashboard-spending-row .card-header-inline-stat {
  cursor: default;
  background: transparent;
  border: 0;
  color: var(--color-text-primary, inherit);
  font-size: 0.95rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  padding: 0;
}
/* Horizontal bars, one row per category. Each row has a full-width
   100% track; the colored fill width = that category's share of the
   top (biggest) category. Labels + amount + delta live on the same
   row so nothing overlaps — unlike the column version whose narrow
   cells crushed mobile labels together. */
.spending-by-category {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 4px 2px 0;
}
.spending-row {
  display: grid;
  grid-template-columns: minmax(130px, 1.1fr) minmax(0, 2fr) minmax(92px, auto);
  gap: 12px;
  align-items: center;
}
.spending-row__label {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  font-weight: 600;
  font-size: 0.92rem;
}
.spending-row__icon { font-size: 1.05rem; }
.spending-row__name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.spending-row__bar {
  position: relative;
  height: 14px;
  border-radius: 999px;
  background: var(--color-surface-2, rgba(127, 127, 127, 0.12));
  overflow: hidden;
}
.spending-row__fill {
  position: absolute;
  inset: 0;
  border-radius: 999px;
  transform-origin: left;
  transition: width 360ms cubic-bezier(0.22, 1, 0.36, 1);
  min-width: 4px;
}
.spending-row__pct {
  position: absolute;
  top: 50%;
  right: 8px;
  transform: translateY(-50%);
  font-size: 0.7rem;
  font-weight: 700;
  color: rgba(255, 255, 255, 0.95);
  font-variant-numeric: tabular-nums;
  line-height: 1;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
  pointer-events: none;
}
.spending-row__amount {
  text-align: right;
  font-variant-numeric: tabular-nums;
  line-height: 1.2;
  white-space: nowrap;
}
.spending-row__amount-value {
  font-weight: 800;
  font-size: 0.95rem;
}
.spending-row__amount-delta {
  display: block;
  font-size: 0.72rem;
  font-weight: 600;
  color: var(--muted);
  margin-top: 2px;
}
.spending-row__amount-delta--good { color: #2fa36b; }
.spending-row__amount-delta--bad { color: #e0803a; }

/* Per-row palette — blue → teal → green → amber → rose → violet. */
.spending-row--c0 .spending-row__fill { background: linear-gradient(90deg, #4aa3ff 0%, #097fe8 100%); }
.spending-row--c1 .spending-row__fill { background: linear-gradient(90deg, #3ec1bd 0%, #149890 100%); }
.spending-row--c2 .spending-row__fill { background: linear-gradient(90deg, #5bd3a0 0%, #2fa36b 100%); }
.spending-row--c3 .spending-row__fill { background: linear-gradient(90deg, #f5c36b 0%, #e0a134 100%); }
.spending-row--c4 .spending-row__fill { background: linear-gradient(90deg, #f28a8a 0%, #c94d4d 100%); }
.spending-row--c5 .spending-row__fill { background: linear-gradient(90deg, #b590e8 0%, #7d52c9 100%); }

/* Collapsed state — single compact row with title left, amount right.
   No body padding, no header bottom margin so the card reads as a tight
   one-line summary instead of an empty box. */
.dashboard-spending-row.is-collapsed {
  padding-top: 14px;
  padding-bottom: 14px;
  margin-bottom: 14px;
}
.dashboard-spending-row.is-collapsed .card-header {
  margin-bottom: 0;
}
.dashboard-spending-row.is-collapsed .card-header-inline-stat {
  font-size: 1.05rem;
  font-weight: 800;
}

@media (max-width: 640px) {
  .spending-row {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas:
      "label  amount"
      "bar    bar";
    row-gap: 3px;
    column-gap: 10px;
  }
  .spending-row__label  { grid-area: label; }
  .spending-row__amount { grid-area: amount; }
  .spending-row__bar    { grid-area: bar; height: 10px; }
  .spending-row__pct    { font-size: 0.65rem; right: 6px; }
}

/* ---------- Settings — collapsible cards -------------------- */
#page-settings .settings-card {
  margin-bottom: 8px;
  transition: border-color 140ms ease, background-color 140ms ease;
}
#page-settings .settings-card .card-header {
  user-select: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 10px 14px;
  margin: -16px;          /* pull edges to card boundary so the whole bar is hot */
  margin-bottom: 14px;
  border-radius: 14px 14px 0 0;
  transition: background-color 140ms ease;
}
#page-settings .settings-card .card-header:hover {
  background: color-mix(in srgb, var(--color-brand) 5%, transparent);
}
#page-settings .settings-card .card-header .card-title {
  font-size: 0.95rem;
  font-weight: 700;
  letter-spacing: 0.005em;
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
#page-settings .settings-card__chevron {
  font-size: 0.85rem;
  color: var(--muted);
  flex: 0 0 auto;
  margin-left: auto;
  width: 18px;
  text-align: center;
  transition: transform 180ms ease, color 140ms ease;
}
#page-settings .settings-card:not(.settings-card--collapsed) .settings-card__chevron {
  color: var(--text);
}
/* When collapsed, hide every header child EXCEPT the title and the
   chevron — keeps inline action buttons (Add User, Pair Device, etc.)
   from cluttering the collapsed bar. */
#page-settings .settings-card.settings-card--collapsed .card-header > *:not(.card-title):not(.settings-card__chevron) {
  display: none !important;
}
#page-settings .settings-card.settings-card--collapsed > *:not(.card-header) {
  display: none !important;
}
#page-settings .settings-card.settings-card--collapsed {
  padding: 0;
  background: transparent;
}
#page-settings .settings-card.settings-card--collapsed .card-header {
  margin: 0;
  border-radius: 14px;
  border: 1px solid var(--border);
  background: var(--color-surface-1, rgba(255, 255, 255, 0.02));
}
#page-settings .settings-card.settings-card--collapsed .card-header:hover {
  background: color-mix(in srgb, var(--color-brand) 5%, transparent);
}

/* ---------- In-App Assistant -------------------------------- */
.chat-fab {
  position: fixed;
  right: 18px;
  bottom: 18px;
  z-index: 950;
  width: 52px;
  height: 52px;
  border-radius: 50%;
  border: 1px solid var(--border);
  background: var(--color-brand, #4aa3ff);
  color: #fff;
  font-size: 1.5rem;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.28);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: transform 140ms ease, box-shadow 140ms ease;
}
.chat-fab:hover {
  transform: translateY(-2px);
  box-shadow: 0 10px 22px rgba(0, 0, 0, 0.32);
}
.chat-fab[hidden] { display: none; }

.chat-panel {
  position: fixed;
  right: 16px;
  bottom: 16px;
  width: min(420px, calc(100vw - 32px));
  height: min(640px, calc(100vh - 80px));
  min-width: 320px;
  min-height: 240px;
  max-width: calc(100vw - 16px);
  max-height: calc(100vh - 16px);
  z-index: 951;
  background: var(--color-surface-1, #181a1f);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 16px;
  box-shadow: 0 18px 44px rgba(0, 0, 0, 0.45);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  transition: height 180ms ease, box-shadow 140ms ease;
}
.chat-panel__resize-handle {
  position: absolute;
  right: 4px;
  bottom: 4px;
  width: 16px;
  height: 16px;
  cursor: nwse-resize;
  z-index: 2;
  display: flex;
  align-items: flex-end;
  justify-content: flex-end;
  color: var(--muted);
  opacity: 0.55;
  transition: opacity 120ms ease;
  user-select: none;
  touch-action: none;
}
.chat-panel__resize-handle:hover { opacity: 1; }
.chat-panel__resize-handle::before {
  content: "";
  display: block;
  width: 10px;
  height: 10px;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  border-bottom-right-radius: 4px;
}
.chat-panel.is-minimized .chat-panel__resize-handle { display: none; }
.chat-panel[hidden] { display: none; }

.chat-panel.is-dragging {
  user-select: none;
  box-shadow: 0 24px 56px rgba(0, 0, 0, 0.55);
  transition: none;
}

.chat-panel.is-minimized {
  height: 56px !important;
  resize: none;
}
.chat-panel.is-minimized .chat-panel__body,
.chat-panel.is-minimized .chat-panel__form {
  display: none !important;
}

.chat-panel__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 12px 14px;
  border-bottom: 1px solid var(--border);
  background: color-mix(in srgb, var(--color-brand) 6%, transparent);
  cursor: move;
  user-select: none;
  touch-action: none;
}
.chat-panel.is-minimized .chat-panel__head {
  border-bottom: none;
}
.chat-panel__title-wrap {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
}
.chat-panel__avatar {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--color-brand) 22%, transparent);
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.chat-panel__title {
  font-weight: 800;
  font-size: 0.95rem;
}
.chat-panel__subtitle {
  font-size: 0.75rem;
  color: var(--muted);
}
.chat-panel__head-actions {
  display: inline-flex;
  gap: 4px;
}

.chat-panel__body {
  flex: 1 1 auto;
  overflow-y: auto;
  padding: 12px 14px;
  background: var(--color-surface-2, rgba(255, 255, 255, 0.02));
}

.chat-panel__form {
  border-top: 1px solid var(--border);
  padding: 10px 12px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  background: var(--color-surface-1, #181a1f);
}
.chat-panel__input {
  width: 100%;
  resize: none;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--color-surface-2, rgba(255, 255, 255, 0.04));
  color: var(--text);
  padding: 8px 10px;
  font: inherit;
  font-size: 0.9rem;
  min-height: 56px;
  max-height: 140px;
}
.chat-panel__input:focus {
  outline: 2px solid color-mix(in srgb, var(--color-brand) 35%, transparent);
  outline-offset: 0;
}
.chat-panel__form-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
.chat-panel__hint {
  font-size: 0.72rem;
  color: var(--muted);
}

.chat-thread {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.chat-thread--empty {
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.chat-thread__welcome {
  font-size: 0.86rem;
  color: var(--muted);
}
.chat-thread__suggestions {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.chat-suggestion {
  appearance: none;
  border: 1px dashed var(--border);
  background: transparent;
  color: var(--text);
  text-align: left;
  padding: 8px 10px;
  border-radius: 10px;
  cursor: pointer;
  font-size: 0.85rem;
  transition: background-color 140ms ease, border-color 140ms ease;
}
.chat-suggestion:hover {
  background: color-mix(in srgb, var(--color-brand) 8%, transparent);
  border-color: color-mix(in srgb, var(--color-brand) 35%, transparent);
}

.chat-msg {
  display: flex;
  flex-direction: column;
  gap: 4px;
  max-width: 90%;
}
.chat-msg--user {
  align-self: flex-end;
  align-items: flex-end;
}
.chat-msg--assistant {
  align-self: flex-start;
  align-items: flex-start;
}
.chat-msg__bubble {
  padding: 8px 12px;
  border-radius: 12px;
  font-size: 0.88rem;
  line-height: 1.45;
  word-wrap: break-word;
}
.chat-msg__bubble .chat-p {
  margin: 0 0 6px;
}
.chat-msg__bubble .chat-p:last-child {
  margin-bottom: 0;
}
.chat-msg__bubble .chat-h {
  margin: 4px 0 4px;
  font-size: 0.92rem;
  font-weight: 800;
}
.chat-msg__bubble .chat-list {
  margin: 4px 0 6px;
  padding-left: 18px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  font-variant-numeric: tabular-nums;
}
.chat-msg__bubble .chat-list:last-child {
  margin-bottom: 0;
}
.chat-msg__bubble .chat-list li::marker {
  color: var(--muted);
}
.chat-msg__bubble code {
  background: color-mix(in srgb, var(--text) 10%, transparent);
  padding: 0 4px;
  border-radius: 4px;
  font-size: 0.82rem;
}
.chat-msg--user .chat-msg__bubble {
  background: color-mix(in srgb, var(--color-brand) 26%, transparent);
  border: 1px solid color-mix(in srgb, var(--color-brand) 38%, transparent);
}
.chat-msg--assistant .chat-msg__bubble {
  background: var(--color-surface-1, rgba(255, 255, 255, 0.03));
  border: 1px solid var(--border);
}
.chat-msg--flagged .chat-msg__bubble {
  border-color: color-mix(in srgb, #e0803a 50%, var(--border));
  background: color-mix(in srgb, #e0803a 8%, transparent);
}
.chat-msg__trace {
  font-size: 0.72rem;
  color: var(--muted);
}
.chat-msg--flagged .chat-msg__trace {
  color: #e0803a;
  font-weight: 700;
}
.chat-msg__dots {
  display: inline-flex;
  gap: 4px;
}
.chat-msg__dots span {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--muted);
  animation: chat-dot 1.1s infinite ease-in-out;
}
.chat-msg__dots span:nth-child(2) { animation-delay: 0.18s; }
.chat-msg__dots span:nth-child(3) { animation-delay: 0.36s; }
@keyframes chat-dot {
  0%, 80%, 100% { opacity: 0.3; transform: translateY(0); }
  40%           { opacity: 1;   transform: translateY(-2px); }
}

.chat-demo {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.chat-demo__lead {
  font-size: 0.86rem;
  color: var(--text);
  background: color-mix(in srgb, var(--color-brand) 8%, transparent);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 10px 12px;
}
.chat-demo__section-title {
  font-size: 0.72rem;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
  margin-top: 6px;
}
.chat-demo__caps {
  margin: 0;
  padding-left: 18px;
  font-size: 0.86rem;
  display: flex;
  flex-direction: column;
  gap: 3px;
}
.chat-demo-card {
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 10px 12px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  background: var(--color-surface-1, rgba(255, 255, 255, 0.02));
}
.chat-demo-card__role {
  display: block;
  font-size: 0.66rem;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--muted);
  margin-bottom: 2px;
}
.chat-demo-card__q {
  font-size: 0.86rem;
}
.chat-demo-card__a {
  font-size: 0.85rem;
  background: color-mix(in srgb, var(--color-brand) 5%, transparent);
  border-radius: 8px;
  padding: 8px 10px;
}
.chat-demo__footer {
  font-size: 0.78rem;
  color: var(--muted);
  text-align: center;
  margin-top: 4px;
}

@media (max-width: 480px) {
  .chat-panel {
    right: 8px;
    bottom: 8px;
    left: 8px;
    width: auto;
    height: 70vh;
  }
  .chat-fab {
    right: 12px;
    bottom: 12px;
  }
}

/* ---------- Spending row drill-down ------------------------- */
.spending-row-wrap {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
button.spending-row {
  appearance: none;
  border: none;
  padding: 8px 6px;
  background: transparent;
  color: inherit;
  text-align: left;
  width: 100%;
  border-radius: 10px;
  cursor: pointer;
  transition: background-color 140ms ease;
  font: inherit;
}
button.spending-row:hover {
  background: color-mix(in srgb, var(--color-brand) 6%, transparent);
}
.spending-row-wrap.is-open > button.spending-row {
  background: color-mix(in srgb, var(--color-brand) 9%, transparent);
}
.spending-row__chevron {
  display: inline-block;
  width: 12px;
  font-size: 0.78rem;
  color: var(--muted);
  transition: transform 140ms ease;
  flex: 0 0 auto;
}
.spending-row-wrap.is-open .spending-row__chevron {
  color: var(--text);
}
.spending-row__drill {
  margin: 0 6px 6px;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: 12px;
  background: color-mix(in srgb, var(--color-brand) 4%, transparent);
}
.spending-row__drill[hidden] { display: none; }
.spending-drill__header {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  font-size: 0.78rem;
  color: var(--muted);
  margin-bottom: 8px;
  font-variant-numeric: tabular-nums;
}
.spending-drill__header span:last-child {
  font-weight: 800;
  color: var(--text);
  font-size: 0.92rem;
}
.spending-drill__list {
  display: flex;
  flex-direction: column;
  gap: 2px;
  max-height: 320px;
  overflow-y: auto;
}
.spending-drill__row {
  appearance: none;
  border: none;
  background: transparent;
  color: inherit;
  font: inherit;
  display: grid;
  grid-template-columns: 70px 1fr auto;
  gap: 10px;
  align-items: center;
  padding: 6px 8px;
  border-radius: 8px;
  cursor: pointer;
  text-align: left;
  font-variant-numeric: tabular-nums;
}
.spending-drill__row:hover {
  background: color-mix(in srgb, var(--color-brand) 10%, transparent);
}
.spending-drill__date {
  color: var(--muted);
  font-size: 0.78rem;
  white-space: nowrap;
}
.spending-drill__store {
  font-size: 0.86rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.spending-drill__amount {
  font-weight: 700;
  font-size: 0.86rem;
}
.spending-drill__row.is-refund .spending-drill__amount {
  color: #2fa36b;
}
.spending-drill__loading,
.spending-drill__empty,
.spending-drill__error,
.spending-drill__truncated {
  font-size: 0.8rem;
  color: var(--muted);
  padding: 6px 4px;
}
.spending-drill__error { color: #e0803a; }

/* ---------- Floor obligations drill (inside Spending by Category) --- */
.spending-row--floor .spending-row__fill {
  background: linear-gradient(90deg, #7b8cde 0%, #4f63c8 100%);
}
.floor-drill-row {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 10px;
  align-items: center;
  padding: 6px 2px;
  font-size: 0.83rem;
}
.floor-drill-row + .floor-drill-row {
  border-top: 1px solid var(--border);
}
.floor-drill-main {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}
.floor-drill-label {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.floor-drill-bar-wrap {
  height: 5px;
  background: var(--border, #333);
  border-radius: 3px;
  overflow: hidden;
}
.floor-drill-fill {
  height: 100%;
  border-radius: 3px;
  background: var(--color-brand, #4f63c8);
}
.floor-drill-fill--paid { background: #2fa36b; }
.floor-drill-fill--over { background: #e0a134; }
.floor-drill-amounts {
  text-align: right;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
  font-size: 0.8rem;
  color: var(--muted);
}
.floor-drill-paid {
  font-weight: 700;
  color: var(--text);
}

/* ---------- Spending Flow (Sankey-style) -------------------- */
.spending-flow {
  width: 100%;
}
.spending-flow svg {
  width: 100%;
  height: auto;
  display: block;
}
.spending-flow__source-label {
  fill: var(--color-text-primary, #fff);
  font-size: 12px;
  font-weight: 700;
  font-family: inherit;
}
.spending-flow__source-sub {
  fill: var(--muted, #888);
  font-size: 10px;
  font-weight: 600;
  font-family: inherit;
}
.spending-flow__target-label {
  fill: var(--color-text-primary, #fff);
  font-size: 12px;
  font-weight: 600;
  font-family: inherit;
}
.spending-flow__target-value {
  fill: var(--color-text-primary, #fff);
  font-size: 12px;
  font-weight: 800;
  font-family: inherit;
  font-variant-numeric: tabular-nums;
}
.spending-flow__target-sub {
  fill: var(--muted, #888);
  font-size: 10px;
  font-weight: 600;
  font-family: inherit;
}
.spending-flow__ribbon {
  fill-opacity: 0.55;
  transition: fill-opacity 160ms ease;
}
.spending-flow__ribbon:hover {
  fill-opacity: 0.85;
}
.spending-flow__source-bar {
  fill: #4aa3ff;
}
.spending-flow__node {
  stroke: var(--color-surface, #1f2024);
  stroke-width: 1;
}
@media (max-width: 640px) {
  .spending-flow__source-label { font-size: 10px; }
  .spending-flow__source-sub { font-size: 9px; }
  .spending-flow__target-label { font-size: 10px; }
  .spending-flow__target-value { font-size: 10px; }
  .spending-flow__target-sub { font-size: 9px; }
}

/* ---------- Receipts bulk-select ---------------------------- */
.receipt-bulk-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  padding: 10px 12px;
  border-radius: 10px;
  background: var(--color-surface-2, rgba(74, 163, 255, 0.1));
  border: 1px solid var(--color-border, rgba(74, 163, 255, 0.3));
}
.receipt-bulk-bar__count {
  font-weight: 700;
  color: #4aa3ff;
  font-size: 0.88rem;
  margin-right: 4px;
}
.receipt-bulk-bar select {
  min-width: 140px;
}
.result-card__select {
  display: flex;
  align-items: center;
  padding: 0 2px 0 8px;
}
.result-card__select input[type="checkbox"] {
  width: 18px;
  height: 18px;
  accent-color: #4aa3ff;
  cursor: pointer;
}
.result-card.card--bulk-checked {
  outline: 2px solid #4aa3ff;
  outline-offset: -2px;
}
@media (max-width: 640px) {
  .receipt-bulk-bar {
    padding: 8px 10px;
    gap: 6px;
  }
  .receipt-bulk-bar select {
    min-width: 0;
    flex: 1 1 100px;
  }
  .receipt-bulk-bar .btn { flex: 0 0 auto; }
}

/* ---------- Sortable table headers (receipts month table) --- */
.sortable-receipts-table th.sortable-receipts-th {
  transition: color 120ms ease, background-color 120ms ease;
}
.sortable-receipts-table th.sortable-receipts-th:hover {
  color: var(--color-brand, #097fe8);
  background: var(--color-surface-2, rgba(127, 127, 127, 0.08));
}
.sortable-receipts-table th.sortable-receipts-th.is-active {
  color: var(--color-brand, #097fe8);
}

/* ---------- Sidebar: restricted (non-granted) nav items ---- */
/* User-facing signal that the page exists but isn't included in this
   user's allowed_pages. Item stays in the sidebar so the user has a
   mental model of the whole app, but is dimmed and non-clickable. */
.nav-item.nav-item--restricted {
  opacity: 0.32;
  pointer-events: none;
  filter: saturate(0.4);
  cursor: not-allowed;
}
.nav-item.nav-item--restricted .nav-icon {
  opacity: 0.7;
}

/* ---------- Accounts: collapsible cards ------------------- */
#page-accounts .card.accounts-collapsed > *:not(.card-header) {
  display: none !important;
}
#page-accounts .card.accounts-collapsed .card-header .accounts-toolbar {
  display: none !important;
}
#page-accounts .card.accounts-collapsed {
  padding-top: 14px;
  padding-bottom: 14px;
}
#page-accounts .card.accounts-collapsed .card-header {
  margin-bottom: 0;
}

/* ---------- Accounts: per-account transaction breakdown ---- */
.accounts-breakdown-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 6px 10px;
  padding: 8px 10px;
  border-radius: 8px;
  cursor: pointer;
  font-size: 0.9rem;
  transition: background-color 120ms ease;
}
.accounts-breakdown-row:hover {
  background: var(--color-surface-2, rgba(127, 127, 127, 0.08));
}
.accounts-breakdown-row.is-active {
  background: rgba(9, 127, 232, 0.14);
  color: #097fe8;
  font-weight: 700;
}
.accounts-breakdown-row__name {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-weight: 600;
}
.accounts-breakdown-row__counts {
  display: inline-flex;
  align-items: baseline;
  gap: 10px;
  white-space: nowrap;
  flex-wrap: wrap;
  justify-content: flex-end;
}
.accounts-breakdown-row__cell {
  font-variant-numeric: tabular-nums lining-nums;
  color: var(--color-text-secondary, var(--muted));
  white-space: nowrap;
}
.accounts-breakdown-row__cell--zero {
  opacity: 0.35;
}
.accounts-breakdown-row__total {
  font-variant-numeric: tabular-nums lining-nums;
  font-weight: 700;
  color: var(--color-text-primary, inherit);
  white-space: nowrap;
  margin-left: 4px;
  padding-left: 10px;
  border-left: 1px solid var(--color-border, rgba(127, 127, 127, 0.25));
}
@media (max-width: 640px) {
  .accounts-breakdown-row {
    flex-direction: column;
    align-items: stretch;
    gap: 2px;
    padding: 6px 8px;
    font-size: 0.88rem;
  }
  .accounts-breakdown-row__name {
    font-size: 0.92rem;
    line-height: 1.25;
    white-space: normal;
    word-break: break-word;
  }
  .accounts-breakdown-row__counts {
    justify-content: space-between;
    gap: 0 4px;
    font-size: 0.84rem;
  }
  .accounts-breakdown-row__cell,
  .accounts-breakdown-row__total {
    /* Tight horizontal rhythm — every count cell gets just enough
       room for "⚡ 12" at worst. */
    min-width: 40px;
  }
  .accounts-breakdown-row__total {
    margin-left: 0;
    padding-left: 8px;
  }
}
/* Slightly tighter vertical rhythm on all viewports — the breakdown
   is a scannable summary, not an interactive list. */
#accounts-breakdown-body .accounts-breakdown-row + .accounts-breakdown-row {
  margin-top: 2px;
}

/* ---------- Receipts Processed activity chart ------------- */
/* Clean line-area chart + stats strip. Inspired by modern finance
   apps (Monarch, Copilot) — shape at a glance, detail on hover. */
.receipts-activity-body {
  margin-top: 10px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.receipts-activity-stats {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 10px;
}
.receipts-activity-stat {
  padding: 6px 10px;
  border-radius: 8px;
  background: var(--color-surface-2, rgba(127, 127, 127, 0.08));
  min-width: 0;
}
.receipts-activity-stat__label {
  display: block;
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--muted);
  line-height: 1;
  margin-bottom: 4px;
}
.receipts-activity-stat__value {
  display: block;
  font-size: 1.1rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums lining-nums;
  line-height: 1.1;
  color: var(--color-text-primary, inherit);
}
.receipts-activity-stat__sub {
  display: block;
  font-size: 0.72rem;
  color: var(--muted);
  margin-top: 2px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.receipts-activity-chart {
  position: relative;
  width: 100%;
  height: 160px;
}
.receipts-activity-chart svg {
  width: 100%;
  height: 100%;
  display: block;
  overflow: visible;
}
.receipts-activity-chart__axis {
  stroke: var(--color-border, rgba(127, 127, 127, 0.18));
  stroke-width: 1;
}
.receipts-activity-chart__area {
  fill: url(#receipts-activity-gradient);
}
.receipts-activity-chart__line {
  fill: none;
  stroke: #4aa3ff;
  stroke-width: 2px;
  stroke-linecap: round;
  stroke-linejoin: round;
  /* Keep stroke at 2 logical pixels regardless of SVG viewBox scaling —
     without this, preserveAspectRatio='none' on wide containers warps
     the line weight asymmetrically and the chart reads as angular. */
  vector-effect: non-scaling-stroke;
}
.receipts-activity-chart__dot {
  fill: #4aa3ff;
  stroke: var(--color-surface, #1f2024);
  stroke-width: 2px;
  vector-effect: non-scaling-stroke;
  opacity: 0;
  transition: opacity 120ms ease;
}
.receipts-activity-chart__hit {
  fill: transparent;
  cursor: crosshair;
}
.receipts-activity-chart__hit:hover + .receipts-activity-chart__dot,
.receipts-activity-chart__dot--active {
  opacity: 1;
}
.receipts-activity-chart__hover-line {
  stroke: rgba(74, 163, 255, 0.35);
  stroke-width: 1;
  stroke-dasharray: 3 3;
  opacity: 0;
  pointer-events: none;
}
.receipts-activity-tooltip {
  position: absolute;
  top: 0;
  background: var(--color-surface, #1f2024);
  border: 1px solid var(--color-border, rgba(127, 127, 127, 0.3));
  border-radius: 8px;
  padding: 6px 10px;
  font-size: 0.8rem;
  pointer-events: none;
  opacity: 0;
  transition: opacity 120ms ease;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.22);
  white-space: nowrap;
  z-index: 3;
}
.receipts-activity-tooltip__period {
  color: var(--muted);
  font-size: 0.72rem;
  margin-bottom: 2px;
}
.receipts-activity-tooltip__count {
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.receipts-activity-tooltip__amount {
  margin-top: 2px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: #4aa3ff;
}
.receipts-activity-axis-labels {
  display: flex;
  justify-content: space-between;
  color: var(--muted);
  font-size: 0.75rem;
  margin-top: 2px;
}
@media (max-width: 640px) {
  .receipts-activity-stat__value {
    font-size: 1rem;
  }
  .receipts-activity-stat__label {
    font-size: 0.62rem;
  }
  .receipts-activity-stats {
    gap: 6px;
  }
  .receipts-activity-stat {
    padding: 5px 8px;
  }
  .receipts-activity-chart {
    height: 140px;
  }
}
.spend-by-person-monthnav__btn.is-active {
  color: var(--color-text-primary, inherit);
  background: var(--color-surface-2, rgba(127, 127, 127, 0.12));
}

/* ---------- Spend-by-person month navigator ---------------- */
.spend-by-person-monthnav {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 2px;
  border-radius: 9999px;
  border: 1px solid var(--color-border, rgba(0, 0, 0, 0.15));
  background: transparent;
}
.spend-by-person-monthnav__btn {
  -webkit-appearance: none;
  appearance: none;
  background: transparent;
  border: 0;
  padding: 2px 8px;
  cursor: pointer;
  font-size: 0.95rem;
  line-height: 1;
  color: var(--color-text-secondary, var(--muted, #888));
  border-radius: 9999px;
  transition: background-color 120ms ease, color 120ms ease;
}
.spend-by-person-monthnav__btn:hover {
  background: var(--color-surface-2, rgba(127, 127, 127, 0.1));
  color: var(--color-text-primary, inherit);
}
.spend-by-person-monthnav__label {
  min-width: 44px;
  text-align: center;
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--color-text-primary, inherit);
  padding: 0 2px;
  font-variant-numeric: tabular-nums;
}

/* ---------- Attribution multi-select picker ----------------- */
.attr-picker-wrap {
  position: relative;
  display: inline-block;
}
.attr-picker-trigger {
  -webkit-appearance: none;
  appearance: none;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px;
  border-radius: 9999px;
  border: 1px solid var(--color-border, rgba(0, 0, 0, 0.15));
  background-color: transparent;
  background-image: none;
  color: var(--color-text-primary, inherit);
  font-size: 0.82rem;
  font-weight: 600;
  cursor: pointer;
  max-width: 220px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  transition: background-color 120ms ease, border-color 120ms ease;
}
.attr-picker-trigger:hover {
  background: var(--color-surface-2, rgba(127, 127, 127, 0.08));
}
.attr-picker-trigger.is-open {
  border-color: #097fe8;
  background: var(--color-surface-2, rgba(127, 127, 127, 0.08));
}
.attr-picker-trigger .attr-caret {
  opacity: 0.55;
  font-size: 0.7rem;
}
.attr-picker-panel {
  position: absolute;
  z-index: 1200;
  top: calc(100% + 6px);
  right: 0;
  min-width: 220px;
  max-height: 320px;
  overflow-y: auto;
  background: var(--color-surface, var(--color-surface-1, #1b1b1d));
  color: var(--color-text-primary, inherit);
  border: 1px solid var(--color-border, rgba(255, 255, 255, 0.15));
  border-radius: var(--radius-md, 10px);
  box-shadow: var(--shadow-2, 0 6px 18px rgba(0, 0, 0, 0.35));
  padding: 6px;
  font-size: 0.88rem;
}
.attr-picker-option {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 10px;
  border-radius: 6px;
  cursor: pointer;
  user-select: none;
  color: var(--color-text-primary, inherit);
}
.attr-picker-option:hover {
  background: var(--color-surface-2, rgba(127, 127, 127, 0.1));
}
.attr-picker-option.is-active {
  background: rgba(9, 127, 232, 0.18);
  color: #4aa3ff;
  font-weight: 600;
}
.attr-picker-option input[type="radio"],
.attr-picker-option input[type="checkbox"] {
  accent-color: #097fe8;
  margin: 0;
}
.attr-picker-divider {
  height: 1px;
  background: var(--color-border, rgba(0, 0, 0, 0.1));
  margin: 4px 0;
}
.attr-picker-caption {
  padding: 4px 10px;
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted, #888);
}
.attr-badge--shared {
  background: rgba(148, 78, 194, 0.12);
  color: #944ec2;
  border: 1px solid rgba(148, 78, 194, 0.28);
}
@media (max-width: 640px) {
  .attr-picker-panel {
    right: auto;
    left: 0;
  }
}

/* === Receipts bulk-attribution toolbar === */
.attr-bulk-toolbar {
  position: sticky;
  top: 12px;
  z-index: 50;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 14px;
  margin-bottom: 12px;
  background: var(--color-surface-1, #fff);
  border: 1px solid var(--color-accent, #4aa3ff);
  border-radius: 999px;
  box-shadow: var(--shadow-2, 0 4px 12px rgba(0, 0, 0, 0.08));
  font-weight: 600;
  font-size: 0.92rem;
}
.attr-bulk-toolbar__label {
  margin-right: auto;
  font-variant-numeric: tabular-nums;
}
.receipt-bulk-cell {
  width: 28px;
  text-align: center;
}
/* === Bulk attribution modal — theme-aware, polished === */
.attr-bulk-modal {
  background: var(--color-surface, #fff);
  color: var(--color-text-primary, #1d1d1f);
  border: 1px solid var(--color-border, rgba(0, 0, 0, 0.12));
  border-radius: 16px;
  padding: 0;
  width: min(440px, 92vw);
  max-height: min(86vh, 720px);
  box-shadow: 0 18px 48px rgba(0, 0, 0, 0.28);
  overflow: hidden;
  font-family: inherit;
}
.attr-bulk-modal::backdrop {
  background: rgba(0, 0, 0, 0.55);
  backdrop-filter: blur(2px);
}
.attr-modal__form {
  display: flex;
  flex-direction: column;
  max-height: inherit;
  margin: 0;
  padding: 0;
  background: inherit;
}
.attr-modal__header {
  padding: 18px 22px 12px;
  border-bottom: 1px solid var(--color-border, rgba(0, 0, 0, 0.10));
  background: var(--color-surface, transparent);
}
.attr-modal__title {
  margin: 0;
  font-size: 1.08rem;
  font-weight: 700;
  color: var(--color-text-primary, #1d1d1f);
  letter-spacing: -0.01em;
}
.attr-modal__sub {
  margin: 6px 0 0;
  font-size: 0.85rem;
  line-height: 1.4;
  color: var(--color-text-secondary, rgba(0, 0, 0, 0.7));
}
.attr-modal__section {
  padding: 14px 22px;
  border-bottom: 1px solid var(--color-border, rgba(0, 0, 0, 0.08));
  background: var(--color-surface, transparent);
}
.attr-modal__section:last-of-type { border-bottom: 0; }
.attr-modal__members-section {
  flex: 1 1 auto;
  overflow-y: auto;
  min-height: 0;
}
.attr-modal__heading {
  margin: 0 0 10px;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-text-muted, rgba(0, 0, 0, 0.55));
}
/* Kind selector — segmented row of cards. */
.attr-modal__kinds {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 8px;
}
.attr-modal__kind {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 10px 10px;
  background: var(--color-surface-2, rgba(127, 127, 127, 0.06));
  border: 1px solid var(--color-border, rgba(0, 0, 0, 0.12));
  border-radius: 12px;
  cursor: pointer;
  text-align: left;
  transition: background 140ms ease, border-color 140ms ease;
  color: var(--color-text-primary, inherit);
}
.attr-modal__kind input[type="radio"] {
  position: absolute;
  inset: 0;
  opacity: 0;
  cursor: pointer;
  margin: 0;
}
.attr-modal__kind:hover {
  background: var(--color-surface-3, rgba(127, 127, 127, 0.12));
}
.attr-modal__kind.is-active {
  background: color-mix(in srgb, var(--color-border-brand, #0071e3) 18%, var(--color-surface, transparent));
  border-color: var(--color-border-brand, #0071e3);
  box-shadow: 0 0 0 1px var(--color-border-brand, #0071e3) inset;
}
.attr-modal__kind-label {
  font-weight: 700;
  font-size: 0.92rem;
  color: var(--color-text-primary, inherit);
}
.attr-modal__kind-hint {
  font-size: 0.72rem;
  color: var(--color-text-secondary, rgba(0, 0, 0, 0.65));
}
/* Member rows — chip-card style with avatar. */
.attr-modal__members {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.attr-modal__member {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px 12px;
  border-radius: 10px;
  background: transparent;
  border: 1px solid transparent;
  cursor: pointer;
  transition: background 120ms ease, border-color 120ms ease;
  color: var(--color-text-primary, inherit);
}
.attr-modal__member:hover {
  background: var(--color-surface-2, rgba(127, 127, 127, 0.10));
}
.attr-modal__member input[type="checkbox"] {
  width: 16px;
  height: 16px;
  margin: 0;
  accent-color: var(--color-border-brand, #0071e3);
  cursor: pointer;
}
.attr-modal__avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: linear-gradient(135deg,
    color-mix(in srgb, var(--color-border-brand, #0071e3) 60%, #ffffff 40%),
    var(--color-border-brand, #0071e3));
  color: #fff;
  font-size: 0.78rem;
  font-weight: 800;
  letter-spacing: 0.02em;
  flex-shrink: 0;
}
.attr-modal__name {
  flex: 1;
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--color-text-primary, inherit);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.attr-modal__check {
  font-weight: 800;
  font-size: 0.85rem;
  color: var(--color-border-brand, #0071e3);
  opacity: 0;
  transition: opacity 120ms ease;
}
.attr-modal__member.is-checked {
  background: color-mix(in srgb, var(--color-border-brand, #0071e3) 12%, var(--color-surface, transparent));
  border-color: color-mix(in srgb, var(--color-border-brand, #0071e3) 30%, transparent);
}
.attr-modal__member.is-checked .attr-modal__check {
  opacity: 1;
}
.attr-modal__empty {
  padding: 12px;
  font-size: 0.85rem;
  color: var(--color-text-secondary, rgba(0, 0, 0, 0.65));
  text-align: center;
}
.attr-modal__footer {
  display: flex;
  gap: 8px;
  justify-content: flex-end;
  padding: 14px 22px;
  border-top: 1px solid var(--color-border, rgba(0, 0, 0, 0.10));
  background: var(--color-surface-2, transparent);
}

/* === Dashboard attribution-nudge banner === */
.dash-attr-nudge {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 14px;
  margin: 0 0 16px;
  background: var(--color-surface-2);
  color: var(--color-text-primary);
  border: 1px solid var(--color-brand-soft);
  border-radius: var(--radius-lg, 12px);
  font-size: 0.92rem;
}
.dash-attr-nudge__icon {
  font-size: 1.1rem;
}
.dash-attr-nudge__text {
  flex: 1;
  font-weight: 600;
  color: var(--color-text-primary);
}
.dash-attr-nudge__cta {
  cursor: pointer;
  font-weight: 700;
  color: var(--color-link);
  white-space: nowrap;
}
.dash-attr-nudge__cta:hover {
  text-decoration: underline;
}

/* === Page pager (bottom-of-page Prev / Next) === */
.page-pager {
  display: flex;
  align-items: stretch;
  gap: 0;
  margin: 28px 0 12px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg, 14px);
  background: var(--color-surface-2);
  overflow: hidden;
  font-family: inherit;
  /* Pin to bottom of viewport regardless of content height so the
     Prev/Next pair stays in the same screen position across pages. */
  position: sticky;
  bottom: 8px;
  z-index: 10;
  margin-top: auto;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.25);
}

/* Make the active page a flex column so .page-pager's margin-top:auto
   pushes it to the bottom even when content is short. */
.page.active {
  display: flex;
  flex-direction: column;
  min-height: calc(100vh - var(--app-header-height, 64px));
}
.page-pager__btn {
  flex: 1;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 18px;
  background: transparent;
  border: 0;
  cursor: pointer;
  color: var(--color-text-primary);
  font: inherit;
  text-align: left;
  transition:
    background-color 160ms ease,
    transform 160ms ease;
}
.page-pager__next {
  flex-direction: row;
  text-align: right;
  justify-content: flex-end;
}
.page-pager__btn:hover:not(:disabled) {
  background: var(--color-brand-soft);
}
.page-pager__btn:active:not(:disabled) {
  transform: translateY(1px);
}
.page-pager__btn:focus-visible {
  outline: 2px solid var(--color-brand);
  outline-offset: -2px;
}
.page-pager__btn:disabled {
  cursor: default;
  opacity: 0.55;
}
.page-pager__divider {
  width: 1px;
  background: var(--color-border);
  flex: 0 0 auto;
}
.page-pager__arrow {
  font-size: 1.4rem;
  font-weight: 600;
  line-height: 1;
  color: var(--color-brand);
  flex: 0 0 auto;
}
.page-pager__arrow--mute {
  color: var(--color-text-muted, var(--color-text-primary));
  opacity: 0.55;
}
.page-pager__stack {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
  flex: 1 1 auto;
}
.page-pager__stack--right {
  align-items: flex-end;
  text-align: right;
}
.page-pager__hint {
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--color-text-muted, var(--color-text-primary));
  opacity: 0.7;
}
.page-pager__name {
  font-size: 0.98rem;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
}
.page-pager__name--mute {
  font-weight: 500;
  opacity: 0.65;
}
@media (max-width: 560px) {
  .page-pager__hint {
    font-size: 0.66rem;
  }
  .page-pager__name {
    font-size: 0.88rem;
  }
  .page-pager__btn {
    padding: 12px 14px;
    gap: 8px;
  }
}

/* === Upload result extras (inline attribution + per-item photo) === */
.upload-result-attr {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  margin: 14px 0;
  padding: 12px 14px;
  background: var(--color-surface-2);
  color: var(--color-text-primary);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg, 12px);
}
.upload-result-attr-label {
  font-size: 0.74rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-text-muted, var(--color-text-primary));
  opacity: 0.8;
}
.upload-result-attr-hint {
  font-size: 0.78rem;
  color: var(--color-text-muted, var(--color-text-primary));
  opacity: 0.75;
  flex: 1 1 240px;
}
.upload-result-table-wrap {
  margin-top: 6px;
  overflow-x: auto;
}
.upload-result-items {
  width: 100%;
  border-collapse: collapse;
}
.upload-result-items th,
.upload-result-items td {
  padding: 10px 12px;
  border-bottom: 1px solid var(--color-border);
}
.upload-result-items th {
  text-align: left;
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--color-text-muted, var(--color-text-primary));
  opacity: 0.85;
}
.upload-result-items tbody tr:last-child td {
  border-bottom: 0;
}
.upload-result-photo-cell {
  text-align: right;
  white-space: nowrap;
}
.upload-result-photo-btn {
  white-space: nowrap;
}
.upload-result-photo-na {
  color: var(--color-text-muted, var(--color-text-primary));
  opacity: 0.55;
  font-size: 0.78rem;
}
.upload-result-summary {
  margin-top: 12px;
  color: var(--color-text-muted, var(--color-text-primary));
  font-size: 0.82rem;
}
.upload-result-actions {
  margin-top: 14px;
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  justify-content: flex-end;
}
