/* ============================================================
   public/css/app.css — L'Économe
   Vert Jean-Talon : vert maraîcher vif (#4A9E46) en accent unique,
   papier presque blanc teinté tabac (#faf6ec), encre tabac profonde.
   Direction Atelier : mono-accent premium, registre boutique
   artisan québécois, jamais SaaS, jamais folklorique.
   ============================================================ */

/* ── DESIGN TOKENS ──────────────────────────────────────────── */
:root {
  /* ── Motion — courbes d'animation partagées ─────────────── */
  --ease-snap: cubic-bezier(0.22, 0.61, 0.36, 1); /* press/pop — décélération nette, plus de rebond */
  --ease-out: cubic-bezier(0.25, 0.1, 0.25, 1); /* décélération naturelle */
  --ease-out-quart: cubic-bezier(0.25, 1, 0.5, 1); /* exponentielle douce */
  --ease-in-out: cubic-bezier(0.4, 0, 0.2, 1); /* transitions fluides */

  /* ── Typography ─────────────────────────────────────────── */
  --font-display: "Young Serif", "Iowan Old Style", "Palatino Linotype", Palatino, Georgia, serif;
  --font-body: "Commissioner", -apple-system, BlinkMacSystemFont, system-ui, "Segoe UI", sans-serif;
  --font-numeric: "Commissioner", ui-monospace, "SF Mono", monospace; /* tabular figures via feature-settings */

  /* ── Paper surfaces — blanc crème option B, jamais #fff pur ─ */
  /* Hue 75° = tabac / papier boulangerie. Chroma 0.006 = quasi-blanc
     perçu mais jamais froid, warmth résiduelle pour asseoir le vert. */
  --paper: oklch(0.985 0.006 75); /* #faf6ec — fond page, presque blanc */
  --paper-soft: oklch(0.948 0.008 75); /* #ebe5d2 — sunk surface, +4 delta vs paper (war room 2026-05-10) */
  --paper-sheet: oklch(0.996 0.002 75); /* #fefdfa — raised card, quasi-pur */
  --paper-deep: oklch(0.935 0.01 75); /* #e7e0cd — diviseurs forts */

  /* ── Ink — tabac profond, warm-brown charcoal ───────────── */
  --ink: oklch(0.22 0.016 75); /* primary text — 15.2:1 on paper */
  --ink-soft: oklch(0.36 0.014 72); /* secondary — 9.8:1 (boost pour <14px et fond accent-tint) */
  --ink-muted: oklch(0.46 0.012 70); /* tertiary / metadata — 6.9:1 AA+ (boost mobile/small-text) */
  --ink-fade: oklch(0.54 0.01 70); /* placeholder / disabled — 5.0:1 AA+ */

  /* ── Accent unique — Vert Jean-Talon ──────────────────────
     Repensé avril 2026 — direction Atelier, mono-accent premium.
     Vert maraîcher vif, échantillonné du titre "Marché Jean-Talon",
     registre farmer-market-chalkboard / Olive et Gourmando. Pas
     Mint, pas Starbucks, pas Too Good To Go, pas iOS green. */
  --accent: oklch(0.59 0.16 143); /* #4A9E46 — signature unique, 4.9:1 cream-on-accent */
  --accent-deep: oklch(0.44 0.13 143); /* #2f6f30 — pressed / petit texte sur cream, 7.9:1 */
  --accent-bright: oklch(0.72 0.17 143); /* #6ec269 — hover / glow companion */
  --accent-tint: oklch(0.958 0.026 143); /* #eaf3e6 — surface tintée rare (actif nav, badge) */
  --accent-tint2: oklch(0.91 0.05 143); /* #d4e8ce — callout « aubaine confirmée » */
  --accent-glow: 0 6px 28px oklch(0.59 0.16 143 / 0.26);

  /* ── Danger — oxblood retiré du quotidien, réservé vraies urgences
     (suppression compte, erreur réseau). Urgence souper passe à --accent. */
  --danger: oklch(0.44 0.14 25); /* 6.8:1 AA */
  --danger-deep: oklch(0.34 0.12 25);
  --danger-bright: oklch(0.58 0.16 25);
  --danger-tint: oklch(0.945 0.035 25); /* #f4e3df — fond alerte */
  /* ── Heart (coup de cœur) — rouge-coeur doux tinté brick, distinct
     de --danger pour ne pas confondre « retirer » et « j'aime ». */
  --heart: oklch(0.58 0.19 15);
  --heart-deep: oklch(0.52 0.2 15);
  --danger-tint2: oklch(0.9 0.04 25);
  --danger-glow: 0 6px 28px oklch(0.44 0.14 25 / 0.22);

  /* Badges intensité (dislikes : parfois OK = ambre, trace OK = neutre).
     Tokens theme-aware (audit 2026-05-28) : avant valeurs oklch littérales
     fixes qui ne flippaient pas en dark mode → contraste insuffisant. */
  --badge-warn-bg: oklch(0.85 0.10 80 / 0.18);
  --badge-warn-ink: oklch(0.40 0.13 70);
  --badge-neutral-bg: oklch(0.92 0.012 75);
  --badge-neutral-ink: oklch(0.42 0.012 75);

  /* Accents saisonniers / utilitaires — seulement via seasons.css */
  --courge: oklch(0.62 0.14 68); /* squash amber — automne */
  --courge-tint: oklch(0.955 0.038 68);
  --moutarde: oklch(0.54 0.13 82); /* conservé en accent automne saisonnier, retiré du core */
  --moutarde-tint: oklch(0.945 0.038 82);
  --ardoise: oklch(0.52 0.1 220); /* slate bleu-pétrole — hiver */
  --ardoise-tint: oklch(0.945 0.03 220);
  --paille: oklch(0.82 0.13 72); /* straw — été highlight */
  --violette: oklch(0.52 0.13 325);
  --violette-tint: oklch(0.945 0.03 325);

  /* ── Fixed cream — text color on accent backgrounds ──────── */
  /* NEVER swaps in dark mode — cream-on-vert reste lisible light+dark. */
  --cream-fixed: oklch(0.992 0.006 85);
  --cream-fixed-soft: oklch(0.992 0.006 85 / 0.82);
  --cream-fixed-fade: oklch(0.992 0.006 85 / 0.55);

  /* ── Legacy aliases — 3 000+ lignes cascadent sans refactor ── */
  --bg: var(--paper);
  --white: var(--paper-sheet);
  --surface: var(--paper-soft);
  --ink2: var(--ink-soft);
  --muted: var(--ink-muted);
  --muted2: var(--ink-fade);

  --brand: var(--accent);
  --brand-light: var(--accent-bright);
  --brand-dark: var(--accent-deep);
  --brand-pale: var(--accent-tint);
  --brand-glow: var(--accent-glow);

  /* Legacy --brick / --canneberge / --labrador / --moutarde : tous alias
     vers --accent ou --danger. Aucune recherche-remplacement massive requise. */
  --brick: var(--accent);
  --brick-deep: var(--accent-deep);
  --brick-bright: var(--accent-bright);
  --brick-tint: var(--accent-tint);
  --brick-tint2: var(--accent-tint2);
  --brick-glow: var(--accent-glow);

  --canneberge: var(--danger);
  --canneberge-tint: var(--danger-tint);

  --labrador: var(--accent);
  --labrador-deep: var(--accent-deep);
  --labrador-bright: var(--accent-bright);
  --labrador-tint: var(--accent-tint);
  --labrador-tint2: var(--accent-tint2);
  --labrador-glow: var(--accent-glow);

  --oxblood: var(--danger);
  --oxblood-deep: var(--danger-deep);
  --oxblood-bright: var(--danger-bright);
  --oxblood-tint: var(--danger-tint);
  --oxblood-tint2: var(--danger-tint2);
  --oxblood-glow: var(--danger-glow);

  --orange: var(--accent);
  --orange-pale: var(--accent-tint);
  --green: var(--accent); /* vert canonique = accent unique */
  --green-pale: var(--accent-tint);
  --red: var(--danger);
  --amber: var(--courge);
  --amber-pale: var(--accent-tint);
  --blue: var(--ardoise);
  --violet: var(--violette);

  /* ── Borders, shadows, radii — tabac tint visible sur papier blanc ── */
  --border: oklch(0.82 0.018 75); /* 2.1:1 — visible en plein soleil */
  --border2: oklch(0.88 0.014 75);
  --shadow: 0 1px 2px oklch(0.22 0.016 75 / 0.08), 0 1px 3px oklch(0.22 0.016 75 / 0.09);
  --shadow-md: 0 6px 20px oklch(0.22 0.016 75 / 0.12), 0 2px 6px oklch(0.22 0.016 75 / 0.08);
  --shadow-lg: 0 18px 48px oklch(0.22 0.016 75 / 0.16), 0 4px 12px oklch(0.22 0.016 75 / 0.09);

  --radius-sm: 10px;
  --radius: 14px;
  --radius-lg: 20px;
  --radius-xl: 28px;

  /* ── Spacing scale (4pt, semantic) ──────────────────────── */
  --space-2xs: 4px;
  --space-xs: 8px;
  --space-sm: 12px;
  --space-md: 16px;
  --space-lg: 24px;
  --space-xl: 32px;
  --space-2xl: 48px;
  --space-3xl: 64px;
  --space-4xl: 96px;
}

/* ── RESET & UTILITIES ──────────────────────────────────────── */
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

/* Screen-reader only — visible to assistive tech, invisible to sighted users */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* Reduced motion — respect user OS preference */
@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;
  }
}
/* Par défaut (mobile-first) : document coule naturellement dans body.
   Le scroll-lock desktop (double-container) est appliqué seulement ≥ 769px,
   voir la règle @media (min-width: 769px) plus bas. */
html,
body {
  min-height: 100%;
}
body {
  font-family: var(--font-body);
  font-feature-settings:
    "ss01",
    "cv11",
    "tnum" 0;
  font-size: 16px;
  line-height: 1.55;
  background: var(--paper);
  color: var(--ink);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}
a {
  text-decoration: none;
  color: inherit;
}
/* Numbers use tabular figures so prices align down a column */
.num,
.fb-amount,
.kpi-val,
.sc-pct,
.cmp-v,
.fb-sub strong,
.rc-total,
.mockup-budget-amount,
.ri-price,
.si-p,
.plan-price {
  font-variant-numeric: tabular-nums;
  font-feature-settings:
    "tnum" 1,
    "lnum" 1;
}
::-webkit-scrollbar {
  width: 6px;
  height: 6px;
}
::-webkit-scrollbar-track {
  background: transparent;
}
::-webkit-scrollbar-thumb {
  background: var(--border);
  border-radius: 3px;
}
@media (hover: hover) and (pointer: fine) {
  ::-webkit-scrollbar-thumb:hover {
    background: var(--ink-fade);
  }
}

/* accent-color global 2026-05-09 (audit R10 a11y) : harmonise les
   widgets natifs (checkbox, radio, range, progress) avec la marque.
   Chrome 93+ / Edge 93+ / Safari 15.4+ / Firefox 92+. Pour iOS Safari
   < 15.3, le fallback :checked + ::before sur .profil-toggle-cb (R4)
   continue de marcher en parallele. */
input[type="checkbox"],
input[type="radio"],
input[type="range"],
progress {
  accent-color: var(--brand-dark, var(--brand));
}

/* ── LAYOUT ─────────────────────────────────────────────────── */
/* Mobile-first : on remplit juste le viewport, body scrolle naturellement.
   100dvh fix iOS Safari 2026-05-09 (audit R8) : 100vh = hauteur viewport
   AVEC barre adresse baissee, depasse de ~100px quand la barre se leve.
   100dvh = dynamic viewport height qui suit la chrome bar. Fallback 100vh
   pour browsers anciens (Safari < 15.4). */
.app-layout {
  display: flex;
  min-height: 100vh;
  min-height: 100dvh;
}

/* ============================================================
   SIDEBAR — Apple-style Light
   ============================================================ */
.sidebar {
  width: 240px;
  flex-shrink: 0;
  background: var(--paper-sheet);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  position: relative;
  border-right: 1px solid var(--border);
}
/* Scrollable nav area — prevents overflow on short screens */
.sidebar .nav {
  flex: 1;
  overflow-y: auto;
  overflow-x: hidden;
  padding-bottom: 8px;
  scrollbar-width: thin;
  scrollbar-color: var(--border) transparent;
}
.sidebar .nav::-webkit-scrollbar {
  width: 4px;
}
.sidebar .nav::-webkit-scrollbar-thumb {
  background: var(--border);
  border-radius: 4px;
}
.sidebar .nav::-webkit-scrollbar-track {
  background: transparent;
}
.sidebar::after {
  content: "";
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  width: 1px;
  background: transparent;
}

/* Logo */
.logo-zone {
  padding: 20px 20px 18px;
  border-bottom: 1px solid var(--border);
}
.logo-mark {
  display: flex;
  align-items: center;
  gap: 10px;
}
/* Logo mark refonte 2026-05-10 : retrait du gradient + halo vert qui
   transformait le logo en bouton SaaS. Maintenant fond plat brand,
   pas de halo (un logotype n'a pas besoin d'auréole). */
.logo-sq {
  width: 36px;
  height: 36px;
  border-radius: var(--radius-sm);
  background: var(--accent, var(--brand));
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 18px;
}
.logo-img {
  filter: drop-shadow(0 2px 6px oklch(0.59 0.16 143 / 0.32));
}
.logo-txt {
  font-family: var(--font-display);
  font-size: 19px;
  font-weight: 800;
  color: var(--ink);
  letter-spacing: -0.5px;
  white-space: nowrap;
}
.logo-txt em {
  color: var(--brand);
  font-style: normal;
}
/* Inline-É glyph — replaces the É in "L'Économe" so the wordmark itself
   carries the brand mark. Defensive selector (img.brand-e) to beat any
   global `img { display:block; height:auto }` reset present in the bundle. */
img.brand-e {
  display: inline-block;
  height: 1.08em;
  width: auto;
  max-width: none;
  vertical-align: -0.1em;
  color: var(--brand);
  margin: 0 0.01em;
  flex-shrink: 0;
}
.logo-sub {
  font-size: 9px;
  letter-spacing: 2.5px;
  text-transform: uppercase;
  color: var(--muted);
  margin-top: 4px;
}

/* A2HS install button — apparait uniquement quand beforeinstallprompt est dispo */
.pwa-install-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-top: 10px;
  padding: 7px 12px;
  border-radius: 999px;
  background: var(--brand);
  color: var(--cream-fixed);
  border: none;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.3px;
  cursor: pointer;
  transition:
    transform 0.15s ease,
    background 0.15s ease;
}
@media (hover: hover) and (pointer: fine) {
  .pwa-install-btn:hover {
    background: oklch(0.4 0.1 158);
    transform: translateY(-1px);
  }
}
.pwa-install-btn[hidden] {
  display: none;
}

/* Weather */
.weather-strip {
  margin: 14px 16px 0;
  padding: 10px 14px;
  border-radius: var(--radius);
  background: var(--brand-pale);
  border: 1px solid oklch(0.59 0.16 143 / 0.14);
  display: flex;
  align-items: center;
  gap: 10px;
}
.w-icon {
  font-size: 22px;
}
.w-temp {
  font-size: 13px;
  font-weight: 700;
  color: var(--ink);
}
.w-desc {
  font-size: 11px;
  color: var(--ink-soft);
}
.w-ai {
  font-size: 11px;
  color: var(--brand-dark);
  margin-top: 2px;
  font-weight: 500;
}

/* Navigation */
.nav {
  flex: 1;
  padding: 12px 0;
  overflow-y: auto;
}
.nav-sec {
  font-size: 9px;
  letter-spacing: 2.5px;
  text-transform: uppercase;
  color: var(--muted2);
  padding: 16px 20px 5px;
  font-weight: 600;
}
.ni {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 20px;
  margin: 1px 8px;
  border-radius: var(--radius-sm);
  font-size: 13px;
  font-weight: 500;
  color: var(--muted);
  cursor: pointer;
  transition:
    transform 0.2s,
    opacity 0.2s,
    color 0.2s,
    background 0.2s,
    border-color 0.2s,
    box-shadow 0.2s cubic-bezier(0.25, 0.46, 0.45, 0.94);
  border-left: none;
}
@media (hover: hover) and (pointer: fine) {
  .ni:hover {
    color: var(--ink);
    background: var(--bg);
  }
}
.ni.on {
  color: var(--brand-dark);
  background: var(--brand-pale);
  font-weight: 600;
}
.nico {
  width: 16px;
  text-align: center;
  color: var(--ink-fade);
  font-size: 18px;
  line-height: 1;
  transition:
    color 0.2s,
    transform 0.2s;
  flex-shrink: 0;
}
.ni.on .nico {
  color: var(--brand-dark);
  transform: scale(1.4);
}
@media (hover: hover) and (pointer: fine) {
  .ni:hover .nico {
    color: var(--ink-muted);
  }
}
.nbadge {
  margin-left: auto;
  font-size: 9px;
  font-weight: 700;
  padding: 2px 7px;
  border-radius: 20px;
}
.nb-r {
  background: oklch(0.44 0.14 25 / 0.14);
  color: var(--red);
  border: 1px solid oklch(0.44 0.14 25 / 0.22);
}
.nb-a {
  background: oklch(0.62 0.14 68 / 0.14);
  color: var(--amber);
  border: 1px solid oklch(0.62 0.14 68 / 0.22);
}

/* ── Collapsible nav groups ─────────────────────────────────── */
.nav-group-toggle {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: calc(100% - 16px);
  margin: 10px 8px 2px;
  padding: 8px 14px;
  border-radius: var(--radius-sm);
  font-size: 10px;
  letter-spacing: 1.8px;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--ink-muted);
  background: none;
  border: none;
  cursor: pointer;
  transition:
    color 0.2s,
    background 0.2s;
  font-family: var(--font-body);
}
@media (hover: hover) and (pointer: fine) {
  .nav-group-toggle:hover {
    color: var(--ink);
    background: var(--bg);
  }
}
.nav-group-toggle.is-open {
  color: var(--brand-dark);
  background: var(--accent-tint);
}
.nav-group-chevron {
  font-size: 14px;
  font-weight: 400;
  line-height: 1;
  transition: transform 0.25s cubic-bezier(0.25, 0.46, 0.45, 0.94);
  color: var(--ink-fade);
}
.nav-group-toggle.is-open .nav-group-chevron {
  transform: rotate(90deg);
  color: var(--brand-dark);
}
.nav-group {
  /* Audit /audit P2 : avant `max-height: 0 → 400px` était un hack qui
     cappait le contenu à 400px (mauvais si nav grandit) et animait une
     propriété layout (paint+reflow). Maintenant grid-template-rows 0fr→1fr,
     unbounded, transitionne sur le compositor.
     Browser support 2026 : Chrome 117+, Firefox 127+, Safari 17.4+ (95%+).
     Browsers anciens : pas de transition smooth mais l'open/close marche. */
  display: grid;
  grid-template-rows: 0fr;
  opacity: 0;
  overflow: hidden;
  transition:
    grid-template-rows 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94),
    opacity 0.25s ease;
  border-left: 1px solid var(--border);
  margin-left: 22px;
}
.nav-group > * {
  min-height: 0;
}
.nav-group.is-open {
  grid-template-rows: 1fr;
  opacity: 1;
}
.nav-group .ni {
  padding-left: 14px;
  margin-left: 0;
}

/* Urgence button — mono-accent Vert Jean-Talon (zéro gradient) */
.urgence-btn {
  margin: 8px 12px 14px;
  padding: 11px 14px;
  border-radius: var(--radius);
  background: var(--accent);
  display: flex;
  align-items: center;
  gap: 10px;
  color: var(--cream-fixed);
  font-size: 12px;
  font-weight: 700;
  font-family: var(--font-body);
  transition:
    background 0.15s ease,
    transform 0.15s ease;
}
@media (hover: hover) and (pointer: fine) {
  .urgence-btn:hover {
    background: var(--accent-deep);
    transform: translateY(-1px);
  }
}
.ub-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--paper-sheet);
  animation: ubpulse 1.5s infinite;
}
@keyframes ubpulse {
  0%,
  100% {
    opacity: 1;
    transform: scale(1);
  }
  50% {
    opacity: 0.6;
    transform: scale(1.3);
  }
}

/* Sidebar Mode Grand-Maman toggle 2026-05-09 (Phase 1) :
   visible permanente pres du sidebar-user. Pas un setting cache,
   un commutateur de premier plan. Touch target 44px obligatoire. */
.sidebar-mode-gm-form {
  margin: 12px 16px 8px;
}
.sidebar-mode-gm-toggle {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  min-height: 44px;
  padding: 10px 14px;
  background: transparent;
  border: 1px solid var(--border, oklch(0.88 0.02 75));
  border-radius: 10px;
  cursor: pointer;
  font-family: var(--font-body);
  font-size: 13px;
  font-weight: 500;
  color: var(--ink-soft);
  text-align: left;
  transition:
    background 0.15s ease,
    border-color 0.15s ease,
    color 0.15s ease;
}
@media (hover: hover) and (pointer: fine) {
  .sidebar-mode-gm-toggle:hover,
  .sidebar-mode-gm-toggle:focus-visible {
    background: var(--paper-soft, var(--paper));
    border-color: color-mix(in oklch, var(--brand) 30%, var(--border));
    outline: none;
  }
}
.sidebar-mode-gm-toggle:focus-visible {
  box-shadow:
    0 0 0 2px var(--brand-dark, var(--brand)),
    0 0 0 4px var(--paper);
}
.sidebar-mode-gm-toggle.is-on {
  background: var(--accent-tint, color-mix(in oklch, var(--brand) 12%, var(--paper)));
  border-color: color-mix(in oklch, var(--brand) 40%, transparent);
  color: var(--brand-dark, var(--brand));
  font-weight: 600;
}
.sidebar-mode-gm-dot {
  flex: 0 0 auto;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--ink-fade);
  transition: background 0.15s ease;
}
.sidebar-mode-gm-toggle.is-on .sidebar-mode-gm-dot {
  background: var(--brand-dark, var(--brand));
  box-shadow: 0 0 0 3px color-mix(in oklch, var(--brand) 25%, transparent);
}
.sidebar-mode-gm-label {
  flex: 1;
}
.sidebar-mode-gm-state {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  opacity: 0.7;
}

/* User */
.sidebar-user {
  padding: 14px 20px;
  border-top: 1px solid var(--border);
  display: flex;
  align-items: center;
  gap: 10px;
}
.uav {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--brand), var(--brand-light));
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  font-weight: 700;
  color: var(--cream-fixed);
}
.uname {
  font-size: 12px;
  font-weight: 600;
  color: var(--ink);
}
.uplan {
  font-size: 10px;
  color: var(--brand);
  font-weight: 500;
}

/* ============================================================
   MAIN AREA
   ============================================================ */
.main {
  flex: 1;
  display: flex;
  flex-direction: column;
  background: var(--bg);
}

/* Topbar — surface solide, pas de glassmorphism */
.topbar {
  background: var(--paper-sheet);
  border-bottom: 1px solid var(--border);
  padding: 12px 28px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-shrink: 0;
}
.tb-left {
  display: flex;
  align-items: center;
  gap: 14px;
}
.ptitle {
  font-family: var(--font-display);
  font-size: 18px;
  font-weight: 800;
  color: var(--ink);
  letter-spacing: -0.2px;
}
.live-pill {
  display: flex;
  align-items: center;
  gap: 5px;
  padding: 4px 10px;
  border-radius: 20px;
  background: var(--brand-pale);
  border: 1px solid oklch(0.59 0.16 143 / 0.16);
  font-size: 10px;
  font-weight: 600;
  color: var(--brand-dark);
}
.ldot {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--brand);
  animation: lpulse 2s infinite;
}
@keyframes lpulse {
  0%,
  100% {
    opacity: 1;
  }
  50% {
    opacity: 0.4;
  }
}
.tb-right {
  display: flex;
  gap: 8px;
  align-items: center;
}

/* ── BUTTONS ────────────────────────────────────────────────── */
/* Refonte 2026-05-10 (war room senior) : avant linear-gradient brand→
   brand-light + brand-glow halo = SaaS 2018 atmosphère. Maintenant :
   fond plat brand + edge inset hairline (Linear/Stripe-style) qui donne
   du poids sans halo coloré. Le glow ambiant est désormais réservé au
   CTA primaire dominant unique de la page (cf. .btn-main--hero). */
.btn-main {
  padding: 9px 20px;
  border-radius: var(--radius-sm);
  border: none;
  cursor: pointer;
  font-family: var(--font-body);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: -0.2px;
  background: var(--accent, var(--brand));
  color: var(--cream-fixed);
  transition:
    transform 0.2s,
    opacity 0.2s,
    color 0.2s,
    background 0.2s,
    border-color 0.2s,
    box-shadow 0.2s cubic-bezier(0.25, 0.46, 0.45, 0.94);
  box-shadow: inset 0 -1px 0 oklch(0.44 0.13 143 / 0.35);
}
@media (hover: hover) and (pointer: fine) {
  .btn-main:hover {
    background: var(--brand-dark, var(--accent));
  }
}
.btn-main:active {
  transform: translateY(1px);
}
/* Variante .btn-main--hero : SEUL endroit où le glow ambiant survit
   (CTA primaire dominant de la page). Réservé au dashboard CTA et
   accueil hero CTA. Une surface par viewport maximum. */
.btn-main--hero,
.dash-cta-primary {
  box-shadow: var(--brand-glow);
}

/* État loading sur boutons submit 2026-05-09 (Phase 2) :
   après un submit avec data-loading, le button devient disabled +
   .is-loading. CSS dim + spinner ::before. Empêche clic-double. */
.btn-main.is-loading,
.btn-sec.is-loading {
  opacity: 0.7;
  cursor: progress;
  pointer-events: none;
  position: relative;
  padding-left: 36px;
}
.btn-main.is-loading::before,
.btn-sec.is-loading::before {
  content: "";
  position: absolute;
  left: 14px;
  top: 50%;
  width: 14px;
  height: 14px;
  margin-top: -7px;
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  animation: btn-spin 0.7s linear infinite;
}
@keyframes btn-spin {
  to {
    transform: rotate(360deg);
  }
}
@media (prefers-reduced-motion: reduce) {
  .btn-main.is-loading::before,
  .btn-sec.is-loading::before {
    animation: none;
  }
}
.btn-sec {
  /* iOS app feel : pas de border 1.5px outline (lit « bouton web »).
     Background tint + ink-soft text = pattern iOS tinted button.
     Le bouton garde son rôle interactif visuel sans bordure dure. */
  padding: 9px 16px;
  border-radius: var(--radius-sm);
  background: var(--paper-soft);
  color: var(--ink2);
  font-size: 12px;
  font-family: var(--font-body);
  cursor: pointer;
  transition:
    transform 0.18s,
    opacity 0.18s,
    color 0.18s,
    background 0.18s,
    box-shadow 0.18s;
  font-weight: 600;
}
@media (hover: hover) and (pointer: fine) {
  .btn-sec:hover {
    background: var(--accent-tint);
    color: var(--brand-dark);
  }
}
.btn-sec:active {
  transform: scale(0.98);
}
.btn-full {
  width: 100%;
  text-align: center;
  display: block;
  padding: 12px;
}

/* ── FLASH MESSAGES ─────────────────────────────────────────── */
.flash {
  padding: 12px 28px;
  font-size: 13px;
  font-weight: 500;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  transition:
    opacity 0.4s,
    transform 0.4s;
}
.flash-close {
  background: none;
  border: none;
  cursor: pointer;
  font-size: 20px;
  line-height: 1;
  color: inherit;
  opacity: 0.5;
  padding: 4px 8px;
  min-width: 44px;
  min-height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
}
@media (hover: hover) and (pointer: fine) {
  .flash-close:hover {
    opacity: 1;
  }
}
.flash-success {
  background: oklch(0.59 0.16 143 / 0.12);
  color: var(--brand-dark);
  border-bottom: 1px solid oklch(0.59 0.16 143 / 0.16);
}
.flash-error {
  background: oklch(0.44 0.14 25 / 0.1);
  color: var(--red);
  border-bottom: 1px solid oklch(0.44 0.14 25 / 0.18);
}

/* ── CONTENT ────────────────────────────────────────────────── */
/* Mobile-first : le contenu coule, pas de container scroll interne.
   Le scroll-lock desktop (container intérieur scrollable) est réactivé
   via @media (min-width: 769px) plus bas. */
.content {
  flex: 1;
  padding: 24px 28px;
}

/* Smooth page transitions */
.content > * {
  animation: fadeUp 0.35s cubic-bezier(0.25, 0.46, 0.45, 0.94) both;
}
@keyframes fadeUp {
  from {
    opacity: 0;
    transform: translateY(8px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* ============================================================
   CARDS — Apple-style
   ============================================================ */
.card {
  background: var(--paper);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 20px;
  box-shadow: var(--shadow);
  margin-bottom: 14px;
  transition: border-color 0.18s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}
@media (hover: hover) and (pointer: fine) {
  /* Hover Linear-style : border-color seulement, pas de translateY ni
   shadow-shift. Évite le pattern uniforme « tout bouge pareil ». */
  .card:hover {
    border-color: var(--accent-tint2, color-mix(in oklch, var(--brand) 30%, var(--border)));
  }
}
.chd {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 16px;
}
.ctitle {
  font-family: var(--font-display);
  font-size: 15px;
  font-weight: 700;
  color: var(--ink);
}
.caction {
  font-size: 11px;
  color: var(--brand);
  cursor: pointer;
  font-weight: 600;
}
/* Carte d'action destructive (suppression compte, etc.) — bordure
   canneberge atténuée et titre en canneberge plein. Utilise le token
   afin de rester cohérent en dark mode (≠ oklch hardcodé). */
.card--danger {
  border-color: color-mix(in oklch, var(--danger) 30%, transparent);
}
.ctitle--danger {
  color: var(--danger);
}

/* ── Mode cuisson plein-écran (cuisiner.blade.php) ───────────
   Anciennement inline <style> dans la vue, déplacé ici pour
   être cachable et utiliser uniquement les tokens (pas de hex). */
.cuisine-shell {
  max-width: 640px;
  margin: 0 auto;
  padding: 20px;
  display: flex;
  flex-direction: column;
  min-height: calc(100vh - 120px);
}
/* Header cuisine : flex-wrap pour ne pas écraser le titre + actions
   sur viewport étroit (<360px). Titre tronque proprement si très long. */
.cuisine-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 12px;
  margin-bottom: 16px;
  flex-wrap: wrap;
}
.cuisine-header-title {
  min-width: 0;
  flex: 1 1 auto;
}
.cuisine-header-actions {
  display: flex;
  gap: 8px;
  align-items: center;
  flex-shrink: 0;
}
/* Touch targets ≥ 44px (WCAG 2.5.5) sur le header cuisine — mode
   cuisine = mains pleines de farine, mal-tap probable sur 36px. */
.cuisine-tts-btn,
.cuisine-quitter-btn {
  font-size: 12px;
  padding: 12px 14px;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.cuisine-tts-btn[aria-pressed="true"],
.cuisine-tts-btn.is-on {
  background: var(--brand);
  color: var(--cream-fixed, #fff);
  border-color: var(--brand);
}
.cuisine-tts-btn:focus-visible,
.cuisine-quitter-btn:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
}
.cuisine-tts-icon {
  font-size: 14px;
  line-height: 1;
}
/* Bloc « Tu as terminé! » — éditorial centré, pas d'inline styles. */
.cuisine-end-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 12px;
  color: var(--brand-dark, var(--brand));
}
.cuisine-end-title {
  text-align: center;
  margin: 0 0 8px;
}
.cuisine-end-lede {
  text-align: center;
  color: var(--ink-muted);
  margin: 0 0 24px;
  font-size: 14px;
}
.cuisson-note-wrap {
  margin-top: 20px;
}
.cuisson-note-label {
  display: block;
  font-size: 12px;
  color: var(--ink-muted);
  margin-bottom: 6px;
}
.cuisson-note-textarea {
  width: 100%;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: 10px;
  font-family: var(--font-body);
  font-size: 13px;
  line-height: 1.5;
  resize: vertical;
  min-height: 60px;
  background: var(--paper-sheet);
  color: var(--ink);
}
.cuisson-note-textarea:focus {
  outline: 2px solid var(--brand);
  outline-offset: 1px;
  border-color: var(--brand);
}
.cuisson-note-counter {
  display: block;
  margin-top: 4px;
  font-size: 11px;
  color: var(--ink-muted);
  text-align: right;
  font-feature-settings: "tnum" 1;
}
.cuisson-note-counter.is-near-limit {
  color: var(--danger);
}
.cuisine-end-actions {
  display: flex;
  gap: 10px;
  margin-top: 24px;
}
.cuisine-end-action {
  flex: 1;
  text-align: center;
}

/* ── Utilitaires accessibilité standard ─────────────────────
   visually-hidden : caché visuellement mais lu par screen readers.
   Utilisé pour <caption> de tables, contexte ARIA, skip-links. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
.cuisine-eyebrow {
  font-size: 12px;
  color: var(--ink-muted);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-weight: 700;
}
.cuisine-step-counter {
  /* Phase 6 clamp() — mode GM (1.5× base) cassait à 36px sur petits écrans.
     Maintenant fluide : 20px min → 5vw → 32px max. Lisible Claudette 67 +
     Casey 28 sans débordement écran. */
  font-size: clamp(20px, 5vw, 32px);
  font-weight: 900;
  color: var(--ink);
  margin-top: 4px;
  line-height: 1.1;
}
.cuisine-progress {
  height: 6px;
  background: var(--paper-soft);
  border-radius: 3px;
  overflow: hidden;
  margin-bottom: 24px;
}
/* GPU-accelerated : transform: scaleX au lieu de width pour éviter
   le reflow à chaque frame. Le JS doit set --progress (0..1) au lieu
   de width %. */
.cuisine-progress-bar {
  height: 100%;
  background: var(--brand);
  transform-origin: left center;
  transform: scaleX(var(--progress, 0));
  transition: transform 0.4s cubic-bezier(0.22, 1, 0.36, 1);
  will-change: transform;
}
.cuisine-step {
  background: var(--paper-sheet);
  border: 1px solid var(--border);
  border-radius: 20px;
  padding: 32px 28px;
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 20px;
  box-shadow: var(--shadow);
}
.cuisine-step-num {
  background: var(--brand);
  color: var(--cream-fixed, #fff);
  width: 56px;
  height: 56px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 26px;
  font-weight: 900;
  flex-shrink: 0;
}
.cuisine-step-text {
  font-size: 18px;
  line-height: 1.7;
  color: var(--ink);
  font-weight: 500;
}
.cuisine-timer {
  background: var(--accent-tint);
  border-radius: 14px;
  padding: 18px;
  width: 100%;
  text-align: center;
  border: 1px solid color-mix(in oklch, var(--courge) 35%, transparent);
}
.cuisine-timer-display {
  /* Phase 6 clamp() — timer visible 10 pieds de distance en cuisine.
     Avant 42px fixe = trop petit mobile, lisibilité cassée mode GM. */
  font-size: clamp(32px, 9vw, 56px);
  font-weight: 900;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
  margin-bottom: 10px;
  letter-spacing: 0.02em;
  line-height: 1;
}
.cuisine-timer-controls {
  display: flex;
  gap: 8px;
  justify-content: center;
}
.cuisine-nav {
  display: flex;
  gap: 10px;
  margin-top: 16px;
}
.cuisine-nav button {
  flex: 1;
  padding: 16px;
  font-size: 14px;
}
.cuisine-end {
  background: var(--paper-sheet);
  border: 1px solid var(--border);
  border-radius: 20px;
  padding: 32px 28px;
}
.cuisine-feedback {
  display: flex;
  gap: 10px;
  justify-content: center;
}
.feedback-btn {
  flex: 1;
  padding: 16px 12px;
  font-size: 14px;
  border-radius: 14px;
  border: 2px solid var(--border);
  background: var(--paper-sheet);
  cursor: pointer;
  font-weight: 600;
  transition:
    transform 0.2s var(--ease-snap, ease),
    border-color 0.15s ease,
    background 0.15s ease,
    box-shadow 0.2s ease;
}
.feedback-btn span {
  font-size: 11px;
  display: block;
  margin-top: 4px;
  color: var(--ink-muted);
}
@media (hover: hover) and (pointer: fine) {
  /* Hover sobre 2026-05-10 : avant translateY(-2px) uniforme. Maintenant
   un changement de border-color = signal sans bruit, cohérent .card. */
  .feedback-btn:hover {
    border-color: var(--accent-tint2, color-mix(in oklch, var(--brand) 35%, var(--border)));
  }
}
@media (hover: hover) and (pointer: fine) {
  .feedback-yes:hover {
    border-color: var(--brand);
    background: var(--accent-tint);
  }
}
@media (hover: hover) and (pointer: fine) {
  .feedback-no:hover {
    border-color: var(--danger);
    background: var(--danger-tint);
  }
}
@media (hover: hover) and (pointer: fine) {
  .feedback-neutre:hover {
    border-color: var(--ink-muted);
    background: var(--paper-soft);
  }
}
/* Selected = signal fort par fond + border, pas par scale + shadow.
   Le scale 1.05 + shadow-md cumulés étaient un tell SaaS feedback widget. */
.feedback-btn.selected {
  background: var(--accent-tint);
  border-color: var(--accent);
}
@media (prefers-reduced-motion: reduce) {
  .feedback-btn {
    transition: none;
  }
  @media (hover: hover) and (pointer: fine) {
    .feedback-btn:hover {
      transform: none;
    }
  }
}

/* ============================================================
   DASHBOARD
   ============================================================ */
/* Budget Fantome Banner — refonte 2026-05-10 : retrait du shadow vert
   tinté (atmosphère SaaS), neutre tabac désormais. La bordure
   accent-tint suffit comme signal. */
.fantome-banner {
  background: var(--paper-sheet);
  border: 1px solid color-mix(in oklch, var(--brand) 16%, transparent);
  border-radius: var(--radius-xl);
  padding: 26px 30px;
  margin-bottom: 18px;
  position: relative;
  overflow: hidden;
  box-shadow: var(--shadow);
}
.fantome-banner::before {
  /* Blob radial-gradient retiré 2026-05-10 (war room) — atmosphère
     SaaS verte ambiante. La fantome-banner garde sa bordure accent. */
  content: none;
}
.fb-inner {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.fb-eyebrow {
  font-size: 9px;
  letter-spacing: 3px;
  text-transform: uppercase;
  color: var(--brand);
  font-weight: 700;
  margin-bottom: 6px;
}
.fb-main {
  display: flex;
  align-items: baseline;
  gap: 6px;
}
.fb-amount {
  font-family: var(--font-display);
  font-size: 56px;
  font-weight: 900;
  color: var(--ink);
  line-height: 1;
}
.fb-currency {
  font-size: 24px;
  font-weight: 700;
  color: var(--muted);
}
.fb-sub {
  font-size: 12.5px;
  color: var(--muted);
  margin-top: 8px;
  line-height: 1.6;
}
.fb-sub strong {
  color: var(--brand);
}
.fb-tags {
  display: flex;
  gap: 8px;
  margin-top: 14px;
  flex-wrap: wrap;
}
.ftag {
  font-size: 10px;
  font-weight: 600;
  padding: 5px 12px;
  border-radius: 20px;
  border: 1px solid var(--border);
  color: var(--muted);
  background: var(--bg);
}
.fb-ring {
  position: relative;
  flex-shrink: 0;
}
.fb-ring-center {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  text-align: center;
}
.fb-pct {
  font-family: var(--font-display);
  font-size: 22px;
  font-weight: 900;
  color: var(--brand);
}
.fb-plbl {
  font-size: 9px;
  color: var(--muted);
  letter-spacing: 1px;
  text-transform: uppercase;
}

/* KPI Strip */
.kpi-strip {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 12px;
  margin-bottom: 18px;
}
.kpi {
  background: var(--paper);
  border: 1px solid var(--border);
  border-radius: 18px;
  padding: 16px 18px;
  box-shadow: var(--shadow);
  position: relative;
  overflow: hidden;
  transition:
    transform 0.22s,
    opacity 0.22s,
    color 0.22s,
    background 0.22s,
    border-color 0.22s,
    box-shadow 0.22s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}
@media (hover: hover) and (pointer: fine) {
  /* Hover Linear-style cohérent .card / .feedback-btn — border-color
   uniquement, pas de translateY. */
  .kpi:hover {
    border-color: var(--accent-tint2, color-mix(in oklch, var(--brand) 30%, var(--border)));
  }
}
.kpi::after {
  content: "";
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  height: 3px;
  border-radius: 0 0 18px 18px;
}
/* KPI accent bars — mono-accent Vert Jean-Talon strict (v2 direction) */
.kpi.k1::after,
.kpi.k2::after,
.kpi.k3::after,
.kpi.k4::after {
  background: var(--accent);
}
.kpi-ico {
  font-size: 18px;
  margin-bottom: 8px;
}
.kpi-val {
  font-family: var(--font-display);
  font-size: 26px;
  font-weight: 900;
  line-height: 1;
}
/* KPI val — mono-accent v2 : tous en ink solide, pas de color coding */
.kpi.k1 .kpi-val,
.kpi.k2 .kpi-val,
.kpi.k3 .kpi-val,
.kpi.k4 .kpi-val {
  color: var(--ink);
}
.kpi-lbl {
  font-size: 11px;
  color: var(--muted);
  margin-top: 4px;
}
.kpi-delta {
  font-size: 10px;
  color: var(--green);
  margin-top: 5px;
  font-weight: 600;
}
.dgrid {
  display: grid;
  grid-template-columns: 1.5fr 1fr;
  gap: 14px;
}
.dgrid3 {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 14px;
}

/* ── REPAS + SOLDES ─────────────────────────────────────────── */
.ri {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 11px 12px;
  border-radius: 12px;
  background: var(--paper);
  border: 1px solid var(--border2);
  cursor: pointer;
  transition:
    transform 0.2s,
    opacity 0.2s,
    color 0.2s,
    background 0.2s,
    border-color 0.2s,
    box-shadow 0.2s;
  margin-bottom: 7px;
}
.ri:last-child {
  margin-bottom: 0;
}
@media (hover: hover) and (pointer: fine) {
  .ri:hover {
    background: var(--brand-pale);
    border-color: oklch(0.59 0.16 143 / 0.16);
  }
}
.ri-emo {
  width: 40px;
  height: 40px;
  border-radius: var(--radius-sm);
  background: var(--bg);
  border: 1px solid var(--border);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 21px;
  flex-shrink: 0;
}
.ri-name {
  font-size: 13px;
  font-weight: 600;
  color: var(--ink);
}
.ri-detail {
  font-size: 11px;
  color: var(--muted);
  margin-top: 2px;
}
.ri-speed {
  font-size: 9px;
  background: var(--green-pale);
  color: var(--green);
  padding: 2px 6px;
  border-radius: 4px;
  font-weight: 700;
  margin-left: 4px;
}
.ri-price {
  font-family: var(--font-display);
  font-size: 15px;
  font-weight: 700;
  color: var(--brand);
  margin-left: auto;
  flex-shrink: 0;
}
.ri-price.free {
  color: var(--green);
}

/* Soldes items */
.si {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 11px;
  border-radius: var(--radius-sm);
  background: var(--paper);
  border: 1px solid var(--border2);
  margin-bottom: 6px;
  transition:
    transform 0.2s,
    opacity 0.2s,
    color 0.2s,
    background 0.2s,
    border-color 0.2s,
    box-shadow 0.2s;
}
.si:last-child {
  margin-bottom: 0;
}
@media (hover: hover) and (pointer: fine) {
  .si:hover {
    background: var(--brand-pale);
  }
}
.st {
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  padding: 3px 7px;
  border-radius: 4px;
  flex-shrink: 0;
}
.st-maxi,
.st-maxi-groceries {
  background: oklch(0.52 0.1 220 / 0.14);
  color: var(--blue);
}
.st-super-c {
  background: oklch(0.62 0.14 68 / 0.12);
  color: var(--amber);
}
.st-iga {
  background: oklch(0.44 0.14 25 / 0.12);
  color: var(--red);
}
.st-metro {
  background: var(--green-pale);
  color: var(--green);
}
.si-nom {
  flex: 1;
  font-size: 12px;
  color: var(--ink);
}
.si-p {
  font-family: var(--font-display);
  font-size: 13px;
  font-weight: 700;
  color: var(--green);
}
.si-r {
  font-size: 10px;
  color: var(--muted2);
  text-decoration: line-through;
}
.si-pct {
  font-size: 9px;
  font-weight: 700;
  background: var(--green-pale);
  color: var(--green);
  padding: 2px 5px;
  border-radius: 3px;
}

/* ── PREDICTIONS + SCORE ────────────────────────────────────── */
.pred-card {
  background: var(--paper);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 16px;
  position: relative;
  overflow: hidden;
  box-shadow: var(--shadow);
}
.pred-card::before {
  /* Blob radial-gradient retiré 2026-05-10 (war room) — pred-card. */
  content: none;
}
.pred-title {
  font-size: 10px;
  letter-spacing: 2px;
  text-transform: uppercase;
  color: var(--brand);
  margin-bottom: 8px;
  font-weight: 700;
}
.pred-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 0;
  border-bottom: 1px solid var(--border);
  font-size: 12px;
  color: var(--ink);
}
.pred-item:last-child {
  border: none;
}
.pred-ico {
  font-size: 16px;
  width: 20px;
  text-align: center;
}
.pred-info {
  flex: 1;
}
.pred-prod {
  color: var(--ink);
  font-weight: 500;
}
.pred-timing {
  font-size: 10px;
  color: var(--muted);
  margin-top: 1px;
}
.pred-action {
  font-size: 10px;
  font-weight: 700;
  padding: 3px 9px;
  border-radius: 20px;
}
.pred-action.wait {
  background: var(--brand-pale);
  color: var(--brand-dark);
}
.pred-action.buy {
  background: var(--green-pale);
  color: var(--brand-dark);
}

.score-card {
  background: linear-gradient(135deg, var(--violette-tint), oklch(0.93 0.035 295));
  border: 1px solid oklch(0.52 0.13 325 / 0.16);
  border-radius: var(--radius);
  padding: 16px;
  text-align: center;
}
.sc-lbl {
  font-size: 9px;
  letter-spacing: 2px;
  text-transform: uppercase;
  color: var(--violet);
  margin-bottom: 6px;
  font-weight: 600;
}
.sc-pct {
  font-family: var(--font-display);
  font-size: 42px;
  font-weight: 900;
  color: var(--violet);
  line-height: 1;
}
.sc-desc {
  font-size: 11px;
  color: var(--muted);
  margin-top: 5px;
}
.sc-trophy {
  font-size: 28px;
  margin-bottom: 6px;
}

/* ── DETECTIVE ──────────────────────────────────────────────── */
.detective-alert {
  background: oklch(0.62 0.14 68 / 0.1);
  border: 1px solid oklch(0.62 0.14 68 / 0.22);
  border-radius: var(--radius);
  padding: 14px 16px;
  display: flex;
  align-items: flex-start;
  gap: 12px;
}

/* ============================================================
   GARDE-MANGER
   ============================================================ */
.pantry-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 10px;
}
.pantry-item {
  background: var(--paper);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 14px;
  text-align: center;
  transition:
    transform 0.2s,
    opacity 0.2s,
    color 0.2s,
    background 0.2s,
    border-color 0.2s,
    box-shadow 0.2s;
}
@media (hover: hover) and (pointer: fine) {
  .pantry-item:hover {
    transform: translateY(-2px);
    box-shadow: var(--shadow-md);
  }
}
.pi-emo {
  font-size: 28px;
  margin-bottom: 6px;
}
.pi-name {
  font-size: 12px;
  font-weight: 600;
  color: var(--ink);
}
.pi-qty {
  font-size: 11px;
  color: var(--muted);
  margin-top: 2px;
}
.pi-expire {
  font-size: 10px;
  font-weight: 700;
  margin-top: 6px;
  padding: 2px 8px;
  border-radius: 10px;
  display: inline-block;
}
.exp-ok {
  background: var(--green-pale);
  color: var(--green);
}
.exp-warn {
  background: oklch(0.62 0.14 68 / 0.12);
  color: var(--amber);
}
.exp-urgent {
  background: oklch(0.44 0.14 25 / 0.1);
  color: var(--red);
}

/* ── BADGES ─────────────────────────────────────────────────── */
.badges-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 10px;
}
.bdg {
  background: var(--paper);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 14px;
  text-align: center;
  transition:
    transform 0.2s,
    opacity 0.2s,
    color 0.2s,
    background 0.2s,
    border-color 0.2s,
    box-shadow 0.2s;
  box-shadow: var(--shadow);
}
@media (hover: hover) and (pointer: fine) {
  .bdg:hover {
    transform: translateY(-2px);
    box-shadow: var(--shadow-md);
  }
}
.bdg.locked {
  opacity: 0.3;
  filter: grayscale(1);
}
@media (hover: hover) and (pointer: fine) {
  .bdg.locked:hover {
    transform: none;
    box-shadow: var(--shadow);
  }
}
.bdg-ico {
  font-size: 26px;
  margin-bottom: 7px;
}
.bdg-name {
  font-size: 12px;
  font-weight: 700;
  color: var(--ink);
}
.bdg-desc {
  font-size: 10px;
  color: var(--muted);
  margin-top: 2px;
}

/* ============================================================
   MENU
   ============================================================ */
.day-strip {
  display: flex;
  gap: 7px;
  margin-bottom: 20px;
}
.dc {
  flex: 1;
  padding: 10px 6px;
  border-radius: 12px;
  text-align: center;
  cursor: pointer;
  background: var(--paper);
  border: 1px solid var(--border);
  transition:
    transform 0.2s,
    opacity 0.2s,
    color 0.2s,
    background 0.2s,
    border-color 0.2s,
    box-shadow 0.2s;
  box-shadow: var(--shadow);
}
@media (hover: hover) and (pointer: fine) {
  .dc:hover {
    border-color: oklch(0.59 0.16 143 / 0.26);
  }
}
.dc.sel {
  background: var(--brand);
  border-color: var(--brand);
  box-shadow: 0 4px 16px oklch(0.59 0.16 143 / 0.28);
}
.dn {
  font-size: 9px;
  text-transform: uppercase;
  letter-spacing: 0.8px;
  color: var(--muted);
}
.dd {
  font-family: var(--font-display);
  font-size: 17px;
  font-weight: 900;
  color: var(--ink);
}
.de {
  font-size: 16px;
  margin-top: 2px;
}
.dc.sel .dn,
.dc.sel .dd {
  color: var(--cream-fixed);
}

.menu-grid {
  display: grid;
  grid-template-columns: 1.3fr 1fr;
  gap: 14px;
}

/* Recipe panel */
.recipe-panel {
  background: var(--paper);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow-md);
}
/* Bandeau allergies cross-membre 2026-05-09 (Phase 2 P0 ABSOLU) :
   Marie ne reviendra JAMAIS si on propose arachides à Lou.
   Bandeau rouge intense, role="alert" pour screen readers,
   bouton CTA « Remplacer » bien visible. Pattern : danger-tint
   bg + danger border + danger ink. Pas de gradient (BAN 1). */
.recipe-alert-allergie {
  display: flex;
  align-items: flex-start;
  gap: 14px;
  margin: 16px 0 24px;
  padding: 16px 20px;
  background: color-mix(in oklch, var(--danger, #c92a3e) 8%, var(--paper));
  border: 1.5px solid color-mix(in oklch, var(--danger, #c92a3e) 50%, transparent);
  border-radius: 12px;
}
.recipe-alert-allergie-icon {
  flex-shrink: 0;
  font-size: 24px;
  line-height: 1;
  margin-top: 2px;
}
.recipe-alert-allergie-body {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-width: 0;
}
.recipe-alert-allergie-title {
  font-family: var(--font-display, var(--font-body));
  font-size: 18px;
  font-weight: 400;
  color: var(--danger, #c92a3e);
  letter-spacing: -0.005em;
  line-height: 1.3;
}
.recipe-alert-allergie-list {
  margin: 0;
  padding-left: 18px;
  font-size: 13px;
  line-height: 1.55;
  color: var(--ink);
}
.recipe-alert-allergie-list li {
  margin-bottom: 4px;
}
.recipe-alert-allergie-list li:last-child {
  margin-bottom: 0;
}
.recipe-alert-allergie-list strong {
  color: var(--danger, #c92a3e);
}
.recipe-alert-allergie-action {
  margin-top: 8px;
}
.recipe-alert-allergie-action .btn-main {
  background: var(--danger, #c92a3e);
}
@media (hover: hover) and (pointer: fine) {
  .recipe-alert-allergie-action .btn-main:hover {
    filter: brightness(1.08);
  }
}

/* Flag allergie compact dans menu/index card (Phase 2) :
   pas un bandeau pleine largeur (la card est déjà compacte),
   juste un indicateur ⚠️ rouge cliquable qui pointe vers la
   recette détail où le bandeau complet s'affiche. */
.menu-day-allergie-flag {
  display: inline-block;
  margin-top: 4px;
  padding: 2px 8px;
  background: color-mix(in oklch, var(--danger, #c92a3e) 12%, var(--paper));
  border: 1px solid color-mix(in oklch, var(--danger, #c92a3e) 35%, transparent);
  border-radius: 6px;
  font-size: 11px;
  font-weight: 600;
  color: var(--danger, #c92a3e);
  letter-spacing: 0;
}

.recipe-cover {
  height: 160px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 64px;
  position: relative;
  background: var(--paper-sheet);
  border-top: 2px solid var(--brand);
}
.recipe-cover-detail {
  min-height: 240px;
  position: relative;
  overflow: hidden;
}
.recipe-cover-detail::before {
  content: "É";
  position: absolute;
  right: clamp(-30px, -4vw, -12px);
  bottom: clamp(-70px, -8vw, -30px);
  font-family: var(--font-display);
  font-style: italic;
  font-size: clamp(220px, 36vw, 360px);
  line-height: 0.85;
  color: var(--brand);
  opacity: 0.08;
  pointer-events: none;
  user-select: none;
  letter-spacing: -0.04em;
  z-index: 0;
}
.recipe-cover-emoji {
  font-size: 72px;
  position: relative;
  z-index: 1;
  filter: drop-shadow(0 2px 6px oklch(0.2 0.02 110 / 0.2));
}
.recipe-chip {
  position: absolute;
  z-index: 2;
  font-size: 10px;
  font-weight: 700;
  padding: 5px 12px;
  border-radius: 980px;
  background: var(--brand);
  color: var(--cream-fixed);
  letter-spacing: 0.02em;
}
.recipe-chip-meteo {
  top: 12px;
  left: 12px;
  background: var(--accent);
}
.recipe-chip-pantry {
  bottom: 12px;
  left: 12px;
  background: var(--accent-deep);
}
.recipe-price {
  font-family: var(--font-numeric);
  font-size: 14px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  font-feature-settings:
    "tnum" 1,
    "lnum" 1;
}
.recipe-price-solde {
  color: var(--accent);
}
.recipe-price-est {
  color: var(--ink-muted);
  font-weight: 600;
}
.recipe-price-tag {
  font-size: 9px;
  color: var(--ink-fade);
  font-weight: 600;
  margin-left: 2px;
}
.recipe-section-h {
  margin: 24px 0 10px;
}
.recipe-tip-card {
  background: var(--accent-tint);
  border: 1px solid color-mix(in oklch, var(--accent) 25%, transparent);
  border-radius: 14px;
  padding: 18px;
}
.recipe-tip-list {
  margin: 0;
  padding-left: 20px;
  font-size: 13px;
  line-height: 1.8;
  color: var(--ink);
}
.recipe-tip-list li {
  margin-bottom: 8px;
}
.recipe-tip-list li:last-child {
  margin-bottom: 0;
}

/* Nutrition grid — mono-accent, pas de macro color-coding : hiérarchie
   via typo (serif display pour le chiffre, caps track wide pour le label). */
.recipe-nutri-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
  gap: 8px;
}
.recipe-nutri-cell {
  background: var(--paper-soft);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 14px 12px;
  text-align: center;
}
.recipe-nutri-num {
  font-family: var(--font-display);
  font-size: 24px;
  font-weight: 400;
  line-height: 1;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
  margin-bottom: 6px;
}
.recipe-nutri-unit {
  font-size: 13px;
  color: var(--ink-muted);
  margin-left: 1px;
}
.recipe-nutri-lbl {
  font-size: 10px;
  color: var(--ink-muted);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-weight: 600;
}

/* Substitutions, accompagnements, pantry-note — tokens + mono-accent */
.recipe-sub-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.recipe-sub-row {
  background: var(--paper-soft);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 12px 14px;
  font-size: 13px;
  line-height: 1.5;
}
.recipe-sub-row strong {
  color: var(--ink);
  font-weight: 600;
}
.recipe-sub-arrow {
  color: var(--ink-muted);
  margin: 0 6px;
}
.recipe-sub-alt {
  color: var(--ink-soft);
}
.recipe-acc-list {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.recipe-acc-pill {
  background: var(--accent-tint);
  color: var(--accent-deep);
  font-size: 12px;
  padding: 7px 14px;
  border-radius: 980px;
  font-weight: 500;
}
.recipe-pantry-note {
  background: var(--accent-tint);
  border: 1px solid color-mix(in oklch, var(--accent) 22%, transparent);
  border-radius: 10px;
  padding: 12px 14px;
  font-size: 13px;
  color: var(--accent-deep);
  margin-top: 10px;
  line-height: 1.5;
}
.recipe-pantry-note strong {
  color: var(--accent-deep);
  font-weight: 700;
}
.recipe-badge {
  position: absolute;
  top: 12px;
  right: 12px;
  font-size: 10px;
  font-weight: 700;
  padding: 4px 12px;
  border-radius: 20px;
  background: var(--brand);
  color: var(--cream-fixed);
}
.recipe-speed {
  position: absolute;
  top: 12px;
  left: 12px;
  font-size: 10px;
  font-weight: 700;
  padding: 4px 12px;
  border-radius: 20px;
  background: var(--green);
  color: var(--cream-fixed);
}
.recipe-body {
  padding: 18px;
}
.recipe-title {
  font-family: var(--font-display);
  font-size: 20px;
  font-weight: 900;
  color: var(--ink);
  margin-bottom: 10px;
  line-height: 1.2;
}
.rmeta {
  display: flex;
  gap: 14px;
  margin-bottom: 16px;
  flex-wrap: wrap;
  align-items: center;
}
.rm {
  font-size: 11px;
  color: var(--muted);
}
.rm strong {
  color: var(--ink);
  font-weight: 600;
}
.rm-portions {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.rm-portion-btn {
  width: 28px;
  height: 28px;
  min-width: 28px;
  border: 1px solid var(--border);
  background: var(--paper);
  border-radius: 50%;
  color: var(--ink);
  font-size: 16px;
  line-height: 1;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition:
    background 0.12s,
    border-color 0.12s;
  -webkit-tap-highlight-color: transparent;
}
@media (hover: hover) and (pointer: fine) {
  .rm-portion-btn:hover {
    background: var(--accent-tint);
    border-color: var(--brand-dark);
  }
}
.rm-portion-btn:active {
  background: var(--brand-dark);
  color: var(--paper);
}
.rm-portion-btn:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px rgba(26, 138, 74, 0.35);
}
@media (max-width: 900px) {
  .rm-portion-btn {
    width: 44px;
    height: 44px;
    min-width: 44px;
    font-size: 18px;
  }
}
.recipe-startat {
  font-size: 12px;
  color: var(--ink2);
  background: var(--accent-tint);
  border: 1px solid rgba(26, 138, 74, 0.22);
  padding: 8px 12px;
  border-radius: 8px;
  margin: 0 0 14px 0;
}
.recipe-startat strong {
  color: var(--brand-dark);
  font-weight: 700;
}

/* Substitutions IA Phase 3 P3-4 */
.ing-subst-btn {
  background: transparent;
  border: 1px dashed var(--border);
  color: var(--muted);
  font-size: 10px;
  padding: 3px 8px;
  border-radius: 999px;
  margin-left: 8px;
  cursor: pointer;
  font-family: inherit;
  transition:
    background 0.12s,
    color 0.12s,
    border-color 0.12s;
}
@media (hover: hover) and (pointer: fine) {
  .ing-subst-btn:hover {
    background: var(--accent-tint);
    color: var(--brand-dark);
    border-color: var(--brand-dark);
    border-style: solid;
  }
}
.ing-subst-btn:disabled {
  opacity: 0.5;
  cursor: wait;
}
.ing-subst-result {
  background: var(--paper-soft, var(--accent-tint));
  border: 1px solid rgba(26, 138, 74, 0.22);
  border-radius: 10px;
  padding: 12px 14px;
  margin: 4px 0 10px 0;
  font-size: 12px;
  color: var(--ink2);
  animation: ing-subst-fade 0.18s ease-out;
}
@keyframes ing-subst-fade {
  from {
    opacity: 0;
    transform: translateY(-4px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}
.ing-subst-title {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 1.2px;
  color: var(--brand-dark);
  font-weight: 700;
  margin-bottom: 8px;
}
.ing-subst-item {
  padding: 6px 0;
  border-bottom: 1px solid rgba(26, 138, 74, 0.1);
}
.ing-subst-item:last-child {
  border-bottom: none;
  padding-bottom: 0;
}
.ing-subst-item strong {
  color: var(--ink);
  font-weight: 700;
}
.ing-subst-prop {
  color: var(--muted);
  font-size: 11px;
}
.ing-subst-note {
  font-size: 11px;
  color: var(--muted);
  margin-top: 4px;
  line-height: 1.5;
}
.ing-subst-empty {
  font-size: 12px;
  color: var(--muted);
  margin: 0;
  font-style: italic;
}
@media (max-width: 900px) {
  /* WCAG 2.5.5 (AAA) : touch target 44×44 minimum sur mobile.
     Avant : 28px ; Marie 42 doigt sur cuisinière chaude ratait la
     cible. Padding et font-size légèrement bumpés pour cohérence. */
  .ing-subst-btn {
    padding: 10px 14px;
    font-size: 12px;
    min-height: 44px;
  }
}

/* Phase 3 P3-5 : Tes essentiels habituels + extras */
.essentiels-card {
  margin-top: 18px;
}
.essentiels-intro {
  font-size: 12.5px;
  color: var(--muted);
  margin: 4px 0 14px 0;
  line-height: 1.5;
}
.essentiels-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.essentiels-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  padding: 10px 12px;
  background: var(--paper-soft, var(--accent-tint));
  border: 1px solid var(--border);
  border-radius: 10px;
}
.essentiels-meta {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
  flex: 1;
}
.essentiels-meta strong {
  color: var(--ink);
  font-weight: 700;
  font-size: 13px;
}
.essentiels-freq {
  font-size: 11px;
  color: var(--muted);
}
.essentiels-form {
  margin: 0;
}
.essentiels-btn {
  padding: 11px 14px;
  font-size: 12px;
  min-height: 44px;
  white-space: nowrap;
}
.extras-card {
  margin-top: 18px;
}
.extras-list {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
@media (max-width: 900px) {
  .essentiels-item {
    flex-direction: column;
    align-items: stretch;
  }
  .essentiels-btn {
    width: 100%;
    min-height: 44px;
  }
}

/* Phase 4 P4-1 : Bundle Réception */
.ev-bundle-credit {
  background: var(--accent-tint);
  border: 1px solid rgba(26, 138, 74, 0.22);
  padding: 10px 14px;
  border-radius: 8px;
  margin: 10px 0;
  font-size: 13px;
  color: var(--ink2);
}
.ev-bundle-credit strong {
  color: var(--brand-dark);
  font-weight: 700;
}
.ev-bundle-card {
  background: var(--paper);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 24px 28px;
  box-shadow: var(--shadow);
  text-align: center;
}
.ev-bundle-eyebrow {
  font-family: var(--font-display);
  font-size: 11px;
  letter-spacing: 2.4px;
  text-transform: uppercase;
  color: var(--brand-dark);
  font-weight: 700;
  margin-bottom: 8px;
}
.ev-bundle-title {
  font-family: var(--font-display);
  font-size: 22px;
  margin: 0 0 12px 0;
  color: var(--ink);
  font-weight: 800;
  line-height: 1.25;
}
.ev-bundle-title strong {
  color: var(--brand-dark);
  font-weight: 900;
}
.ev-bundle-sub {
  font-size: 14px;
  color: var(--ink2);
  line-height: 1.65;
  max-width: 540px;
  margin: 0 auto 18px auto;
}
.ev-bundle-fineprint {
  font-size: 11.5px;
  color: var(--muted);
  margin: 12px 0 0 0;
}

/* Phase 4 P4-4 : Templates saisonniers QC */
.ev-templates {
  background: var(--paper);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 24px 26px;
  margin: 16px 0 28px 0;
}
.ev-templates-title {
  font-family: var(--font-display);
  font-size: 18px;
  font-weight: 800;
  color: var(--ink);
  margin: 0 0 4px 0;
}
.ev-templates-sub {
  font-size: 13px;
  color: var(--muted);
  margin: 0 0 18px 0;
}
.ev-templates-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: 10px;
}
.ev-template-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  padding: 16px 10px;
  background: var(--paper-soft, var(--accent-tint));
  border: 1px solid var(--border);
  border-radius: 12px;
  font-family: inherit;
  cursor: pointer;
  text-align: center;
  transition:
    background 0.15s,
    border-color 0.15s,
    transform 0.12s;
  min-height: 92px;
}
/* Phase 8 — alternance subtile des templates saisonniers pour
   rompre le « list dump » uniforme. 4 teintes rotatives qui
   restent dans la palette brand (vert tint + cream variations).
   L'identité saisonnière sort enfin visuellement. */
.ev-template-card:nth-child(4n + 1) {
  background: var(--accent-tint);
}
.ev-template-card:nth-child(4n + 2) {
  background: var(--paper-soft);
}
.ev-template-card:nth-child(4n + 3) {
  background: var(--paper-sheet);
  border-color: var(--brand);
  border-style: dashed;
}
.ev-template-card:nth-child(4n + 4) {
  background: var(--accent-tint);
  border-color: color-mix(in oklch, var(--brand) 40%, var(--border));
}
@media (hover: hover) and (pointer: fine) {
  .ev-template-card:hover {
    background: var(--accent-tint);
    border-color: var(--brand-dark);
    transform: translateY(-1px);
  }
}
.ev-template-card.is-selected {
  background: var(--brand-dark);
  color: var(--paper);
  border-color: var(--brand-dark);
}
.ev-template-card.is-selected .ev-template-titre {
  color: var(--paper);
}
.ev-template-icon {
  font-size: 24px;
  line-height: 1;
}
.ev-template-titre {
  font-size: 12px;
  font-weight: 700;
  color: var(--ink);
  line-height: 1.3;
}
@media (max-width: 900px) {
  .ev-templates-grid {
    grid-template-columns: repeat(2, 1fr);
  }
  .ev-template-card {
    min-height: 100px;
  }
}

/* Phase 4 P4-5 : Lien partage allergies invités */
.ev-share-allergies {
  margin: 18px 0 28px 0;
  background: var(--paper-soft, var(--accent-tint));
  border: 1px solid var(--border);
  border-radius: 12px;
}
.ev-share-summary {
  list-style: none;
  cursor: pointer;
  padding: 14px 18px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  font-size: 13.5px;
  color: var(--ink);
  font-weight: 600;
  -webkit-tap-highlight-color: transparent;
}
.ev-share-summary::-webkit-details-marker {
  display: none;
}
.ev-share-summary-cta {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 1.5px;
  color: var(--brand-dark);
  font-weight: 700;
}
.ev-share-allergies[open] .ev-share-summary {
  border-bottom: 1px solid var(--border);
}
.ev-share-body {
  padding: 16px 18px 18px 18px;
}
.ev-share-intro {
  font-size: 13px;
  color: var(--ink2);
  margin: 0 0 12px 0;
  line-height: 1.6;
}
.ev-share-link-wrap {
  display: flex;
  gap: 8px;
  margin: 12px 0;
}
.ev-share-link-wrap input {
  flex: 1;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--paper);
  font-family: ui-monospace, monospace;
  font-size: 12px;
  color: var(--ink);
  min-height: 44px;
}
.ev-share-link-wrap button {
  white-space: nowrap;
  min-height: 44px;
}
.ev-share-status {
  background: var(--accent-tint);
  border: 1px solid rgba(26, 138, 74, 0.22);
  padding: 10px 12px;
  border-radius: 8px;
  font-size: 12.5px;
  color: var(--ink2);
  margin: 8px 0 0 0;
}
.ev-share-status strong {
  color: var(--brand-dark);
}
@media (max-width: 640px) {
  .ev-share-link-wrap {
    flex-direction: column;
  }
  .ev-share-link-wrap button {
    width: 100%;
  }
}
.ing-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 8px 0;
  border-bottom: 1px solid var(--border2);
  font-size: 12.5px;
}
.ing-row:last-child {
  border: none;
}
.pantry-tag {
  font-size: 9px;
  background: var(--green-pale);
  color: var(--green);
  padding: 2px 6px;
  border-radius: 4px;
  font-weight: 700;
}
.expire-tag {
  font-size: 9px;
  background: oklch(0.44 0.14 25 / 0.1);
  color: var(--red);
  padding: 2px 6px;
  border-radius: 4px;
  font-weight: 700;
}

/* Shopping list */
.lp {
  background: var(--paper);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 18px;
  box-shadow: var(--shadow);
}
.ls {
  margin-bottom: 14px;
}
.ls-title {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 1.5px;
  color: var(--muted);
  margin-bottom: 8px;
  font-weight: 600;
}
.li {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 0;
  border-bottom: 1px solid var(--border2);
  font-size: 12.5px;
}
.li:last-child {
  border: none;
}
.chk {
  width: 18px;
  height: 18px;
  border-radius: 5px;
  border: 2px solid var(--muted2);
  flex-shrink: 0;
  cursor: pointer;
  transition:
    transform 0.18s,
    opacity 0.18s,
    color 0.18s,
    background 0.18s,
    border-color 0.18s,
    box-shadow 0.18s;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 10px;
}
.chk.on {
  background: var(--brand);
  border-color: var(--brand);
  color: var(--cream-fixed);
}
.li-n {
  flex: 1;
  color: var(--ink);
}
.li-n.done {
  text-decoration: line-through;
  color: var(--muted2);
}
.li-q {
  font-size: 11px;
  color: var(--muted);
}

/* ============================================================
   URGENCE
   ============================================================ */
.urgence-hero {
  background: linear-gradient(135deg, var(--danger), oklch(0.58 0.16 25));
  border-radius: var(--radius-xl);
  padding: 24px 28px;
  margin-bottom: 18px;
  color: var(--cream-fixed);
  box-shadow: 0 8px 32px oklch(0.44 0.14 25 / 0.25);
}
.uh-top {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 16px;
}
.uh-clock {
  font-size: 32px;
}
.urgence-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 12px;
}
.ug-card {
  background: color-mix(in oklch, var(--cream-fixed) 15%, transparent);
  border-radius: var(--radius);
  padding: 14px;
  border: 1px solid color-mix(in oklch, var(--cream-fixed) 20%, transparent);
  cursor: pointer;
  transition:
    transform 0.2s,
    opacity 0.2s,
    color 0.2s,
    background 0.2s,
    border-color 0.2s,
    box-shadow 0.2s;
}
@media (hover: hover) and (pointer: fine) {
  .ug-card:hover {
    background: color-mix(in oklch, var(--cream-fixed) 25%, transparent);
    transform: translateY(-2px);
  }
}
.ug-emo {
  font-size: 28px;
  margin-bottom: 8px;
}
.ug-name {
  font-size: 13px;
  font-weight: 700;
  color: var(--cream-fixed);
  margin-bottom: 4px;
}
.ug-time {
  font-size: 11px;
  color: var(--cream-fixed-soft);
}
.ug-badge {
  display: inline-block;
  margin-top: 6px;
  font-size: 9px;
  font-weight: 700;
  padding: 2px 8px;
  border-radius: 10px;
  background: color-mix(in oklch, var(--cream-fixed) 20%, transparent);
  color: var(--cream-fixed);
}
.ug-expire {
  color: var(--paille);
  font-size: 10px;
  margin-top: 4px;
  font-weight: 600;
}

/* ============================================================
   RECU (Receipt)
   ============================================================ */
.scan-zone {
  border: 2px dashed oklch(0.59 0.16 143 / 0.28);
  border-radius: var(--radius-lg);
  padding: 48px;
  text-align: center;
  background: var(--brand-pale);
  cursor: pointer;
  transition:
    transform 0.2s,
    opacity 0.2s,
    color 0.2s,
    background 0.2s,
    border-color 0.2s,
    box-shadow 0.2s;
  margin-bottom: 20px;
}
@media (hover: hover) and (pointer: fine) {
  .scan-zone:hover {
    border-color: var(--brand);
    background: oklch(0.59 0.16 143 / 0.12);
  }
}
.sz-ico {
  font-size: 48px;
  margin-bottom: 12px;
}
.sz-title {
  font-family: var(--font-display);
  font-size: 20px;
  font-weight: 900;
  color: var(--ink);
  margin-bottom: 5px;
}
.sz-sub {
  font-size: 12px;
  color: var(--muted);
}
.rc {
  background: var(--paper);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 22px;
  box-shadow: var(--shadow-md);
}
.rc-hd {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  margin-bottom: 18px;
}
.rc-store {
  font-family: var(--font-display);
  font-size: 18px;
  font-weight: 900;
  color: var(--ink);
}
.rc-date {
  font-size: 11px;
  color: var(--muted);
  margin-top: 3px;
}
.rc-total {
  font-family: var(--font-display);
  font-size: 32px;
  font-weight: 900;
  color: var(--ink);
  text-align: right;
}
.rc-save {
  font-size: 12px;
  color: var(--green);
  margin-top: 3px;
  font-weight: 700;
}
.cmp-row {
  display: flex;
  gap: 10px;
  margin-bottom: 16px;
}
.cmp {
  flex: 1;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 14px;
  text-align: center;
}
.cmp-v {
  font-family: var(--font-display);
  font-size: 22px;
  font-weight: 900;
}
.cmp-v.g {
  color: var(--green);
}
.cmp-v.r {
  color: var(--red);
}
.cmp-l {
  font-size: 10px;
  color: var(--muted);
  margin-top: 4px;
}
.ai-insight {
  background: var(--brand-pale);
  border: 1px solid oklch(0.59 0.16 143 / 0.14);
  border-radius: 12px;
  padding: 14px;
}
.ai-t {
  font-size: 12px;
  font-weight: 700;
  color: var(--brand);
  margin-bottom: 5px;
  display: flex;
  align-items: center;
  gap: 6px;
}
.ai-b {
  font-size: 12.5px;
  color: var(--ink2);
  line-height: 1.6;
}

/* ============================================================
   VOTE
   ============================================================ */
.vote-banner {
  background: oklch(0.62 0.14 68 / 0.1);
  border: 1px solid oklch(0.62 0.14 68 / 0.18);
  border-radius: var(--radius);
  padding: 15px 18px;
  display: flex;
  align-items: center;
  gap: 14px;
  margin-bottom: 18px;
}
.vc {
  background: var(--paper);
  border: 1px solid var(--border);
  border-radius: 16px;
  padding: 18px;
  margin-bottom: 12px;
  box-shadow: var(--shadow);
  transition:
    transform 0.2s,
    opacity 0.2s,
    color 0.2s,
    background 0.2s,
    border-color 0.2s,
    box-shadow 0.2s;
}
@media (hover: hover) and (pointer: fine) {
  .vc:hover {
    box-shadow: var(--shadow-md);
  }
}
.vt {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-bottom: 12px;
}
.ve {
  font-size: 34px;
}
.vn {
  font-family: var(--font-display);
  font-size: 15px;
  font-weight: 900;
  color: var(--ink);
}
.vm {
  font-size: 11px;
  color: var(--muted);
  margin-top: 3px;
}
.vmembers {
  display: flex;
  gap: 8px;
  margin-bottom: 11px;
}
.mv {
  display: flex;
  align-items: center;
  gap: 4px;
}
.mav {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 10px;
  font-weight: 700;
  color: var(--cream-fixed);
  background: var(--brand);
}
.mvi {
  font-size: 11px;
}
.vbar {
  height: 5px;
  background: var(--bg);
  border-radius: 3px;
  overflow: hidden;
  border: 1px solid var(--border);
}
.vfill {
  height: 100%;
  border-radius: 3px;
  background: linear-gradient(90deg, var(--brand), var(--brand-light));
}
.vfill.low {
  background: linear-gradient(90deg, var(--danger), oklch(0.58 0.16 25));
}
.vscores {
  display: flex;
  justify-content: space-between;
  font-size: 10px;
  color: var(--muted);
  margin-top: 5px;
}

/* ============================================================
   EPARGNE (Savings)
   ============================================================ */
.fantome-big {
  background: var(--paper-sheet);
  border: 1px solid oklch(0.59 0.16 143 / 0.16);
  border-radius: var(--radius-xl);
  padding: 28px 32px;
  margin-bottom: 18px;
  position: relative;
  overflow: hidden;
  box-shadow: var(--shadow-md);
}
.fantome-big::before {
  /* Blob radial-gradient retiré 2026-05-10 (war room) — fantome-big. */
  content: none;
}
/* .fb2-* block supprimé 2026-06-04 (audit sévère) — dead code, aucune
   vue ne consommait .fb2-big / .fb2-stats / .fb2-sv. Le pattern hero-
   metric (72px font + grid 3-col stats) flaggé par /impeccable disparaît
   avec le code. La Budget Fantôme live utilise .fb-* (56px + ring chart). */

/* Charts */
.chart-card {
  background: var(--paper);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 20px;
  margin-bottom: 14px;
  box-shadow: var(--shadow);
}
.bars-wrap {
  display: flex;
  align-items: flex-end;
  gap: 10px;
  height: 90px;
  margin-top: 14px;
}
.bc {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
}
.b-track {
  position: relative;
  width: 100%;
}
.b-bud {
  width: 100%;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 5px 5px 0 0;
}
.b-real {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  border-radius: 5px 5px 0 0;
  background: linear-gradient(180deg, var(--brand), var(--brand-light));
}
.b-lbl {
  font-size: 9px;
  color: var(--muted2);
}

/* ── PILLS ──────────────────────────────────────────────────── */
.pill {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 4px 11px;
  border-radius: 20px;
  font-size: 10px;
  font-weight: 600;
}
.p-orange {
  background: var(--brand-pale);
  border: 1px solid oklch(0.59 0.16 143 / 0.16);
  color: var(--brand);
}
.p-green {
  background: var(--green-pale);
  border: 1px solid oklch(0.32 0.09 158 / 0.18);
  color: var(--green);
}
.p-amber {
  background: oklch(0.62 0.14 68 / 0.1);
  border: 1px solid oklch(0.62 0.14 68 / 0.18);
  color: var(--amber);
}
.p-red {
  background: oklch(0.44 0.14 25 / 0.1);
  border: 1px solid oklch(0.44 0.14 25 / 0.18);
  color: var(--red);
}

/* ── FORMS ──────────────────────────────────────────────────── */
input,
select,
textarea {
  background: var(--paper);
  border: 1.5px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 10px 14px;
  font-size: 14px;
  color: var(--ink);
  font-family: var(--font-body);
  transition:
    border-color 0.18s,
    box-shadow 0.18s;
  width: 100%;
}
input:focus,
select:focus,
textarea:focus {
  outline: none;
  border-color: var(--brand);
  box-shadow: 0 0 0 3px oklch(0.59 0.16 143 / 0.14);
}
label {
  font-size: 11px;
  font-weight: 600;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 1px;
  margin-bottom: 5px;
  display: block;
}
.form-group {
  margin-bottom: 14px;
}
.form-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
}

/* Profil toggle row 2026-05-09 (P1 fix Claudette 67 ans iPad) :
   checkbox + label sur une rangee 44px min, hit area complete sur la
   rangee. text-transform:none et letter-spacing:0 pour lire en serie. */
.profil-toggle-row {
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: 44px;
  padding: 10px 8px;
  margin: 0;
  cursor: pointer;
  border-radius: 8px;
  transition:
    background 0.15s ease,
    box-shadow 0.15s ease;
  text-transform: none;
  letter-spacing: 0;
}
@media (hover: hover) and (pointer: fine) {
  .profil-toggle-row:hover {
    background: var(--paper-soft, var(--paper));
  }
}
/* :focus-within propage le focus de la checkbox au parent label —
   le ring (box-shadow) couvre la rangee 44px complete, visible
   sans ambiguite au clavier (Claudette qui navigue avec Tab).
   2026-05-09 R4 : avant `outline: 2px solid transparent` au repos
   puis change uniquement la couleur au focus -> outline 2px transparent
   visible sur fond clair = invisible. Maintenant box-shadow concrete
   au focus, rien au repos. WCAG AAA 3:1 contrast OK. */
.profil-toggle-row:focus-within {
  outline: none;
  box-shadow:
    0 0 0 2px var(--brand-dark, var(--brand)),
    0 0 0 4px var(--paper);
  background: var(--paper-soft, var(--paper));
}
.profil-toggle-cb {
  flex: 0 0 auto;
  width: 22px;
  height: 22px;
  margin: 0;
  cursor: pointer;
  accent-color: var(--brand-dark, var(--brand));
}
.profil-toggle-text {
  font-size: 14px;
  font-weight: 500;
  color: var(--ink);
  line-height: 1.4;
}
/* Fallback :checked iOS Safari < 15.3 (accent-color non supporte).
   2026-05-09 R4 : avant juste font-weight 600 + color = trop subtil
   pour Claudette (vue mauvaise) sur iPad. Maintenant : bold + color
   + checkmark vert prepended via pseudo-element ::before. Vrai signal
   visuel meme si la checkbox systeme reste grise. */
.profil-toggle-cb:checked + .profil-toggle-text {
  font-weight: 600;
  color: var(--brand-dark, var(--brand));
}
.profil-toggle-cb:checked + .profil-toggle-text::before {
  content: "\2713 ";
  color: var(--brand-dark, var(--brand));
  font-weight: 700;
  margin-right: 2px;
}
.profil-toggle-help {
  display: block;
  font-size: 12px;
  font-weight: 400;
  color: var(--ink-muted);
  margin-top: 2px;
  letter-spacing: 0;
}

/* Progressive disclosure 2026-05-09 (audit R2 P1) :
   <details> qui replie 3 fieldsets avances (Priorite menu,
   Restrictions, Allergies) que Marie/Casey n ouvrent jamais.
   Pattern coherent avec onb-collapse, dash-recevoir-teaser :
   summary 44px, no marker, pill compact. */
.profil-advanced {
  margin: 14px 0;
  border: 1px dashed var(--border, oklch(0.88 0.02 75));
  border-radius: 10px;
  background: transparent;
  overflow: hidden;
}
.profil-advanced-summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 16px;
  cursor: pointer;
  list-style: none;
  min-height: 44px;
}
.profil-advanced-summary::-webkit-details-marker {
  display: none;
}
.profil-advanced-text {
  font-size: 13.5px;
  font-weight: 500;
  color: var(--ink);
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}
.profil-advanced-count {
  font-size: 11px;
  font-weight: 600;
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--accent-tint);
  color: var(--brand-dark, var(--brand));
  letter-spacing: 0;
}
.profil-advanced-cta {
  font-size: 11px;
  font-weight: 600;
  color: var(--brand-dark, var(--brand));
  text-transform: uppercase;
  letter-spacing: 0.06em;
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  transition: opacity 0.15s ease;
}
.profil-advanced-cta::after {
  content: "";
  display: inline-block;
  width: 0;
  height: 0;
  margin-left: 2px;
  border-left: 4px solid transparent;
  border-right: 4px solid transparent;
  border-top: 5px solid currentColor;
  transition: transform 0.2s ease;
}
.profil-advanced[open] .profil-advanced-cta {
  opacity: 0.6;
}
.profil-advanced[open] .profil-advanced-cta::after {
  transform: rotate(180deg);
}
.profil-advanced-body {
  padding: 4px 16px 16px;
  border-top: 1px dashed var(--border2, oklch(0.92 0.015 75));
  margin-top: 4px;
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.profil-advanced-body .form-group {
  margin-bottom: 0;
}

/* Boutons utilitaires regroupes apres Sauvegarder 2026-05-09
   (audit R3) : Mon compte + Mes donnees + Deconnexion replies
   sous un <details> discret pour ne pas competition avec le
   primary CTA Sauvegarder. */
.profil-actions-more {
  margin: 12px 0 24px;
  border: 1px dashed var(--border, oklch(0.88 0.02 75));
  border-radius: 10px;
  background: transparent;
  overflow: hidden;
}
.profil-actions-more-summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 16px;
  cursor: pointer;
  list-style: none;
  min-height: 44px;
  font-size: 13px;
  font-weight: 500;
  color: var(--ink-muted);
}
.profil-actions-more-summary::-webkit-details-marker {
  display: none;
}
.profil-actions-more-cta {
  font-size: 11px;
  font-weight: 600;
  color: var(--brand-dark, var(--brand));
  text-transform: uppercase;
  letter-spacing: 0.06em;
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  transition: opacity 0.15s ease;
}
.profil-actions-more-cta::after {
  content: "";
  display: inline-block;
  width: 0;
  height: 0;
  margin-left: 2px;
  border-left: 4px solid transparent;
  border-right: 4px solid transparent;
  border-top: 5px solid currentColor;
  transition: transform 0.2s ease;
}
.profil-actions-more[open] .profil-actions-more-cta {
  opacity: 0.6;
}
.profil-actions-more[open] .profil-actions-more-cta::after {
  transform: rotate(180deg);
}
.profil-actions-more-body {
  padding: 4px 16px 16px;
  border-top: 1px dashed var(--border2, oklch(0.92 0.015 75));
  margin-top: 4px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.profil-actions-more-body .btn-sec,
.profil-actions-more-body .profil-logout-btn {
  width: 100%;
  text-align: center;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.profil-logout-btn {
  color: var(--danger);
  border-color: var(--danger);
  background: transparent;
  cursor: pointer;
}
@media (hover: hover) and (pointer: fine) {
  .profil-logout-btn:hover {
    background: color-mix(in oklch, var(--danger) 8%, transparent);
  }
}
.profil-actions-more-body .profil-logout {
  margin: 0;
}
.form-divider {
  font-size: 11px;
  font-weight: 700;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 1.5px;
  padding: 14px 0 8px;
  border-top: 1px solid var(--border);
  margin-top: 4px;
}

/* ── TAGS ───────────────────────────────────────────────────── */
.tag-cloud {
  display: flex;
  flex-wrap: wrap;
  gap: 7px;
}
.ptag {
  padding: 5px 13px;
  border-radius: 20px;
  font-size: 11px;
  font-weight: 500;
  cursor: pointer;
  border: 1.5px solid var(--border);
  color: var(--muted);
  transition:
    transform 0.18s,
    opacity 0.18s,
    color 0.18s,
    background 0.18s,
    border-color 0.18s,
    box-shadow 0.18s;
  background: var(--paper);
  display: inline-block;
}
.ptag.on {
  background: var(--brand-pale);
  border-color: oklch(0.59 0.16 143 / 0.26);
  color: var(--brand);
}
@media (hover: hover) and (pointer: fine) {
  .ptag:hover {
    border-color: oklch(0.59 0.16 143 / 0.26);
    color: var(--brand);
  }
}

/* ============================================================
   RESPONSIVE
   ============================================================ */
.sidebar-toggle {
  display: none;
  background: none;
  border: none;
  cursor: pointer;
  padding: 6px;
  font-size: 22px;
  line-height: 1;
  color: var(--ink);
}

/* Bouton retour PWA — visible uniquement en mode standalone (PWA installée
   sur home screen, browser chrome caché). En web mobile normal le browser
   gère le back via swipe-edge ou barre du navigateur, on évite la
   redondance. JS (LE.pwaBack) toggle l'attribut [hidden] selon
   history.length et display-mode. */
.pwa-back-btn {
  display: none;
  width: 44px;
  height: 44px;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: none;
  cursor: pointer;
  color: var(--accent);
  border-radius: 50%;
  transition: background-color 150ms cubic-bezier(0.22, 1, 0.36, 1);
}
@media (hover: hover) and (pointer: fine) {
  .pwa-back-btn:hover {
    background: var(--accent-tint);
  }
}
.pwa-back-btn:active {
  background: color-mix(in oklch, var(--accent-tint) 80%, var(--accent) 20%);
}
.pwa-back-btn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
@media (display-mode: standalone) {
  .pwa-back-btn:not([hidden]) {
    display: inline-flex;
  }
}

.sidebar-overlay {
  display: none;
  position: fixed;
  inset: 0;
  background: oklch(0.18 0.015 110 / 0.55);
  z-index: 199;
}

/* ── DESKTOP (≥ 769px) : scroll-lock + double-container ─────── */
/* On verrouille html/body et on laisse scroller le .content intérieur.
   Évite les problèmes de scroll Android/iOS en restaurant un flow
   naturel dès que le viewport est mobile (< 769px). */
@media (min-width: 769px) {
  html,
  body {
    height: 100%;
    overflow: hidden;
  }
  .app-layout {
    height: 100vh;
    height: 100dvh;
    overflow: hidden;
  }
  .main {
    overflow: hidden;
  }
  .content {
    overflow-y: auto;
    scrollbar-gutter: stable;
  }
}

/* ── TABLET 1024px ──────────────────────────────────────────── */
@media (max-width: 1024px) {
  .sidebar {
    width: 200px;
  }
  .content-inner {
    padding: 18px;
  }
  .cards-grid {
    grid-template-columns: repeat(2, 1fr);
  }
  .epargne-grid {
    grid-template-columns: 1fr;
  }
}

/* ── MOBILE 768px ───────────────────────────────────────────── */
@media (max-width: 768px) {
  /* Scroll : géré par l'absence de lock dans les règles par défaut (voir haut du fichier).
     html/body/.app-layout/.main/.content ont tous leur flow naturel ici. */
  .app-layout {
    flex-direction: column;
  }

  .sidebar {
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    width: 100vw;
    max-width: 100vw;
    z-index: 200;
    transform: translateX(-100%);
    transition: transform 0.28s cubic-bezier(0.22, 0.61, 0.36, 1);
    box-shadow: none;
  }
  .sidebar.open {
    transform: translateX(0);
  }
  .sidebar-overlay.open {
    display: block;
  }

  .topbar {
    padding: 10px 16px;
    position: sticky;
    top: 0;
    z-index: 100;
  }
  .sidebar-toggle {
    display: flex;
    align-items: center;
    justify-content: center;
  }
  .tb-left {
    gap: 10px;
  }
  .ptitle {
    font-size: 15px;
  }

  .content-inner {
    padding: 14px 16px;
  }

  .cards-grid {
    grid-template-columns: 1fr;
  }
  .form-row {
    grid-template-columns: 1fr;
  }
  .epargne-grid {
    grid-template-columns: 1fr;
  }
  /* .fb2-* media overrides supprimés 2026-06-04 (dead code). */

  .tb-right {
    gap: 6px;
  }
  /* Audit /audit P1 : touch targets WCAG 2.5.5 AAA — avant 7px 12px →
     hauteur ~28px, mistaps fréquents Claudette 67. Maintenant 12px 16px
     + min-height 44px pour respecter le seuil. font-size reste 11px pour
     éviter wrap mais on garde le hit area généreux. */
  .tb-right .btn-main,
  .tb-right .btn-sec {
    padding: 12px 16px;
    font-size: 11px;
    min-height: 44px;
  }

  .score-grid {
    grid-template-columns: 1fr;
  }
  .page-header {
    flex-direction: column;
    align-items: flex-start;
    gap: 10px;
  }
}

/* ── SMALL MOBILE 480px ─────────────────────────────────────── */
@media (max-width: 480px) {
  .topbar {
    padding: 8px 12px;
  }
  .ptitle {
    font-size: 14px;
  }
  .content-inner {
    padding: 10px 12px;
  }
  .card {
    padding: 14px;
  }
  /* .fb2-* media overrides supprimés 2026-06-04 (dead code). */
  .bars-wrap {
    gap: 5px;
  }
  .modal-box {
    margin: 12px;
    width: calc(100% - 24px);
    border-radius: 16px;
  }
  .kpi-strip {
    grid-template-columns: repeat(2, 1fr);
  }
}

/* ============================================================
   DARK MODE — [data-theme="dark"]
   "Soir d'automne sur le divan" — warm forest dark, never cold gray
   ============================================================ */
[data-theme="dark"] {
  /* Warm tabac-dark paper — "soir à la cabane à sucre" */
  --paper: oklch(0.18 0.014 75);
  --paper-soft: oklch(0.15 0.012 75);
  --paper-sheet: oklch(0.23 0.016 75);
  --paper-deep: oklch(0.12 0.01 75);

  /* Cream text on warm dark */
  --ink: oklch(0.94 0.01 75);
  --ink-soft: oklch(0.8 0.012 75);
  --ink-muted: oklch(0.72 0.012 75); /* WCAG AA on dark paper */
  --ink-fade: oklch(0.6 0.01 75); /* remonté pour rester lisible sur dark paper */

  /* Vert Jean-Talon dark — plus lumineux, légèrement désaturé pour tenir
     sur paper sombre sans devenir fluo. Cible : 5:1 vs dark paper. */
  --accent: oklch(0.72 0.14 143);
  --accent-deep: oklch(0.56 0.13 143);
  --accent-bright: oklch(0.84 0.14 143);
  --accent-tint: oklch(0.28 0.042 143); /* surface active/badge */
  --accent-tint2: oklch(0.34 0.05 143);
  --accent-glow: 0 8px 32px oklch(0.72 0.14 143 / 0.28);

  /* Badges intensité — variantes nuit (ambre sombre, neutre sombre) */
  --badge-warn-bg: oklch(0.34 0.08 80 / 0.40);
  --badge-warn-ink: oklch(0.82 0.12 80);
  --badge-neutral-bg: oklch(0.30 0.014 75);
  --badge-neutral-ink: oklch(0.80 0.012 75);

  /* Danger dark — rouge chaud nuit */
  --danger: oklch(0.58 0.15 25);
  --danger-deep: oklch(0.44 0.13 25);
  --danger-bright: oklch(0.7 0.16 25);
  /* Heart dark — plus lumineux pour rester visible sur paper dark */
  --heart: oklch(0.7 0.17 15);
  --heart-deep: oklch(0.78 0.18 15);
  --danger-tint: oklch(0.3 0.042 25);
  --danger-tint2: oklch(0.36 0.05 25);
  --danger-glow: 0 8px 32px oklch(0.58 0.15 25 / 0.28);

  /* Legacy aliases reconduits pour dark — tous pointent --accent ou --danger */
  --brick: var(--accent);
  --brick-deep: var(--accent-deep);
  --brick-bright: var(--accent-bright);
  --brick-tint: var(--accent-tint);
  --brick-tint2: var(--accent-tint2);
  --brick-glow: var(--accent-glow);
  --canneberge: var(--danger);
  --canneberge-tint: var(--danger-tint);
  --labrador: var(--accent);
  --labrador-deep: var(--accent-deep);
  --labrador-bright: var(--accent-bright);
  --labrador-tint: var(--accent-tint);
  --labrador-tint2: var(--accent-tint2);
  --labrador-glow: var(--accent-glow);
  --oxblood: var(--danger);
  --oxblood-deep: var(--danger-deep);
  --oxblood-bright: var(--danger-bright);
  --oxblood-tint: var(--danger-tint);
  --oxblood-tint2: var(--danger-tint2);
  --oxblood-glow: var(--danger-glow);
  --moutarde: oklch(0.7 0.13 82);
  --moutarde-tint: oklch(0.3 0.042 82);

  /* ── Brand fill tokens — accent-deep pour cream-on-brand WCAG AA ── */
  --brand: oklch(0.54 0.14 143);
  --brand-light: oklch(0.72 0.14 143);
  --brand-dark: oklch(0.42 0.12 143);
  --brand-pale: oklch(0.28 0.042 143);
  --brand-glow: 0 8px 32px oklch(0.54 0.14 143 / 0.38);

  --courge: oklch(0.74 0.14 68);
  --courge-tint: oklch(0.3 0.04 68);
  --ardoise: oklch(0.66 0.1 220);
  --ardoise-tint: oklch(0.28 0.032 220);
  --paille: oklch(0.84 0.12 72);
  --violette: oklch(0.64 0.13 325);
  --violette-tint: oklch(0.3 0.038 325);

  /* Borders wake up gently */
  --border: oklch(0.32 0.016 75);
  --border2: oklch(0.26 0.014 75);

  /* Shadows — deeper, warmer tabac */
  --shadow: 0 1px 3px oklch(0.08 0.012 75 / 0.4), 0 1px 2px oklch(0.08 0.012 75 / 0.3);
  --shadow-md: 0 6px 24px oklch(0.08 0.012 75 / 0.5), 0 2px 8px oklch(0.08 0.012 75 / 0.35);
  --shadow-lg: 0 18px 48px oklch(0.08 0.012 75 / 0.6), 0 4px 14px oklch(0.08 0.012 75 / 0.4);
}
[data-theme="dark"] body {
  background: var(--paper);
  color: var(--ink);
}
[data-theme="dark"] .sidebar {
  background: var(--paper-sheet);
  border-right-color: var(--border);
}
[data-theme="dark"] .topbar {
  background: color-mix(in oklch, var(--paper-sheet) 82%, transparent);
}
[data-theme="dark"] .fantome-banner,
[data-theme="dark"] .fantome-big {
  background: linear-gradient(135deg, var(--paper-sheet), oklch(0.26 0.035 155));
  border-color: oklch(0.72 0.14 143 / 0.22);
}
[data-theme="dark"] input,
[data-theme="dark"] select,
[data-theme="dark"] textarea {
  background: var(--paper-soft);
  border-color: var(--border);
  color: var(--ink);
}
[data-theme="dark"] .flash-success {
  background: oklch(0.72 0.14 143 / 0.18);
  border-color: oklch(0.72 0.14 143 / 0.26);
}
[data-theme="dark"] .flash-error {
  background: oklch(0.62 0.17 22 / 0.18);
  border-color: oklch(0.62 0.17 22 / 0.26);
}
[data-theme="dark"] .score-card {
  background: linear-gradient(135deg, oklch(0.26 0.035 295), oklch(0.22 0.028 295));
  border-color: oklch(0.65 0.13 295 / 0.26);
}
[data-theme="dark"] canvas {
  filter: brightness(0.92) saturate(0.9);
}

/* Dark mode toggle button — legacy selector kept for compat */
.dark-toggle,
.tb-icon-btn {
  background: var(--paper-sheet);
  border: 1px solid var(--border);
  border-radius: 12px;
  cursor: pointer;
  padding: 12px;
  width: 44px;
  height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--ink-soft);
  transition:
    transform 0.2s,
    opacity 0.2s,
    color 0.2s,
    background 0.2s,
    border-color 0.2s,
    box-shadow 0.2s cubic-bezier(0.22, 1, 0.36, 1);
  line-height: 1;
}
@media (hover: hover) and (pointer: fine) {
  .dark-toggle:hover,
  .tb-icon-btn:hover {
    border-color: var(--brand-dark);
    color: var(--brand-dark);
    background: var(--accent-tint);
  }
}
.tb-icon-btn.is-dark {
  color: var(--brand-dark);
}

.topbar-form {
  display: inline-flex;
}
.live-pill-hidden {
  display: none !important;
}
.is-hidden {
  display: none !important;
}

/* Topbar action button — text on desktop, icon-only on mobile */
.btn-icon-mobile-icon {
  display: none;
}
@media (max-width: 768px) {
  .btn-icon-mobile {
    width: 44px;
    height: 44px;
    padding: 0 !important;
    border-radius: 12px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }
  .btn-icon-mobile-text {
    display: none;
  }
  .btn-icon-mobile-icon {
    display: block;
  }
  /* Hide the live-pill on mobile to free up topbar room */
  .live-pill {
    display: none;
  }
  /* Page-title in topbar is redundant when the page has a page-masthead.
     Truncate it instead of hiding so admin views without a masthead
     still have a title visible. */
  .ptitle {
    max-width: 38vw;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
}

/* ============================================================
   VOCAL ASSISTANT
   ============================================================ */
.vocal-active {
  border-color: var(--brand) !important;
  animation: pulse-border 1s infinite;
}
@keyframes pulse-border {
  0%,
  100% {
    box-shadow: none;
  }
  50% {
    box-shadow: 0 0 0 4px oklch(0.59 0.16 143 / 0.26);
  }
}
#vocalBtn.vocal-active {
  background: var(--brand-pale);
  color: var(--brand);
}

/* Meteo badge topbar */
.meteo-badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 12px;
  color: var(--muted);
  padding: 4px 10px;
  border: 1.5px solid var(--border);
  border-radius: 8px;
}

/* Modal overlay backdrop : surface solide tintée ink au lieu de glassmorphism
   blur — gain perf mobile + look plus maîtrisé (pas de tell AI slop). */
.modal-overlay {
  background: oklch(0.18 0.015 110 / 0.62);
}

/* ============================================================
   YOUNG SERIF WEIGHT CORRECTION
   Young Serif is a single-weight display face (400 only).
   Any class that previously had font-weight: 700–900 on a
   display-family element now uses Commissioner 700–900 for
   numeric displays (prices, KPIs, big amounts) and weight 400
   for editorial titles (Young Serif). This prevents fake-bold
   rendering which looks broken.
   ============================================================ */

/* Display titles — Young Serif, weight always 400 */
.ptitle,
.ctitle,
.logo-txt,
.recipe-title,
.sz-title,
.rc-store,
.vn,
.dd,
.fb-eyebrow,
.sc-lbl,
.fb-plbl {
  font-weight: 400 !important;
  letter-spacing: -0.01em;
}
.logo-txt {
  letter-spacing: -0.012em;
}

/* Numeric displays — switch back to Commissioner (has real bold) */
.fb-amount,
.fb-currency,
.fb-pct,
.kpi-val,
.sc-pct,
.rc-total,
.cmp-v,
.ri-price,
.si-p,
.mockup-budget-amount {
  font-family: var(--font-body);
  font-feature-settings:
    "tnum" 1,
    "lnum" 1,
    "ss01";
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
}
.fb-amount {
  font-weight: 800;
}
.kpi-val,
.sc-pct {
  font-weight: 800;
}
.rc-total,
.cmp-v,
.mockup-budget-amount {
  font-weight: 800;
}
.ri-price,
.si-p {
  font-weight: 700;
}

/* ============================================================
   EDITORIAL TYPOGRAPHY SCALE — Young Serif for display, Commissioner for body
   Apply to any heading outside legacy .ctitle/.ptitle which keep their sizes.
   ============================================================ */
h1,
h2,
h3,
h4,
.display-xl,
.display-lg,
.display-md,
.display-sm {
  font-family: var(--font-display);
  color: var(--ink);
  line-height: 1.08;
  letter-spacing: -0.01em;
  font-weight: 400; /* Young Serif is one-weight; rely on size for hierarchy */
  text-wrap: balance;
}
.display-xl {
  font-size: clamp(40px, 6vw, 72px);
  line-height: 1.02;
  letter-spacing: -0.015em;
}
.display-lg {
  font-size: clamp(32px, 4.2vw, 54px);
  line-height: 1.05;
  letter-spacing: -0.012em;
}
.display-md {
  font-size: clamp(26px, 3vw, 38px);
  line-height: 1.1;
}
.display-sm {
  font-size: clamp(20px, 2.2vw, 26px);
  line-height: 1.2;
}

/* Eyebrow label — small caps over a heading */
.eyebrow {
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--brand-dark);
  display: inline-block;
  margin-bottom: 10px;
}
[data-theme="dark"] .eyebrow {
  color: var(--accent);
}

/* Focus — always visible, warm, matches brand */
:focus {
  outline: none;
}
:focus-visible {
  outline: 2.5px solid var(--brand-dark);
  outline-offset: 3px;
  border-radius: 4px;
}
input:focus-visible,
select:focus-visible,
textarea:focus-visible {
  outline: none;
  border-color: var(--brand-dark);
  box-shadow: 0 0 0 4px oklch(0.59 0.16 143 / 0.18);
}
/* Nav group buttons + sidebar links */
.nav-group-toggle:focus-visible,
.ni:focus-visible {
  outline: 2px solid var(--brand-dark);
  outline-offset: -2px;
}
/* Topbar icon buttons */
.tb-icon-btn:focus-visible {
  outline: 2px solid var(--brand-dark);
  outline-offset: 2px;
}
/* Skip to content link (hidden until focused) */
.skip-link {
  position: absolute;
  top: 8px;
  left: 16px;
  transform: translateY(-200%);
  background: var(--brand-dark);
  color: var(--cream-fixed);
  padding: 8px 16px;
  border-radius: var(--radius-sm);
  z-index: 9999;
  font-size: 13px;
  font-weight: 600;
  transition: transform 0.2s;
}
.skip-link:focus {
  transform: translateY(0);
}

/* ============================================================
   SIDEBAR — Premium nav item (was inline border-left)
   ============================================================ */
.ni.ni-premium {
  color: var(--danger);
  font-weight: 700;
  background: var(--brick-tint);
  position: relative;
}
@media (hover: hover) and (pointer: fine) {
  .ni.ni-premium:hover {
    color: var(--brick-deep);
    background: oklch(0.59 0.16 143 / 0.14);
  }
}
.ni.ni-premium .nico {
  opacity: 1;
}

/* ============================================================
   CIRCULAIRES EN ATTENTE — bandeau sitewide quand Flipp n'a pas
   encore publié les rabais de la semaine courante
   ============================================================ */
/* Bandeau « Circulaires en attente cette semaine » — état d'attente
   temporaire signalé en haut de l'app quand Flipp n'a pas encore
   publié les rabais de la semaine. Refonte avril 2026 : palette
   mono-accent Vert Jean-Talon (avant : courge-tint + brick deprecated).
   Registre « note neutre » plutôt que « alerte » — c'est temporaire,
   pas critique. Voix grand-maman tenue dans le copy. */
.circulaires-pending {
  display: none; /* toggled by JS */
  background: var(--paper-soft);
  border: 1px solid color-mix(in oklch, var(--brand) 22%, var(--border));
  border-radius: var(--radius);
  padding: 14px 18px;
  margin: 0 0 16px 0;
  font-size: 13.5px;
  color: var(--ink-soft);
  align-items: flex-start;
  gap: 14px;
  line-height: 1.55;
}
.circulaires-pending-icon {
  font-size: 22px;
  line-height: 1;
  flex-shrink: 0;
  color: var(--brand-dark, var(--brand));
}
.circulaires-pending-body {
  flex: 1;
}
.circulaires-pending-title {
  font-family: var(--font-display);
  font-size: 15px;
  font-weight: 400;
  margin-bottom: 4px;
  color: var(--ink);
  letter-spacing: -0.005em;
}
.circulaires-pending a {
  color: var(--brand-dark, var(--brand));
  text-decoration: underline;
  text-decoration-thickness: 1.5px;
  text-underline-offset: 2px;
  font-weight: 600;
}
@media (hover: hover) and (pointer: fine) {
  .circulaires-pending a:hover {
    text-decoration-thickness: 2px;
  }
}
.circulaires-pending-close {
  background: transparent;
  border: 0;
  color: var(--ink-muted);
  font-size: 22px;
  cursor: pointer;
  line-height: 1;
  padding: 8px 12px;
  flex-shrink: 0;
  border-radius: 6px;
  position: relative;
  transition:
    background 0.15s,
    color 0.15s;
}
/* Hit area étendue à 44×44 (pattern Apple HIG / WCAG AAA) sans
   changer la taille visuelle du bouton. */
.circulaires-pending-close::after {
  content: "";
  position: absolute;
  inset: -8px;
  min-width: 44px;
  min-height: 44px;
}
@media (hover: hover) and (pointer: fine) {
  .circulaires-pending-close:hover {
    background: color-mix(in oklch, var(--ink) 6%, transparent);
    color: var(--ink);
  }
}
[data-theme="dark"] .circulaires-pending {
  background: color-mix(in oklch, var(--brand) 8%, var(--paper-soft));
  border-color: color-mix(in oklch, var(--brand) 35%, var(--border));
  color: var(--ink-soft);
}
[data-theme="dark"] .circulaires-pending-title {
  color: var(--ink);
}

/* ============================================================
   VOCAL ASSISTANT OVERLAY
   ============================================================ */
.vocal-overlay {
  display: none;
  position: fixed;
  inset: 0;
  background: oklch(0.18 0.015 110 / 0.62);
  z-index: 600;
  align-items: center;
  justify-content: center;
}
.vocal-dialog {
  background: var(--paper-sheet);
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  padding: 40px 34px;
  text-align: center;
  max-width: 380px;
  width: 90%;
  box-shadow: var(--shadow-lg);
}
.vocal-icon {
  font-size: 56px;
  margin-bottom: 14px;
}
.vocal-title {
  font-family: var(--font-display);
  font-size: 22px;
  font-weight: 400;
  color: var(--ink);
  margin-bottom: 8px;
  letter-spacing: -0.01em;
}
.vocal-status {
  font-size: 13px;
  color: var(--ink-muted);
  margin-bottom: 16px;
}
.vocal-transcript {
  font-size: 17px;
  font-weight: 600;
  color: var(--brand-dark);
  min-height: 30px;
  margin-bottom: 22px;
}
.vocal-commands {
  font-size: 11.5px;
  color: var(--ink-muted);
  line-height: 1.9;
  margin-bottom: 20px;
}
.vocal-commands strong {
  color: var(--ink-soft);
  font-weight: 600;
}
.vocal-actions {
  display: flex;
  gap: 10px;
  justify-content: center;
}
.vocal-close {
  background: var(--paper-soft);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--ink);
  padding: 10px 22px;
  cursor: pointer;
  font-size: 13px;
  font-weight: 600;
  font-family: var(--font-body);
}
@media (hover: hover) and (pointer: fine) {
  .vocal-close:hover {
    border-color: var(--brand-dark);
    color: var(--brand-dark);
  }
}
.vocal-hint {
  margin-top: 14px;
  font-size: 10.5px;
  color: var(--ink-fade);
}

/* ============================================================
   OFFLINE BAR
   ============================================================ */
.offline-bar {
  display: none;
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  background: var(--danger);
  color: var(--cream-fixed);
  text-align: center;
  padding: 12px 16px;
  font-size: 13px;
  font-weight: 600;
  z-index: 9999;
  letter-spacing: -0.1px;
}

/* ── Loading indicator (bandeau haut, non-bloquant) ──────── */
.loading-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 9999;
  background: var(--accent-tint);
  border-bottom: 1px solid oklch(0.59 0.16 143 / 0.22);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 10px 16px;
  animation: slideDown 0.3s ease;
}
@keyframes slideDown {
  from {
    transform: translateY(-100%);
  }
  to {
    transform: translateY(0);
  }
}
.loading-spinner {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  border: 2.5px solid var(--accent-tint);
  border-top-color: var(--brand-dark);
  animation: spin 0.8s linear infinite;
}
.loading-text {
  font-family: var(--font-body);
  font-size: 13px;
  font-weight: 600;
  color: var(--brand-dark);
}

/* ============================================================
   APP FOOTER (inside authed main) — minimal premium
   Just links + copyright. Legal disclaimer lives on /conditions.
   ============================================================ */
.app-footer {
  margin-top: 56px;
  padding: 22px 4px 18px;
  border-top: 1px solid var(--border);
  font-size: 12px;
  color: var(--ink-fade);
  line-height: 1.6;
  display: flex;
  flex-wrap: wrap;
  gap: 6px 16px;
  align-items: baseline;
  justify-content: space-between;
}
/* PWA standalone : les mentions légales vivent dans la page Compte,
   donc on masque ce pied de page dans l'app installée pour garder
   l'expérience app-like (pas de chrome web). */
@media all and (display-mode: standalone) {
  .app-footer {
    display: none !important;
  }
}
@media all and (display-mode: fullscreen), all and (display-mode: minimal-ui) {
  .app-footer {
    display: none !important;
  }
}
.app-footer-links {
  display: inline-flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 10px;
}
.app-footer-sep {
  color: var(--ink-fade);
  opacity: 0.55;
}
.app-footer-copy {
  font-size: 12px;
  color: var(--ink-fade);
  letter-spacing: 0.01em;
}
.app-footer-copy em {
  font-family: var(--font-display);
  font-style: normal;
  color: var(--accent);
}
.app-footer a {
  color: var(--ink-muted);
  text-decoration: none;
  border-bottom: 1px solid oklch(from var(--ink-muted) l c h / 0.25);
  padding-bottom: 1px;
  transition:
    color 0.15s ease,
    border-color 0.15s ease;
}
@media (hover: hover) and (pointer: fine) {
  .app-footer a:hover {
    color: var(--accent);
    border-bottom-color: var(--accent);
  }
}

/* ============================================================
   PAGE MASTHEAD — ligne éditoriale réutilisable pour chaque vue
   .dash-masthead = alias pour le dashboard (compat backward)
   ============================================================ */
.page-masthead,
.dash-masthead {
  margin-bottom: 26px;
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.page-masthead-meta,
.dash-masthead-date {
  display: flex;
  align-items: center;
  gap: 12px;
  font-family: var(--font-body);
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-muted);
  padding-bottom: 14px;
  border-bottom: 1px solid var(--border);
  flex-wrap: wrap;
}
.page-masthead-eyebrow,
.dash-masthead-eyebrow {
  color: var(--brand-dark);
}
.page-masthead-sep,
.dash-masthead-sep {
  width: 3px;
  height: 3px;
  border-radius: 50%;
  background: var(--ink-fade);
  flex-shrink: 0;
}
.page-masthead-title,
.dash-masthead-greeting {
  font-family: var(--font-display);
  font-size: clamp(28px, 3.2vw, 42px);
  font-weight: 400;
  color: var(--ink);
  letter-spacing: -0.02em;
  line-height: 1.06;
  margin: 0;
  text-wrap: balance;
  max-width: 28ch;
}
.page-masthead-title em,
.dash-masthead-greeting em {
  color: var(--brand-dark);
  font-style: italic;
  font-family: var(--font-display);
}
.page-masthead-lede {
  font-family: var(--font-body);
  font-size: 15.5px;
  line-height: 1.62;
  color: var(--ink-soft);
  max-width: 60ch;
  margin: 6px 0 0;
}

/* Badge savings number inside Budget Fantôme sub-line */
.fb-savings-value {
  color: var(--brand-dark) !important;
  font-family: var(--font-body);
  font-size: 16px !important;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.ftag.ftag-accent {
  color: var(--brand-dark);
  border-color: oklch(0.59 0.16 143 / 0.28);
  background: var(--accent-tint);
}

/* The page-title in topbar uses var(--font-display) (set earlier).
   Override to Commissioner semibold so "Bonjour, Marie" reads
   as a friendly greeting, not a cookbook chapter. */
.ptitle {
  font-family: var(--font-body);
  font-size: 14px;
  font-weight: 600;
  color: var(--ink-soft);
  letter-spacing: 0.02em;
  text-transform: none;
}

/* ============================================================
   DASHBOARD ÉDITORIAL — Vague 5
   Le tableau de bord vu comme une couverture de magazine de
   ta semaine, pas comme un CRM. Sections en flow vertical
   avec eyebrow + serif title + body + action link, plutôt
   que bento-grid de cartes.
   ============================================================ */

/* ── Actions rapides — 4 tuiles d'accès instantané ───────────── */
.dash-quick {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 12px;
  margin-bottom: 28px;
}
.dash-quick-tile {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  padding: 18px 10px 16px;
  background: var(--paper-sheet);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  text-decoration: none;
  transition:
    transform 0.2s,
    opacity 0.2s,
    color 0.2s,
    background 0.2s,
    border-color 0.2s,
    box-shadow 0.2s cubic-bezier(0.25, 0.46, 0.45, 0.94);
  cursor: pointer;
}
@media (hover: hover) and (pointer: fine) {
  .dash-quick-tile:hover {
    background: var(--accent-tint);
    border-color: var(--brand-dark);
    transform: translateY(-2px);
    box-shadow: 0 6px 20px oklch(0.59 0.16 143 / 0.12);
  }
}
.dash-quick-tile--urgent {
  border-color: oklch(0.44 0.14 25 / 0.22);
}
@media (hover: hover) and (pointer: fine) {
  .dash-quick-tile--urgent:hover {
    background: oklch(0.44 0.14 25 / 0.06);
    border-color: var(--danger);
  }
}
.dash-quick-icon {
  font-size: 24px;
  line-height: 1;
}
.dash-quick-label {
  font-size: 12px;
  font-weight: 600;
  color: var(--ink-soft);
  text-align: center;
  line-height: 1.3;
  letter-spacing: -0.2px;
}
@media (hover: hover) and (pointer: fine) {
  .dash-quick-tile:hover .dash-quick-label {
    color: var(--ink);
  }
}
@media (max-width: 640px) {
  .dash-quick {
    grid-template-columns: repeat(2, 1fr);
    gap: 10px;
  }
}
@media (max-width: 480px) {
  .dash-quick {
    grid-template-columns: repeat(2, 1fr);
    gap: 8px;
  }
  .dash-quick-tile {
    padding: 14px 8px 12px;
  }
  .dash-quick-label {
    font-size: 11px;
  }
}

/* ── Skeleton loading shimmer ────────────────────────────────── */
@keyframes shimmer {
  0% {
    background-position: -400px 0;
  }
  100% {
    background-position: 400px 0;
  }
}
.skel {
  background: linear-gradient(90deg, var(--paper-soft) 25%, var(--paper-sheet) 37%, var(--paper-soft) 63%);
  background-size: 800px 100%;
  animation: shimmer 1.6s ease-in-out infinite;
  border-radius: var(--radius-sm);
  color: transparent !important;
}
.skel * {
  visibility: hidden;
}
.skel-line {
  height: 14px;
  margin-bottom: 8px;
}
.skel-line-lg {
  height: 32px;
  margin-bottom: 12px;
  width: 60%;
}
.skel-circle {
  width: 120px;
  height: 120px;
  border-radius: 50%;
}

/* ════════════════════════════════════════════════════════════════
   DASHBOARD HERO — Le focus visuel unique de la semaine
   Ring de budget + KPIs + quick actions dans un seul module.
   ════════════════════════════════════════════════════════════════ */
.dash-hero {
  background: var(--paper-sheet);
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  padding: clamp(24px, 3vw, 40px);
  margin-bottom: 28px;
  position: relative;
  overflow: hidden;
}
.dash-hero-greeting {
  position: relative;
  margin-bottom: 24px;
}
.dash-hero-meta {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  color: var(--ink-muted);
  margin-bottom: 4px;
}
.dash-hero-grid {
  position: relative;
  display: grid;
  grid-template-columns: auto 1fr;
  gap: clamp(24px, 4vw, 48px);
  align-items: center;
  margin-bottom: 24px;
}

/* Ring */
.dash-hero-ring {
  position: relative;
  width: 180px;
  height: 180px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.dash-hero-ring svg {
  position: absolute;
}
.dash-hero-ring-progress {
  transform: rotate(-90deg);
  transform-origin: 60px 60px;
  animation: ringFill 1.2s cubic-bezier(0.25, 0.46, 0.45, 0.94) both;
}
@keyframes ringFill {
  from {
    stroke-dashoffset: 301.6;
  }
  to {
    stroke-dashoffset: var(--offset);
  }
}

/* ── Celebration toast — slide-in latéral, pas de modal ──── */
.celebration-toast {
  position: fixed;
  left: 50%;
  /* Audit /audit P2 : avant `transition: bottom` causait layout repaint
     sur chaque restack. Maintenant transform compositor-only — la base
     `bottom` reste statique, l'offset stack vit dans translateY pour
     rester sur la GPU layer. */
  bottom: calc(env(safe-area-inset-bottom, 0) + 84px);
  transform: translate(-50%, calc(var(--toast-stack-offset, 0px) * -1));
  transition: transform 0.24s var(--ease-out, ease);
  z-index: 9998;
  display: flex;
  align-items: center;
  gap: 12px;
  max-width: min(480px, calc(100vw - 32px));
  padding: 14px 16px;
  background: var(--paper-sheet);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: 0 12px 40px oklch(0.22 0.02 110 / 0.18);
  animation: celebToastIn 0.32s var(--ease-out-quart) both;
}
.celebration-toast.is-leaving {
  animation: celebToastOut 0.24s var(--ease-out) both;
}
@keyframes celebToastIn {
  from {
    opacity: 0;
    transform: translate(-50%, 12px);
  }
  to {
    opacity: 1;
    transform: translate(-50%, 0);
  }
}
@keyframes celebToastOut {
  from {
    opacity: 1;
    transform: translate(-50%, 0);
  }
  to {
    opacity: 0;
    transform: translate(-50%, 8px);
  }
}
.celebration-toast-icon {
  font-size: 22px;
  line-height: 1;
  flex: 0 0 auto;
}
.celebration-toast-text {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.celebration-toast-text strong {
  font-family: var(--font-display);
  font-size: 15px;
  color: var(--ink);
  font-weight: 600;
}
.celebration-toast-text span {
  font-size: 13px;
  color: var(--ink-soft);
  line-height: 1.4;
}
.celebration-toast-close {
  flex: 0 0 auto;
  width: 44px;
  height: 44px;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--ink-soft);
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
}
@media (hover: hover) and (pointer: fine) {
  .celebration-toast-close:hover {
    background: var(--brand-pale);
    color: var(--ink);
  }
}
/* Boutons d'action inline dans un toast (ex: « Reprendre / Recommencer »
   pour pause/resume mode cuisine). Toast pousse à pleine largeur en
   mobile pour que les boutons soient cliquables. */
.celebration-toast-actions {
  display: flex;
  gap: 8px;
  width: 100%;
  margin-top: 6px;
  flex-basis: 100%;
}
.celebration-toast-btn {
  flex: 1;
  padding: 12px 14px;
  border: 1px solid var(--border);
  background: var(--paper-sheet);
  color: var(--ink);
  border-radius: 8px;
  font-family: var(--font-body);
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  min-height: 44px;
  transition:
    background 0.15s,
    border-color 0.15s;
}
@media (hover: hover) and (pointer: fine) {
  .celebration-toast-btn:hover {
    background: var(--paper-soft);
    border-color: var(--ink-muted);
  }
}
.celebration-toast-btn.is-primary {
  background: var(--brand);
  color: var(--cream-fixed, #fff);
  border-color: var(--brand);
}
@media (hover: hover) and (pointer: fine) {
  .celebration-toast-btn.is-primary:hover {
    background: var(--brand-dark, var(--brand));
  }
}
/* Toast avec actions = layout flex-wrap pour que les actions passent
   en dessous du texte au lieu de flotter à côté. */
.celebration-toast:has(.celebration-toast-actions) {
  flex-wrap: wrap;
}
.celebration-toast.is-error {
  border-color: oklch(0.65 0.18 28 / 0.35);
  background: oklch(0.985 0.01 70);
}
.celebration-toast.is-error .celebration-toast-icon {
  color: oklch(0.55 0.2 28);
  font-weight: 700;
}
@media (max-width: 768px) {
  .celebration-toast {
    bottom: calc(env(safe-area-inset-bottom, 0) + 76px + var(--toast-stack-offset, 0px));
  }
}

/* ── Menu generation : reveal cinématique ───────────────── */
.gen-reveal {
  max-width: 620px;
  margin: 40px auto 60px;
  padding: 40px 24px 32px;
  position: relative;
  text-align: center;
  animation: gen-reveal-in 0.6s cubic-bezier(0.19, 1, 0.22, 1) both;
}
@keyframes gen-reveal-in {
  from {
    opacity: 0;
    transform: translateY(18px) scale(0.985);
  }
  to {
    opacity: 1;
    transform: none;
  }
}
.gen-reveal-burst {
  position: absolute;
  inset: 0 0 auto 0;
  height: 180px;
  pointer-events: none;
  overflow: visible;
}
/* Burst particles — mono-accent Vert Jean-Talon en 3 tons (accent / deep / tint)
   pour garder de la vibration visuelle sans violer la discipline mono-accent. */
.gen-reveal-burst span {
  position: absolute;
  left: 50%;
  top: 40%;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--accent);
  opacity: 0;
  animation: gen-burst 1.1s cubic-bezier(0.19, 1, 0.22, 1) 0.15s both;
}
.gen-reveal-burst span:nth-child(1) {
  --tx: -120px;
  --ty: -40px;
  background: var(--accent-deep);
  animation-delay: 0.1s;
}
.gen-reveal-burst span:nth-child(2) {
  --tx: 120px;
  --ty: -40px;
  background: var(--accent);
  animation-delay: 0.15s;
}
.gen-reveal-burst span:nth-child(3) {
  --tx: -70px;
  --ty: -90px;
  background: var(--accent);
  animation-delay: 0.2s;
}
.gen-reveal-burst span:nth-child(4) {
  --tx: 70px;
  --ty: -90px;
  background: var(--accent-deep);
  animation-delay: 0.25s;
}
.gen-reveal-burst span:nth-child(5) {
  --tx: -30px;
  --ty: -30px;
  background: var(--accent);
  animation-delay: 0.3s;
}
.gen-reveal-burst span:nth-child(6) {
  --tx: 30px;
  --ty: -30px;
  background: var(--accent-deep);
  animation-delay: 0.35s;
}
@keyframes gen-burst {
  0% {
    opacity: 0;
    transform: translate(-50%, -50%) scale(0.2);
  }
  30% {
    opacity: 1;
  }
  100% {
    opacity: 0;
    transform: translate(calc(-50% + var(--tx)), calc(-50% + var(--ty))) scale(1);
  }
}
.gen-reveal-eyebrow {
  font-size: 12px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent-deep, #2d6329);
  font-weight: 600;
  margin-bottom: 10px;
}
.gen-reveal-title {
  font-family: var(--font-display);
  font-size: clamp(34px, 6vw, 48px);
  line-height: 1.05;
  letter-spacing: -0.02em;
  margin: 0 0 28px;
  color: var(--text, #1a1a1a);
}
.gen-reveal-title em {
  font-style: italic;
  color: var(--brick, #c44e3a);
  font-weight: 400;
}
.gen-reveal-stats {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 12px;
  margin: 0 0 20px;
}
.gen-reveal-stat {
  padding: 14px 8px;
  border-radius: 14px;
  background: oklch(0.98 0.005 90);
  border: 1px solid oklch(0.92 0.012 85);
  opacity: 0;
  transform: translateY(8px);
  animation: gen-stat-in 0.5s cubic-bezier(0.19, 1, 0.22, 1) both;
  animation-delay: calc(350ms + var(--d, 0ms));
}
@keyframes gen-stat-in {
  to {
    opacity: 1;
    transform: none;
  }
}
.gen-reveal-stat-num {
  font-family: var(--font-display);
  font-size: 28px;
  line-height: 1;
  font-weight: 500;
  color: var(--brick-deep, #8a3526);
  font-variant-numeric: tabular-nums;
  display: inline-flex;
  align-items: baseline;
  gap: 2px;
}
.gen-reveal-stat-unit {
  font-size: 18px;
  font-weight: 400;
  color: var(--brick, #c44e3a);
}
.gen-reveal-stat-lbl {
  font-size: 11.5px;
  letter-spacing: 0.02em;
  color: var(--muted, #666);
  margin-top: 6px;
  text-transform: lowercase;
}
.gen-reveal-chips {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px;
  margin: 0 0 28px;
}
.gen-reveal-chip {
  font-size: 13px;
  padding: 7px 14px;
  background: var(--accent-tint);
  border: 1px solid oklch(0.86 0.06 72);
  color: var(--brick-deep, #8a3526);
  border-radius: 999px;
  font-weight: 500;
  opacity: 0;
  transform: translateY(6px);
  animation: gen-stat-in 0.5s cubic-bezier(0.19, 1, 0.22, 1) both;
  animation-delay: calc(350ms + var(--d, 0ms));
}
.gen-reveal-chip b {
  font-weight: 700;
}
.gen-reveal-cta {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 14px 28px;
  border-radius: 999px;
  background: var(--accent, #4a9e46);
  color: white;
  font-family: var(--font-display);
  font-size: 17px;
  text-decoration: none;
  font-weight: 500;
  box-shadow: 0 8px 22px -10px oklch(0.55 0.18 145 / 0.55);
  transition:
    transform 0.2s,
    box-shadow 0.2s;
  opacity: 0;
  animation: gen-stat-in 0.55s cubic-bezier(0.19, 1, 0.22, 1) 550ms both;
}
@media (hover: hover) and (pointer: fine) {
  .gen-reveal-cta:hover {
    transform: translateY(-2px);
    box-shadow: 0 14px 28px -10px oklch(0.55 0.18 145 / 0.65);
  }
}

[data-theme="dark"] .gen-reveal-stat {
  background: oklch(0.22 0.015 85);
  border-color: oklch(0.3 0.015 85);
}
[data-theme="dark"] .gen-reveal-stat-num {
  color: var(--paille, #e8c547);
}
[data-theme="dark"] .gen-reveal-chip {
  background: oklch(0.28 0.04 70);
  color: var(--paille, #e8c547);
  border-color: oklch(0.45 0.08 72);
}

@media (max-width: 480px) {
  .gen-reveal-stats {
    grid-template-columns: repeat(2, 1fr);
  }
  .gen-reveal-title {
    font-size: clamp(28px, 8vw, 36px);
  }
}

/* ── Menu hero flash (page menu, après génération fraîche) ── */
.menu-fresh-flash {
  margin: -4px 0 20px;
  padding: 14px 18px;
  border-radius: 16px;
  background: linear-gradient(135deg, var(--accent-tint), oklch(0.95 0.035 100));
  border: 1px solid oklch(0.82 0.08 72 / 0.5);
  display: flex;
  align-items: center;
  gap: 14px;
  animation: gen-reveal-in 0.6s cubic-bezier(0.19, 1, 0.22, 1) both;
}
.menu-fresh-flash-icon {
  font-size: 28px;
  line-height: 1;
  flex-shrink: 0;
}
.menu-fresh-flash-title {
  font-family: var(--font-display);
  font-size: 18px;
  line-height: 1.15;
  color: var(--brick-deep, #8a3526);
  margin: 0 0 2px;
}
.menu-fresh-flash-sub {
  font-size: 13.5px;
  color: var(--muted, #666);
  line-height: 1.35;
}
[data-theme="dark"] .menu-fresh-flash {
  background: linear-gradient(135deg, oklch(0.28 0.04 70), oklch(0.24 0.03 60));
  border-color: oklch(0.5 0.08 72 / 0.4);
}
[data-theme="dark"] .menu-fresh-flash-title {
  color: var(--paille, #e8c547);
}

/* Stagger reveal des onglets jours quand ?fresh=1 */
body.menu-fresh .menu-day {
  opacity: 0;
  transform: translateY(10px);
  animation: menu-day-in 0.5s cubic-bezier(0.19, 1, 0.22, 1) both;
}
body.menu-fresh .menu-day:nth-child(1) {
  animation-delay: 60ms;
}
body.menu-fresh .menu-day:nth-child(2) {
  animation-delay: 120ms;
}
body.menu-fresh .menu-day:nth-child(3) {
  animation-delay: 180ms;
}
body.menu-fresh .menu-day:nth-child(4) {
  animation-delay: 240ms;
}
body.menu-fresh .menu-day:nth-child(5) {
  animation-delay: 300ms;
}
body.menu-fresh .menu-day:nth-child(6) {
  animation-delay: 360ms;
}
body.menu-fresh .menu-day:nth-child(7) {
  animation-delay: 420ms;
}
@keyframes menu-day-in {
  to {
    opacity: 1;
    transform: none;
  }
}

body.menu-fresh .menu-spread {
  animation: menu-spread-in 0.7s cubic-bezier(0.19, 1, 0.22, 1) 500ms both;
}
@keyframes menu-spread-in {
  from {
    opacity: 0;
    transform: translateY(16px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .gen-reveal,
  .gen-reveal-stat,
  .gen-reveal-chip,
  .gen-reveal-cta,
  .menu-fresh-flash,
  body.menu-fresh .menu-day,
  body.menu-fresh .menu-spread,
  .gen-reveal-burst span {
    animation: none !important;
    opacity: 1 !important;
    transform: none !important;
  }
}

/* ── Génération menu : écran de chargement éditorial ────── */
.gen-loading {
  max-width: 640px;
  margin: 40px auto;
  padding: 0 20px;
}
.gen-loading-card {
  background: var(--paper-sheet);
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  padding: clamp(32px, 5vw, 56px);
  text-align: center;
  position: relative;
  overflow: hidden;
  animation: fadeInUp 0.5s ease;
}
.gen-loading-card::before {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(ellipse at 50% -20%, oklch(0.59 0.16 143 / 0.08), transparent 60%);
  pointer-events: none;
}
.gen-loading-emoji {
  font-size: 72px;
  line-height: 1;
  margin-bottom: 24px;
  animation: chefBounce 2s ease-in-out infinite;
}
@keyframes chefBounce {
  0%,
  100% {
    transform: translateY(0) rotate(-2deg);
  }
  50% {
    transform: translateY(-10px) rotate(2deg);
  }
}
.gen-loading-title {
  font-family: var(--font-display);
  font-size: clamp(26px, 4vw, 38px);
  color: var(--ink);
  margin-bottom: 12px;
  letter-spacing: -0.5px;
}
.gen-loading-lede {
  font-size: 15px;
  color: var(--ink-muted);
  max-width: 420px;
  margin: 0 auto 36px;
  line-height: 1.55;
}
.gen-steps {
  list-style: none;
  padding: 0;
  margin: 0 0 32px;
  text-align: left;
  max-width: 380px;
  margin-left: auto;
  margin-right: auto;
}
.gen-step {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 10px 0;
  opacity: 0.4;
  transition: opacity 0.4s;
}
.gen-step.is-active {
  opacity: 1;
}
.gen-step.is-done {
  opacity: 0.7;
}
.gen-step-dot {
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--border);
  flex-shrink: 0;
  position: relative;
  transition: background 0.3s;
}
.gen-step.is-active .gen-step-dot {
  background: var(--brand-dark);
  box-shadow: 0 0 0 4px oklch(0.59 0.16 143 / 0.15);
  animation: genPulse 1.5s ease-in-out infinite;
}
.gen-step.is-done .gen-step-dot {
  background: var(--brand-dark);
}
.gen-step.is-done .gen-step-dot::after {
  content: "✓";
  position: absolute;
  inset: 0;
  color: var(--cream-fixed);
  font-size: 9px;
  font-weight: 900;
  display: flex;
  align-items: center;
  justify-content: center;
}
@keyframes genPulse {
  0%,
  100% {
    box-shadow: 0 0 0 4px oklch(0.59 0.16 143 / 0.15);
  }
  50% {
    box-shadow: 0 0 0 10px oklch(0.59 0.16 143 / 0.05);
  }
}
.gen-step-text {
  font-size: 14.5px;
  color: var(--ink);
  font-weight: 500;
}
.gen-step.is-active .gen-step-text {
  font-weight: 600;
}
.gen-loading-meta {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  font-size: 13px;
  color: var(--ink-muted);
  font-variant-numeric: tabular-nums;
}
.gen-loading-meta #genMessage {
  transition: opacity 0.3s;
  font-family: var(--font-display);
  font-style: italic;
  color: var(--brand-dark);
}
.gen-loading-sep {
  width: 3px;
  height: 3px;
  border-radius: 50%;
  background: var(--border);
  display: inline-block;
}

/* Cards éducatives sur la page loading 2026-05-09 (Phase 2) :
   au lieu d'un demo menu fake, l'user apprend les features clés
   pendant que Sonnet travaille sur ses vraies données. Pas
   d'agression marketing : 3 liens concrets vers /recu, /frigo,
   /rapport-finances. Cliquer = explorer + le menu continue de
   se générer en arrière-plan. */
.gen-loading-edu {
  margin-top: 28px;
  padding-top: 24px;
  border-top: 1px dashed var(--border);
}
.gen-loading-edu-title {
  font-family: var(--font-display, var(--font-body));
  font-size: 14px;
  font-weight: 400;
  color: var(--ink-muted);
  margin: 0 0 14px;
  text-align: center;
  letter-spacing: -0.005em;
}
.gen-loading-edu-cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 10px;
}
.gen-loading-edu-card {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 14px 16px;
  background: var(--paper-soft, var(--paper));
  border: 1px solid var(--border);
  border-radius: 10px;
  text-decoration: none;
  color: inherit;
  transition:
    background 0.15s ease,
    border-color 0.15s ease,
    transform 0.1s ease;
  min-height: 44px;
}
@media (hover: hover) and (pointer: fine) {
  .gen-loading-edu-card:hover,
  .gen-loading-edu-card:focus-visible {
    background: var(--accent-tint, color-mix(in oklch, var(--brand) 6%, var(--paper)));
    border-color: color-mix(in oklch, var(--brand) 30%, var(--border));
    outline: none;
  }
}
.gen-loading-edu-card:focus-visible {
  box-shadow:
    0 0 0 2px var(--brand-dark, var(--brand)),
    0 0 0 4px var(--paper);
}
.gen-loading-edu-card:active {
  transform: translateY(1px);
}
.gen-loading-edu-emoji {
  flex-shrink: 0;
  font-family: "Young Serif", Georgia, serif;
  font-size: 22px;
  line-height: 1;
  margin-top: -2px;
  color: var(--brand-dark, #355c4d);
  min-width: 28px;
  letter-spacing: -0.02em;
}
.gen-loading-edu-body {
  display: flex;
  flex-direction: column;
  gap: 3px;
}
.gen-loading-edu-card-title {
  font-size: 13px;
  font-weight: 600;
  color: var(--ink);
  line-height: 1.3;
}
.gen-loading-edu-card-lede {
  font-size: 12px;
  color: var(--ink-soft);
  line-height: 1.45;
}

.gen-loading-error {
  margin-top: 24px;
  padding: 16px;
  background: oklch(0.44 0.14 25 / 0.08);
  border: 1px solid oklch(0.44 0.14 25 / 0.2);
  border-radius: var(--radius);
  color: var(--danger);
}
.gen-loading-error p {
  margin-bottom: 12px;
  font-size: 14px;
}

/* Annuler — lien discret sous la barre de progression, pas un CTA,
   juste une porte de sortie pour qui a changé d'avis. */
.gen-loading-cancel {
  margin-top: 24px;
  text-align: center;
}
.gen-loading-cancel-btn {
  background: none;
  border: none;
  font-family: inherit;
  font-size: 13px;
  color: var(--ink-muted);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-color: var(--border);
  padding: 10px 16px;
  min-height: 44px;
  cursor: pointer;
  transition: color 0.15s;
}
@media (hover: hover) and (pointer: fine) {
  .gen-loading-cancel-btn:hover {
    color: var(--danger);
    text-decoration-color: var(--danger);
  }
}

/* ── Astuce bandeau (toast-like contextuel) ──────────────── */
.astuce-bandeau {
  background: var(--paper-sheet);
  border: 1px solid oklch(0.59 0.16 143 / 0.18);
  border-radius: var(--radius);
  padding: 14px 20px;
  margin-bottom: 20px;
  font-family: var(--font-display);
  font-size: 15px;
  font-style: italic;
  color: var(--brand-dark);
  animation: fadeInUp 0.6s ease both;
  animation-delay: 0.2s;
}

/* ── Mode cuisson fullscreen ─────────────────────────────── */
/* ── Mode cuisson fullscreen — « tu cuisines, rien ne te distrait »
   Esthétique cookbook magazine : typo Young Serif dominante sur fond
   paper crème, ornements éditoriaux, swipe gestures, haptic par étape.
   Zéro chrome superflu. Progress bar filament signale l'avancée. */
.cook-mode[hidden] {
  display: none !important;
}
.cook-mode {
  position: fixed;
  inset: 0;
  z-index: 9997;
  background: var(--paper);
  display: grid;
  grid-template-rows: auto auto 1fr auto auto;
  animation: cookModeIn 0.35s cubic-bezier(0.22, 1, 0.36, 1);
}
@keyframes cookModeIn {
  from {
    opacity: 0;
    transform: scale(0.96);
  }
  to {
    opacity: 1;
    transform: scale(1);
  }
}

/* Progress bar filament fine en haut de l'écran, remplie à mesure. */
.cook-progress-bar {
  height: 3px;
  background: var(--paper-soft);
  position: relative;
  margin-top: env(safe-area-inset-top);
}
.cook-progress-fill {
  height: 100%;
  background: linear-gradient(90deg, var(--brand), var(--brand-dark));
  width: 100%;
  transform: scaleX(var(--progress, 0));
  transform-origin: left center;
  transition: transform 0.5s cubic-bezier(0.22, 1, 0.36, 1);
}

/* Top bar : close à gauche, progress label centre, timer à droite. */
.cook-mode-bar {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: 14px;
  padding: 14px calc(16px + env(safe-area-inset-right)) 14px calc(16px + env(safe-area-inset-left));
}
.cook-close {
  width: 44px;
  height: 44px;
  border: none;
  background: var(--paper-soft);
  border-radius: 50%;
  cursor: pointer;
  color: var(--ink-muted);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition:
    background 0.15s,
    color 0.15s,
    transform 0.12s;
}
@media (hover: hover) and (pointer: fine) {
  .cook-close:hover {
    background: var(--border);
    color: var(--ink);
  }
}
.cook-close:active {
  transform: scale(0.94);
}
.cook-progress-label {
  text-align: center;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink-muted);
  font-variant-numeric: tabular-nums;
}
.cook-timer-btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px 14px;
  border-radius: 980px;
  background: var(--accent-tint);
  border: 1px solid var(--accent-tint2);
  color: var(--accent-deep);
  font-weight: 600;
  cursor: pointer;
  transition:
    background 0.15s,
    transform 0.12s;
}
.cook-timer-btn.is-running {
  background: var(--brand);
  color: var(--cream-fixed);
  border-color: var(--brand-dark);
}
.cook-timer-btn:active {
  transform: scale(0.96);
}
.cook-timer {
  font-family: var(--font-display);
  font-size: 16px;
  font-variant-numeric: tabular-nums;
}
.cook-timer-ico {
  font-size: 12px;
}

/* Content — typographie dominante, stagger reveal au changement d'étape. */
.cook-mode-content {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  padding: 24px calc(28px + env(safe-area-inset-right)) 24px calc(28px + env(safe-area-inset-left));
  max-width: 780px;
  margin: 0 auto;
  width: 100%;
  overflow-y: auto;
}
.cook-mode-eyebrow {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--brand-dark);
  margin-bottom: 14px;
  animation: cookFadeIn 0.5s ease 0.1s both;
  /* Ornement typo : filet fin avant le texte, signe éditorial cookbook */
  display: inline-flex;
  align-items: center;
  gap: 12px;
}
.cook-mode-eyebrow::before {
  content: "";
  width: 24px;
  height: 1px;
  background: var(--brand-dark);
  opacity: 0.55;
}
.cook-recipe-name {
  font-family: var(--font-display);
  font-size: clamp(22px, 3.5vw, 28px);
  font-weight: 400;
  color: var(--ink-muted);
  margin-bottom: 28px;
  line-height: 1.2;
  animation: cookFadeIn 0.5s ease 0.15s both;
}

/* Wrap pour contrôler les transitions step. */
.cook-step-wrap {
  position: relative;
  min-height: 180px;
}
.cook-step {
  font-family: var(--font-display);
  font-size: clamp(30px, 5.5vw, 52px);
  font-weight: 400;
  line-height: 1.2;
  color: var(--ink);
  letter-spacing: -0.015em;
}
.cook-step.is-leaving {
  animation: cookStepOut 0.25s cubic-bezier(0.55, 0, 0.68, 0.18) forwards;
}
.cook-step.is-entering {
  animation: cookStepIn 0.35s cubic-bezier(0.22, 1, 0.36, 1) both;
}
@keyframes cookStepIn {
  from {
    opacity: 0;
    transform: translateY(14px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}
@keyframes cookStepOut {
  from {
    opacity: 1;
    transform: translateY(0);
  }
  to {
    opacity: 0;
    transform: translateY(-14px);
  }
}
@keyframes cookFadeIn {
  from {
    opacity: 0;
    transform: translateY(8px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* Footer actions — 2 boutons, next dominant */
.cook-mode-footer {
  display: grid;
  grid-template-columns: 68px 1fr;
  gap: 10px;
  padding: 16px calc(20px + env(safe-area-inset-right)) calc(20px + env(safe-area-inset-bottom))
    calc(20px + env(safe-area-inset-left));
  border-top: 1px solid var(--border);
  background: var(--paper-sheet);
}
.cook-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 56px;
  padding: 0 20px;
  border-radius: 14px;
  cursor: pointer;
  font-family: var(--font-body);
  font-size: 16px;
  font-weight: 600;
  transition:
    background 0.15s,
    transform 0.12s,
    box-shadow 0.15s;
}
.cook-btn--prev {
  background: var(--paper-soft);
  border: 1px solid var(--border);
  color: var(--ink-muted);
}
.cook-btn--prev:active {
  transform: scale(0.96);
}
.cook-btn--prev:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}
.cook-btn--next {
  background: var(--brand);
  color: var(--cream-fixed);
  border: none;
  box-shadow: 0 2px 8px oklch(0.59 0.16 143 / 0.3);
}
@media (hover: hover) and (pointer: fine) {
  .cook-btn--next:hover {
    box-shadow: 0 4px 14px oklch(0.59 0.16 143 / 0.42);
  }
}
.cook-btn--next:active {
  transform: scale(0.98);
}
.cook-btn--next.is-done {
  background: var(--brand-dark);
}

/* Hint swipe — apparaît 2s puis fade out */
.cook-swipe-hint {
  position: fixed;
  bottom: calc(96px + env(safe-area-inset-bottom));
  left: 50%;
  transform: translateX(-50%);
  font-size: 12px;
  color: var(--ink-muted);
  opacity: 0;
  pointer-events: none;
  animation: cookHint 4s ease both;
}
@keyframes cookHint {
  0% {
    opacity: 0;
  }
  12% {
    opacity: 1;
  }
  75% {
    opacity: 1;
  }
  100% {
    opacity: 0;
  }
}

@media (max-width: 640px) {
  .cook-mode-content {
    padding-top: 18px;
    padding-bottom: 18px;
  }
  .cook-recipe-name {
    font-size: 18px;
    margin-bottom: 20px;
  }
  .cook-step {
    font-size: clamp(26px, 7vw, 36px);
  }
  .cook-step-wrap {
    min-height: 140px;
  }
  .cook-mode-eyebrow {
    font-size: 11px;
  }
  .cook-timer {
    font-size: 15px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .cook-mode,
  .cook-step.is-leaving,
  .cook-step.is-entering,
  .cook-mode-eyebrow,
  .cook-recipe-name,
  .cook-swipe-hint {
    animation: none;
  }
  .cook-progress-fill {
    transition: none;
  }
}

/* Bouton Commencer à cuisiner — met en valeur */
.cook-mode-btn {
  background: linear-gradient(135deg, var(--danger), var(--brick-deep));
  color: var(--cream-fixed);
  border-color: var(--brick-deep);
}
@media (hover: hover) and (pointer: fine) {
  .cook-mode-btn:hover {
    background: linear-gradient(135deg, var(--brick-deep), var(--danger));
  }
}
/* Greeting contextuel */
.dash-hero-context {
  font-family: var(--font-display);
  font-size: 16px;
  font-style: italic;
  color: var(--ink-soft);
  margin-top: 8px;
  line-height: 1.4;
  animation: fadeInUp 0.6s ease both;
  animation-delay: 0.3s;
}
@keyframes fadeInUp {
  from {
    opacity: 0;
    transform: translateY(8px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}
.dash-hero-ring-center {
  text-align: center;
  position: relative;
}
.dash-hero-ring-pct {
  font-family: var(--font-display);
  font-size: 42px;
  color: var(--ink);
  line-height: 1;
}
.dash-hero-ring-pct span {
  font-size: 22px;
  color: var(--ink-muted);
}
.dash-hero-ring-lbl {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  color: var(--ink-muted);
  margin-top: 4px;
}

/* KPIs */
.dash-hero-numbers {
  display: flex;
  flex-direction: column;
  gap: 16px;
}
/* .dash-hero-kpi* base classes retirées 2026-05-18 — KPI déplacés
   vers tab Ma semaine (.dash-week-kpi) en PR #105. Variant mobile
   --secondary plus bas et fragment responsive @media (max-width 900)
   retirés du même coup (audit pass 3 cleanup). */
/* Contexte temporel sous le ring : « Semaine 18 · 22 $/jour jusqu'à
   dimanche ». Réduit l'anxiété budget en donnant un repère
   actionnable plutôt qu'un % abstrait. */
.dash-hero-ring-context {
  margin-top: 8px;
  font-size: 12px;
  color: var(--ink-soft);
  text-align: center;
  line-height: 1.5;
  font-feature-settings: "tnum" 1;
}
.dash-hero-ring-context strong {
  color: var(--ink);
  font-weight: 700;
}

/* Quick actions — pilules compactes intégrées */
.dash-hero-actions {
  position: relative;
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}
.dash-hero-action {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px 16px;
  border-radius: 980px;
  background: var(--paper-sheet);
  border: 1px solid var(--border);
  font-size: 13px;
  font-weight: 600;
  color: var(--ink-soft);
  text-decoration: none;
  transition:
    transform 0.2s,
    opacity 0.2s,
    color 0.2s,
    background 0.2s,
    border-color 0.2s,
    box-shadow 0.2s;
}
.dash-hero-action-lead {
  font-family: var(--font-display);
  font-size: 15px;
  font-weight: 400;
  color: var(--brand-dark);
  line-height: 1;
}
@media (hover: hover) and (pointer: fine) {
  .dash-hero-action:hover {
    background: var(--accent-tint);
    border-color: var(--brand-dark);
    color: var(--brand-dark);
    transform: translateY(-1px);
  }
}
@media (hover: hover) and (pointer: fine) {
  .dash-hero-action--urgent:hover {
    background: var(--accent-tint);
    border-color: var(--brand-dark);
    color: var(--brand-dark);
  }
}

/* ── « Pour toi » éditorial — Chantier 3 ──────────────────────
   Section cookbook magazine : ton menu du soir, ta dernière recette
   aimée, les aubaines qui matchent ton frigo. Personnel, contextuel,
   typographique. Grid responsif : 1 col mobile, 2 tablet, 3 desktop. */
.dash-for-you {
  margin: 36px 0 40px;
  position: relative;
}
.dash-for-you-head {
  margin-bottom: 22px;
}
.dash-for-you-eyebrow {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--brand-dark);
  margin-bottom: 6px;
}
.dash-for-you-title {
  font-family: var(--font-display);
  font-size: clamp(24px, 3.4vw, 34px);
  font-weight: 400;
  line-height: 1.15;
  letter-spacing: -0.01em;
  color: var(--ink);
}
.dash-for-you-title em {
  font-style: italic;
  color: var(--brand-dark);
}

.dash-for-you-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 14px;
}
@media (min-width: 640px) {
  .dash-for-you-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}
@media (min-width: 1024px) {
  .dash-for-you-grid {
    grid-template-columns: repeat(3, 1fr);
  }
}

.dash-for-you-card {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 22px 22px 18px;
  min-height: 200px;
  background: var(--paper-sheet);
  border: 1px solid var(--border);
  border-radius: var(--radius-xl, 18px);
  color: var(--ink);
  text-decoration: none;
  transition:
    background 0.2s ease,
    border-color 0.2s ease,
    transform 0.15s ease;
}
@media (hover: hover) and (pointer: fine) {
  .dash-for-you-card:hover {
    background: var(--paper-soft);
    border-color: var(--brand);
    transform: translateY(-2px);
  }
}
.dash-for-you-card:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 3px;
}

.dash-for-you-card-eyebrow {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-muted);
}
.dash-for-you-card-title {
  font-family: var(--font-display);
  font-size: 22px;
  font-weight: 400;
  line-height: 1.15;
  letter-spacing: -0.01em;
  color: var(--ink);
  font-style: italic;
}
.dash-for-you-card-sub {
  font-size: 14px;
  line-height: 1.5;
  color: var(--ink-muted);
}
.dash-for-you-card-cta {
  margin-top: auto;
  font-size: 13px;
  font-weight: 600;
  color: var(--brand-dark);
  letter-spacing: 0.01em;
  padding-top: 8px;
}

/* Variante « ce soir » : tint accent léger, plus proéminent */
.dash-for-you-card--tonight {
  background: var(--accent-tint);
  border-color: var(--accent-tint2);
}
@media (hover: hover) and (pointer: fine) {
  .dash-for-you-card--tonight:hover {
    background: var(--paper-sheet);
    border-color: var(--brand);
  }
}

/* Variante « aubaines » : liste interne */
.dash-for-you-aubaines {
  list-style: none;
  margin: 6px 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.dash-for-you-aubaines li {
  display: flex;
  align-items: baseline;
  gap: 8px;
  font-size: 13px;
  padding: 8px 0;
  border-bottom: 1px solid var(--border);
}
.dash-for-you-aubaines li:last-child {
  border-bottom: none;
}
.dash-for-you-aubaine-name {
  flex: 1;
  color: var(--ink);
  font-weight: 500;
}
.dash-for-you-aubaine-price {
  color: var(--brand-dark);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.dash-for-you-aubaine-store {
  font-size: 11px;
  color: var(--ink-muted);
  background: var(--paper-soft);
  padding: 2px 8px;
  border-radius: 999px;
}

@media (prefers-reduced-motion: reduce) {
  .dash-for-you-card {
    transition: none;
  }
  @media (hover: hover) and (pointer: fine) {
    .dash-for-you-card:hover {
      transform: none;
    }
  }
}

/* ── Composer Assistant permanent — Chantier 2 ─────────────────
   Barre fixe au-dessus du tabbar mobile (ou en bas-centre desktop).
   Pill cream éditoriale, icône horloge (le temps que l'Assistant fait
   gagner), brand voice grand-maman québécoise. Tap → bottom sheet
   slide-up avec suggestions + input. */
.composer-bar {
  position: fixed;
  left: 50%;
  bottom: calc(70px + env(safe-area-inset-bottom));
  transform: translateX(-50%);
  z-index: 85;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  width: calc(100% - 24px);
  max-width: 520px;
  padding: 12px 16px;
  min-height: 52px;
  background: var(--paper-sheet);
  border: 1px solid var(--border);
  border-radius: 999px;
  box-shadow: 0 6px 24px oklch(0.22 0.015 75 / 0.12);
  color: var(--ink-muted);
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
  text-align: left;
  transition:
    transform 0.15s ease,
    box-shadow 0.2s ease,
    border-color 0.15s ease;
}
@media (hover: hover) and (pointer: fine) {
  .composer-bar:hover {
    transform: translateX(-50%) translateY(-2px);
    box-shadow: 0 10px 32px oklch(0.22 0.015 75 / 0.18);
    border-color: var(--brand);
  }
}
.composer-bar:active {
  transform: translateX(-50%) translateY(0);
}
.composer-bar:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 3px;
}
.composer-bar-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  background: var(--brand);
  color: var(--cream-fixed);
  border-radius: 50%;
  flex-shrink: 0;
}
.composer-bar-glyph {
  font-family: var(--font-display, "Young Serif", serif);
  font-size: 17px;
  font-weight: 400;
  line-height: 1;
  padding-bottom: 2px;
}
.composer-bar-text {
  flex: 1;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.composer-bar-mic {
  color: var(--ink-muted);
  flex-shrink: 0;
}
/* Desktop : barre centrée, plus discrète */
@media (min-width: 900px) {
  .composer-bar {
    bottom: 24px;
    max-width: 420px;
  }
}

/* Bottom sheet — slide-up depuis le bas. Panel cream, handle, close. */
.composer-sheet[hidden] {
  display: none !important;
}
.composer-sheet {
  position: fixed;
  inset: 0;
  z-index: 9990;
  display: flex;
  align-items: flex-end;
  animation: composerFadeIn 0.2s ease both;
}
.composer-sheet-backdrop {
  position: absolute;
  inset: 0;
  background: oklch(0.18 0.015 110 / 0.55);
  cursor: pointer;
}
.composer-sheet-panel {
  position: relative;
  width: 100%;
  max-width: 560px;
  margin: 0 auto;
  background: var(--paper-sheet);
  border-radius: 24px 24px 0 0;
  padding: 8px 20px calc(20px + env(safe-area-inset-bottom));
  max-height: 85vh;
  display: flex;
  flex-direction: column;
  box-shadow: 0 -8px 32px oklch(0.22 0.016 75 / 0.25);
  animation: composerSlideUp 0.35s cubic-bezier(0.22, 1, 0.36, 1) both;
}
.composer-sheet-handle {
  width: 44px;
  height: 5px;
  background: var(--border);
  border-radius: 3px;
  margin: 6px auto 14px;
}
.composer-sheet-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 18px;
}
.composer-sheet-eyebrow {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--brand-dark);
  margin-bottom: 6px;
}
.composer-sheet-title {
  font-family: var(--font-display);
  font-size: 22px;
  line-height: 1.2;
  color: var(--ink);
  font-weight: 400;
  font-style: italic;
}
.composer-sheet-close {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  border: none;
  background: var(--paper-soft);
  color: var(--ink-muted);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition:
    background 0.15s,
    color 0.15s;
  flex-shrink: 0;
}
@media (hover: hover) and (pointer: fine) {
  .composer-sheet-close:hover {
    background: var(--border);
    color: var(--ink);
  }
}

.composer-sheet-body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  margin-bottom: 14px;
  -webkit-overflow-scrolling: touch;
}
.composer-suggestions-label {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-muted);
  margin-bottom: 12px;
}
.composer-suggestions {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.composer-suggestion {
  display: block;
  width: 100%;
  padding: 14px 16px;
  background: var(--paper-soft);
  border: 1px solid var(--border);
  border-radius: 14px;
  color: var(--ink);
  font-size: 14px;
  text-align: left;
  cursor: pointer;
  transition:
    background 0.15s,
    border-color 0.15s,
    transform 0.12s;
}
@media (hover: hover) and (pointer: fine) {
  .composer-suggestion:hover {
    background: var(--paper-sheet);
    border-color: var(--brand);
  }
}
.composer-suggestion:active {
  transform: scale(0.985);
}
.composer-suggestion:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
}

/* Thread — messages user + assistant */
.composer-thread {
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.composer-msg {
  padding: 12px 16px;
  border-radius: 16px;
  font-size: 14px;
  line-height: 1.5;
  max-width: 85%;
}
.composer-msg--user {
  align-self: flex-end;
  background: var(--brand);
  color: var(--cream-fixed);
  border-bottom-right-radius: 4px;
}
.composer-msg--assistant {
  align-self: flex-start;
  background: var(--paper-soft);
  color: var(--ink);
  border-bottom-left-radius: 4px;
}
.composer-msg--thinking {
  align-self: flex-start;
  background: var(--paper-soft);
  color: var(--ink-muted);
  font-style: italic;
}
.composer-msg--thinking::after {
  content: "";
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--ink-muted);
  margin-left: 6px;
  animation: composerPulse 1s ease-in-out infinite;
}
@keyframes composerPulse {
  0%,
  100% {
    opacity: 0.3;
  }
  50% {
    opacity: 1;
  }
}

/* Input form */
.composer-sheet-form {
  margin-top: auto;
}
.composer-sheet-input-wrap {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 4px 4px 4px 18px;
  background: var(--paper-soft);
  border: 1px solid var(--border);
  border-radius: 999px;
  transition: border-color 0.15s;
}
.composer-sheet-input-wrap:focus-within {
  border-color: var(--brand);
}
.composer-sheet-input {
  flex: 1;
  border: none;
  outline: none;
  background: transparent;
  font-size: 16px; /* >= 16 empêche iOS zoom */
  color: var(--ink);
  padding: 10px 0;
  font-family: var(--font-body);
}
.composer-sheet-input::placeholder {
  color: var(--ink-muted);
}
.composer-sheet-send {
  width: 40px;
  height: 40px;
  border: none;
  border-radius: 50%;
  background: var(--brand);
  color: var(--cream-fixed);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition:
    background 0.15s,
    transform 0.12s;
  flex-shrink: 0;
}
@media (hover: hover) and (pointer: fine) {
  .composer-sheet-send:hover {
    background: var(--brand-dark);
  }
}
.composer-sheet-send:active {
  transform: scale(0.94);
}
.composer-sheet-send:disabled {
  background: var(--border);
  color: var(--ink-muted);
  cursor: not-allowed;
}

@keyframes composerFadeIn {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}
@keyframes composerSlideUp {
  from {
    transform: translateY(100%);
  }
  to {
    transform: translateY(0);
  }
}

@media (prefers-reduced-motion: reduce) {
  .composer-bar,
  .composer-suggestion,
  .composer-sheet-send {
    transition: none;
  }
  .composer-sheet,
  .composer-sheet-panel,
  .composer-msg--thinking::after {
    animation: none;
  }
}

/* Cacher le composer quand cook-mode ouvert (immersion) */
body:has(.cook-mode:not([hidden])) .composer-bar {
  display: none;
}

/* ── CTA éditorial : 1 action primaire + liens secondaires ────
   Remplace l'ancienne grille de 5 bulles (dash-hero-actions) par
   un single CTA « Souper express » + une ligne de liens discrets.
   Hiérarchie claire, zéro bruit. --------------------------------- */
.dash-cta {
  display: flex;
  flex-direction: column;
  gap: 14px;
  margin-top: 12px;
}
.dash-cta-primary {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 18px 22px;
  background: var(--paper-sheet);
  /* iOS app feel : pas de border 1px (lit « page web cardée »).
     Élévation subtile via box-shadow = pattern card-native. */
  border-radius: var(--radius-xl, 16px);
  box-shadow:
    0 1px 2px rgba(0, 0, 0, 0.03),
    0 4px 14px rgba(0, 0, 0, 0.04);
  text-decoration: none;
  color: var(--ink);
  transition:
    background 0.2s ease,
    box-shadow 0.2s ease,
    transform 0.15s ease;
}
/* iOS Safari sticky :hover fix — sur touch device le :hover persiste après
   tap → fond accent-tint vert restait visible. @media (hover: hover) +
   (pointer: fine) cible ONLY les devices avec vraie souris (desktop). */
@media (hover: hover) and (pointer: fine) {
  .dash-cta-primary:hover {
    background: var(--accent-tint);
    box-shadow:
      0 2px 4px rgba(74, 158, 70, 0.08),
      0 8px 24px rgba(74, 158, 70, 0.1);
    transform: translateY(-1px);
  }
}
.dash-cta-primary:active {
  transform: translateY(0);
}
/* Variante secondaire (Scanner) : même structure que primary mais
   subtilement moins dominante visuellement — fond cream un cran plus
   bas, sans hover labrador agressif. Garde la hiérarchie : Souper
   express domine, Scanner le suit à un demi-ton. */
.dash-cta-primary--alt {
  background: var(--paper-soft);
}
@media (hover: hover) and (pointer: fine) {
  .dash-cta-primary--alt:hover {
    background: var(--accent-tint);
    border-color: var(--accent);
  }
}
.dash-cta-primary:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 3px;
  border-radius: var(--radius-xl, 16px);
}
/* Variante FIRSTRUN : premier user, jamais de menu — primary
   visuellement dominant (background brand, ink inverse). C'est le
   seul CTA dans la page, on assume sa visibilité. */
.dash-cta-primary--firstrun {
  background: var(--brand-dark, var(--brand));
  border-color: var(--brand-dark, var(--brand));
  color: var(--paper, #faf6ec);
  width: 100%;
  font-family: inherit;
  font-size: inherit;
  text-align: left;
  cursor: pointer;
}
@media (hover: hover) and (pointer: fine) {
  .dash-cta-primary--firstrun:hover {
    background: var(--brand);
    transform: translateY(-1px);
  }
}
.dash-cta-primary--firstrun .dash-cta-sub {
  color: color-mix(in oklch, var(--paper) 85%, var(--brand));
  opacity: 0.92;
}
/* Override critique : .dash-cta-title set color:var(--ink) (noir) plus bas,
   ce qui écrase color:var(--paper) du parent --firstrun → titre noir illisible
   sur fond brand-dark. Match la couleur paper du parent pour le contraste. */
.dash-cta-primary--firstrun .dash-cta-title {
  color: var(--paper, #faf6ec);
}
.dash-cta-firstrun {
  margin: 0;
}
/* CTA secondary typo-only inline (sous le primary), évite le double
   primary visuel concurrent. Pattern Linear/Notion. */
.dash-cta-secondary {
  display: inline-block;
  padding: 8px 0 0;
  margin-bottom: 12px;
  font-size: 13px;
  color: var(--ink-muted);
  text-decoration: none;
  letter-spacing: 0.01em;
  align-self: center;
  /* Avant : border-bottom 1px dotted créait une ligne horizontale qui,
     combinée au dash-section-head border-bottom de la section suivante,
     lisait comme un séparateur de tableau (« continuité tableau »).
     Maintenant : la flèche + le color hover suffisent pour l'affordance
     link. Underline réapparaît au hover pour confirmer interactivité. */
  transition: color 0.15s ease;
}
@media (hover: hover) and (pointer: fine) {
  .dash-cta-secondary:hover {
    color: var(--brand-dark, var(--brand));
  }
}
@media (hover: hover) and (pointer: fine) {
  .dash-cta-secondary:hover {
    color: var(--brand-dark, var(--brand));
    text-decoration: underline;
    text-underline-offset: 3px;
  }
}
.dash-cta-emoji {
  font-size: 28px;
  line-height: 1;
  flex-shrink: 0;
}
.dash-cta-body {
  display: flex;
  flex-direction: column;
  gap: 2px;
  flex: 1;
  min-width: 0;
}
.dash-cta-title {
  font-family: var(--font-display, "Young Serif", serif);
  font-size: clamp(18px, 4vw, 22px);
  font-weight: 400;
  color: var(--ink);
  line-height: 1.15;
  overflow-wrap: break-word;
  hyphens: none;
}
.dash-cta-sub {
  font-size: 15px;
  color: var(--ink-muted);
  line-height: 1.45;
}
.dash-cta-arrow {
  font-size: 20px;
  color: var(--brand-dark);
  flex-shrink: 0;
  transition: transform 0.2s ease;
}
@media (hover: hover) and (pointer: fine) {
  .dash-cta-primary:hover .dash-cta-arrow {
    transform: translateX(3px);
  }
}

/* ── Scanner auto — bouton wow primaire de la section scan ─────
   1 photo, l'IA classe (reçu/frigo/produit) et redirige. Le réflexe
   par défaut. Style outline brand pour le distinguer des cards plates
   en dessous. */
.dash-scan-auto {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 14px 18px;
  min-height: 64px;
  background: var(--accent-tint);
  border: 1px solid var(--accent-tint2);
  border-radius: var(--radius-lg, 14px);
  text-decoration: none;
  color: var(--accent-deep);
  margin-bottom: 12px;
  transition:
    background 0.2s ease,
    border-color 0.2s ease,
    transform 0.15s ease;
}
@media (hover: hover) and (pointer: fine) {
  .dash-scan-auto:hover {
    background: var(--paper-sheet);
    border-color: var(--brand);
    transform: translateY(-1px);
  }
}
.dash-scan-auto:active {
  transform: translateY(0);
}
.dash-scan-auto:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 3px;
}
.dash-scan-auto-icon {
  flex-shrink: 0;
  width: 40px;
  height: 40px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--brand);
  color: var(--cream-fixed);
  border-radius: 50%;
}
.dash-scan-auto-body {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
  flex: 1;
}
.dash-scan-auto-title {
  font-family: var(--font-display, "Young Serif", serif);
  font-size: 18px;
  font-weight: 400;
  color: var(--accent-deep);
  line-height: 1.15;
}
.dash-scan-auto-sub {
  font-size: 13px;
  color: var(--accent-deep);
  opacity: 0.82;
  line-height: 1.3;
}
.dash-scan-precise {
  font-size: 12px;
  color: var(--ink-muted);
  margin-bottom: 8px;
  padding: 0 4px;
  font-style: italic;
}

/* ── Scanner — sous-bloc 2 cards (Mon reçu / Mon frigo) ────────
   Différencie visuellement les 2 scans : intentions distinctes (après
   courses vs anytime), pas juste des labels texte. Hiérarchie tertiaire
   sous le CTA Souper express, primaire devant les chips secondaires. */
.dash-scan-section {
  margin-top: 4px;
}
.dash-scan-eyebrow {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.4px;
  text-transform: uppercase;
  color: var(--ink-muted);
  margin-bottom: 10px;
  padding: 0 4px;
}
.dash-scan-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 10px;
}
.dash-scan-card {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 16px 18px;
  min-height: 72px;
  background: var(--paper-sheet);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg, 14px);
  text-decoration: none;
  color: var(--ink);
  transition:
    background 0.2s ease,
    border-color 0.2s ease,
    transform 0.15s ease;
}
@media (hover: hover) and (pointer: fine) {
  .dash-scan-card:hover {
    background: var(--accent-tint);
    border-color: var(--brand);
    transform: translateY(-1px);
  }
}
.dash-scan-card:active {
  transform: translateY(0);
}
.dash-scan-card:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 3px;
  border-radius: var(--radius-lg, 14px);
}
.dash-scan-card-icon {
  flex-shrink: 0;
  width: 40px;
  height: 40px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--paper-soft);
  border-radius: 50%;
  color: var(--brand-dark);
  transition:
    background 0.2s ease,
    color 0.2s ease;
}
@media (hover: hover) and (pointer: fine) {
  .dash-scan-card:hover .dash-scan-card-icon {
    background: var(--paper-sheet);
  }
}
.dash-scan-card-body {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.dash-scan-card-title {
  font-family: var(--font-display, "Young Serif", serif);
  font-size: 18px;
  font-weight: 400;
  color: var(--ink);
  line-height: 1.15;
}
.dash-scan-card-sub {
  font-size: 13px;
  color: var(--ink-muted);
  line-height: 1.3;
}
@media (max-width: 480px) {
  /* Sur très petit écran : padding et icône réduits, mais font-size
     du sub reste à 13 px minimum (Grand-Maman policy floor pour meta). */
  .dash-scan-card {
    padding: 14px;
    gap: 10px;
  }
  .dash-scan-card-icon {
    width: 36px;
    height: 36px;
  }
  .dash-scan-card-title {
    font-size: 17px;
  }
  .dash-scan-card-sub {
    font-size: 13px;
  }
}
@media (prefers-reduced-motion: reduce) {
  .dash-scan-card,
  .dash-scan-card-icon {
    transition: none;
  }
  @media (hover: hover) and (pointer: fine) {
    .dash-scan-card:hover {
      transform: none;
    }
  }
}

@media (prefers-reduced-motion: reduce) {
  .dash-cta-primary,
  .dash-cta-arrow {
    transition: none;
  }
  @media (hover: hover) and (pointer: fine) {
    .dash-cta-primary:hover {
      transform: none;
    }
  }
  @media (hover: hover) and (pointer: fine) {
    .dash-cta-primary:hover .dash-cta-arrow {
      transform: none;
    }
  }
}

/* ── Ruban d'onglets intra-page (Mon frigo, Mon menu, Zéro gaspillage…)
   Classes .frigo-tabs / .frigo-tab historiques, gardées pour compat. ─── */
.frigo-tabs {
  display: flex;
  gap: 4px;
  padding: 4px;
  margin: 0 0 24px;
  background: var(--paper-soft);
  border-radius: 14px;
  border: 1px solid var(--border);
  overflow-x: auto;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.frigo-tabs::-webkit-scrollbar {
  display: none;
}
.frigo-tab {
  flex: 1 1 0;
  min-width: max-content;
  padding: 12px 18px;
  border-radius: 10px;
  font-weight: 600;
  font-size: 14px;
  text-align: center;
  text-decoration: none;
  color: var(--ink-muted);
  transition:
    background 0.15s ease,
    color 0.15s ease,
    box-shadow 0.15s ease;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
@media (hover: hover) and (pointer: fine) {
  .frigo-tab:hover {
    color: var(--ink);
  }
}
.frigo-tab.is-active {
  background: var(--paper-sheet);
  color: var(--ink);
  box-shadow: 0 1px 3px oklch(0.22 0.016 75 / 0.1);
}
.frigo-tab:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
@media (prefers-reduced-motion: reduce) {
  .frigo-tab {
    transition: none;
  }
}

/* ── Boutons d'actions sur cartes de recette (menu/index) ─────
   Rangée de pills label+icon en haut de la carte recette, AVANT
   l'eyebrow. Layout déterministe (pas d'absolute) : flex row qui
   wrappe naturellement, alignée à droite via margin-left:auto sur
   le 1er élément. Toujours visible, jamais clipped, touch 44 px. */
.menu-recipe-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  align-items: center;
  gap: 8px;
  margin-bottom: 14px;
}
.menu-recipe-action {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 8px 14px;
  min-height: 44px;
  border: 1px solid var(--border);
  background: var(--paper-sheet);
  color: var(--ink-muted);
  border-radius: 980px;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  transition:
    color 0.2s ease,
    transform 0.15s ease,
    background 0.15s ease,
    border-color 0.15s ease;
}
.menu-recipe-action svg {
  flex-shrink: 0;
}
.menu-recipe-action-label {
  white-space: nowrap;
}
@media (hover: hover) and (pointer: fine) {
  .menu-recipe-action:hover {
    background: var(--paper-soft);
    color: var(--ink);
    border-color: var(--ink-muted);
  }
}
.menu-recipe-action:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
}
.menu-recipe-fav.is-on {
  color: var(--heart);
  border-color: var(--heart);
  background: oklch(0.97 0.025 15);
}
.menu-recipe-fav.is-on svg path {
  fill: currentColor;
}
@media (hover: hover) and (pointer: fine) {
  .menu-recipe-fav.is-on:hover {
    color: var(--heart-deep);
    border-color: var(--heart-deep);
  }
}
.menu-recipe-cooked.is-on {
  color: var(--brand-dark);
  border-color: var(--brand);
  background: var(--accent-tint);
}
@media (hover: hover) and (pointer: fine) {
  .menu-recipe-cooked.is-on:hover {
    color: var(--brand-dark);
  }
}
.menu-recipe-action.is-pulsing {
  animation: favPulse 0.45s cubic-bezier(0.25, 1, 0.5, 1);
}
@keyframes favPulse {
  0% {
    transform: scale(1);
  }
  40% {
    transform: scale(1.06);
  }
  100% {
    transform: scale(1);
  }
}
/* Sur très petit écran : labels masqués si manque de place */
@media (max-width: 480px) {
  .menu-recipe-action {
    padding: 10px 12px;
  }
  .menu-recipe-action-label {
    display: none;
  }
}
@media (prefers-reduced-motion: reduce) {
  .menu-recipe-action,
  .menu-recipe-action.is-pulsing {
    transition: none;
    animation: none;
  }
}

/* ── Page Mes coups de cœur ─────────────────────────────────────
   Bibliothèque perso de recettes. Grid auto-fit, editorial cards. */
.cdc-empty {
  text-align: center;
  padding: 80px 24px;
  max-width: 520px;
  margin: 0 auto;
}
.cdc-empty-emoji {
  font-size: 56px;
  margin-bottom: 20px;
  opacity: 0.85;
}
.cdc-empty-title {
  font-family: var(--font-display, "Young Serif", serif);
  font-size: 28px;
  font-weight: 400;
  color: var(--ink);
  margin-bottom: 12px;
  line-height: 1.15;
}
.cdc-empty-lede {
  font-size: 16px;
  color: var(--ink-muted);
  line-height: 1.55;
  margin-bottom: 28px;
}

.cdc-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 14px;
  margin-top: 24px;
}
.cdc-card {
  position: relative;
  display: flex;
  gap: 14px;
  padding: 16px 18px;
  background: var(--paper-sheet);
  border: 1px solid var(--border);
  border-radius: var(--radius-xl, 16px);
  transition:
    transform 0.15s ease,
    border-color 0.15s ease;
}
@media (hover: hover) and (pointer: fine) {
  .cdc-card:hover {
    border-color: var(--brand);
    transform: translateY(-1px);
  }
}
.cdc-card-emoji {
  font-size: 36px;
  line-height: 1;
  flex-shrink: 0;
}
.cdc-card-body {
  flex: 1;
  min-width: 0;
}
.cdc-card-title {
  font-family: var(--font-display, "Young Serif", serif);
  font-size: 18px;
  font-weight: 400;
  color: var(--ink);
  line-height: 1.2;
  margin-bottom: 4px;
}
.cdc-card-meta {
  font-size: 13px;
  color: var(--ink-muted);
  display: flex;
  flex-wrap: wrap;
  gap: 4px 0;
}
.cdc-card-meta > span {
  margin-right: 4px;
}
.cdc-card-sep {
  color: var(--border);
}
.cdc-card-date {
  font-size: 12px;
  color: var(--ink-muted);
  opacity: 0.7;
  margin-top: 6px;
}
.cdc-card-remove-form {
  position: absolute;
  top: 4px;
  right: 4px;
}
.cdc-card-remove {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: none;
  background: transparent;
  color: var(--ink-muted);
  font-size: 16px;
  cursor: pointer;
  opacity: 0.5;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition:
    opacity 0.15s ease,
    background 0.15s ease;
}
@media (hover: hover) and (pointer: fine) {
  .cdc-card-remove:hover {
    opacity: 1;
    background: var(--paper-soft);
  }
}
.cdc-card-remove:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
  opacity: 1;
}
@media (prefers-reduced-motion: reduce) {
  .cdc-card,
  .cdc-card-remove {
    transition: none;
  }
  @media (hover: hover) and (pointer: fine) {
    .cdc-card:hover {
      transform: none;
    }
  }
}

/* ── TABS — navigation secondaire ────────────────────────────── */
.dash-tabs {
  background: var(--paper-sheet);
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  overflow: hidden;
}
.dash-tabs-nav {
  display: flex;
  border-bottom: 1px solid var(--border);
  padding: 0 4px;
  /* Scroll horizontal si plus de 3 onglets et viewport étroit, plutôt
     que de tasser les labels. -webkit-overflow-scrolling pour iOS. */
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.dash-tabs-nav::-webkit-scrollbar {
  display: none;
}
.dash-tabs-nav .dash-tab {
  white-space: nowrap;
  flex-shrink: 0;
}
.dash-tab {
  flex: 1;
  padding: 14px 16px;
  border: none;
  background: none;
  font-family: var(--font-body);
  font-size: 13px;
  font-weight: 600;
  color: var(--ink-muted);
  cursor: pointer;
  position: relative;
  transition: color 0.2s;
}
@media (hover: hover) and (pointer: fine) {
  .dash-tab:hover {
    color: var(--ink);
  }
}
.dash-tab:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: -2px;
  border-radius: 6px;
}
.dash-tab.is-active {
  color: var(--brand-dark);
}
.dash-tab.is-active::after {
  content: "";
  position: absolute;
  bottom: -1px;
  left: 16px;
  right: 16px;
  height: 2px;
  background: var(--brand-dark);
  border-radius: 2px 2px 0 0;
}
.dash-tab-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  background: var(--danger);
  color: var(--cream-fixed);
  font-size: 10px;
  font-weight: 700;
  border-radius: 9px;
  margin-left: 6px;
}
.dash-tab-panel {
  padding: clamp(20px, 3vw, 32px);
}
.dash-tab-panel[hidden] {
  display: none;
}

/* ── Mobile responsive ───────────────────────────────────────── */
@media (max-width: 640px) {
  .dash-hero-grid {
    grid-template-columns: 1fr;
    justify-items: center;
    gap: 20px;
  }
  .dash-hero-ring {
    width: 150px;
    height: 150px;
  }
  .dash-hero-ring svg {
    width: 150px;
    height: 150px;
  }
  .dash-hero-ring-pct {
    font-size: 36px;
  }
  .dash-hero-numbers {
    flex-direction: row;
    gap: 0;
    width: 100%;
    text-align: center;
  }
  /* .dash-hero-kpi* responsive retiré (audit pass 3 cleanup) */
  .dash-hero-actions {
    justify-content: center;
  }
  .dash-hero-action {
    font-size: 12px;
    padding: 7px 12px;
  }

  .dash-tabs-nav {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
  }
  .dash-tab {
    white-space: nowrap;
    flex: none;
    padding: 12px 14px;
  }
}

/* ── Budget Fantôme — module éditorial pleine largeur ──────── */
.dash-budget {
  background: var(--paper-sheet);
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  padding: clamp(28px, 4vw, 48px) clamp(28px, 4vw, 56px);
  margin-bottom: 32px;
  position: relative;
  overflow: hidden;
}
.dash-budget::before {
  /* Blob radial-gradient retiré 2026-05-10 (war room) — dash-budget. */
  content: none;
}
.dash-budget-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: clamp(24px, 4vw, 56px);
  align-items: center;
  position: relative;
  z-index: 1;
}
.dash-budget-main {
  min-width: 0;
}
.dash-budget-eyebrow {
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--brand-dark);
  margin-bottom: 16px;
}
.dash-budget-amount {
  font-family: var(--font-body);
  font-size: clamp(56px, 8vw, 96px);
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.03em;
  color: var(--ink);
  line-height: 0.92;
  margin-bottom: 14px;
  display: flex;
  align-items: baseline;
}
.dash-budget-currency {
  font-size: 0.4em;
  font-weight: 600;
  color: var(--ink-muted);
  margin-right: 6px;
  letter-spacing: -0.01em;
}
.dash-budget-sub {
  font-family: var(--font-body);
  font-size: clamp(14px, 1.4vw, 16px);
  line-height: 1.6;
  color: var(--ink-soft);
  margin: 0 0 18px;
  max-width: 56ch;
}
.dash-budget-sub strong {
  font-family: var(--font-body);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}
.dash-budget-savings {
  color: var(--brand-dark) !important;
  font-size: 1.06em;
}
.dash-budget-tags {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}
.dash-tag {
  display: inline-flex;
  align-items: center;
  padding: 6px 14px;
  border-radius: 980px;
  border: 1px solid var(--border);
  background: var(--paper-sheet);
  font-family: var(--font-body);
  font-size: 11.5px;
  font-weight: 500;
  letter-spacing: 0.04em;
  color: var(--ink-soft);
}
.dash-tag-accent {
  color: var(--brand-dark);
  border-color: oklch(0.59 0.16 143 / 0.26);
  background: var(--accent-tint);
  font-weight: 600;
}

.dash-budget-ring {
  position: relative;
  flex-shrink: 0;
  width: 156px;
  height: 156px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.dash-budget-ring-center {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
}
.dash-budget-ring-pct {
  font-family: var(--font-body);
  font-size: 32px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
  letter-spacing: -0.02em;
  line-height: 1;
}
.dash-budget-ring-pct span {
  font-size: 0.5em;
  color: var(--ink-muted);
  margin-left: 1px;
}
.dash-budget-ring-lbl {
  font-family: var(--font-body);
  font-size: 9.5px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-muted);
  margin-top: 6px;
  max-width: 110px;
  line-height: 1.35;
}
.dash-budget-ring-reste {
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 700;
  color: var(--brand-dark);
  margin-top: 4px;
}

/* ── Stats rule — 3 indicateurs horizontaux éditoriaux ─────── */
.dash-stats {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  border-top: 2px solid var(--ink);
  border-bottom: 1px solid var(--border);
  margin-bottom: 36px;
}
.dash-stat {
  padding: 24px 22px;
  border-right: 1px solid var(--border);
}
.dash-stat:last-child {
  border-right: none;
}
.dash-stat-eyebrow {
  font-family: var(--font-body);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-muted);
  margin-bottom: 12px;
}
.dash-stat-value {
  font-family: var(--font-display);
  font-size: clamp(28px, 3.2vw, 42px);
  font-weight: 400;
  letter-spacing: -0.02em;
  line-height: 1;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.dash-stat-value sub {
  font-family: var(--font-body);
  font-size: 0.32em;
  color: var(--ink-muted);
  vertical-align: baseline;
  font-weight: 500;
  margin-left: 6px;
  letter-spacing: 0.02em;
  text-transform: lowercase;
}
.dash-stat-note {
  font-family: var(--font-body);
  font-size: 12px;
  font-style: italic;
  color: var(--ink-muted);
  margin-top: 10px;
  line-height: 1.5;
}

/* Teaser Forfait Reception sur le dashboard quand 0 event paye —
   2026-05-09 (audit R2 P1 « feature invisible si pas deja consommee »).
   Pattern <details> natif : replie par defaut pour ne pas voler le
   focus du tab Ma semaine, mais decouvrable. Esthetique sobre :
   pas de gradient, pas d eyebrow numerote, pas de pull-quote.
   Une ligne d invitation + une description + un lien. */
/* Forfait Reception banner 2026-05-09 (Phase 1 cleanup) :
   replace l ancien <details> teaser invisible (95% non-decouvert).
   Maintenant : banner ouvert mais sobre, paper-soft + brand border
   + CTA fleche. Pas de gradient, pas de pricing en gros. Cliquable
   en entier (le <a> wrappe tout). Touch target 44px assure. */
/* Refonte 2026-05-10 (war room Cron Calendar) : avant hover changeait
   le fond pour accent-tint = atmosphère SaaS verte. Maintenant fond
   neutre paper-soft maintenu + bordure subtile accent qui signale
   sans saturer (full 1px border, pas de side-stripe BAN 1). */
.dash-recevoir-banner {
  display: flex;
  align-items: center;
  gap: 16px;
  margin: 16px 0 24px;
  padding: 18px 20px;
  border: 1px solid color-mix(in oklch, var(--brand) 25%, var(--border, oklch(0.88 0.02 75)));
  border-radius: 12px;
  background: var(--paper-soft, var(--paper));
  text-decoration: none;
  color: inherit;
  transition: border-color 0.15s ease;
  min-height: 44px;
}
@media (hover: hover) and (pointer: fine) {
  .dash-recevoir-banner:hover,
  .dash-recevoir-banner:focus-visible {
    border-color: color-mix(in oklch, var(--brand) 50%, var(--border));
    outline: none;
  }
}
.dash-recevoir-banner:focus-visible {
  box-shadow:
    0 0 0 2px var(--brand-dark, var(--brand)),
    0 0 0 4px var(--paper);
}
.dash-recevoir-banner:active {
  transform: translateY(1px);
}
.dash-recevoir-banner-body {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}
.dash-recevoir-banner-eyebrow {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--brand-dark, var(--brand));
}
.dash-recevoir-banner-title {
  font-family: var(--font-display, var(--font-body));
  font-size: 18px;
  font-weight: 400;
  color: var(--ink);
  letter-spacing: -0.01em;
  line-height: 1.25;
}
.dash-recevoir-banner-lede {
  font-size: 13px;
  line-height: 1.5;
  color: var(--ink-soft);
}
.dash-recevoir-banner-cta {
  flex-shrink: 0;
  font-size: 12px;
  font-weight: 600;
  color: var(--brand-dark, var(--brand));
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
@media (max-width: 480px) {
  .dash-recevoir-banner {
    padding: 14px 16px;
    gap: 10px;
  }
  .dash-recevoir-banner-title {
    font-size: 16px;
  }
}

/* ── Sections éditoriales du dashboard ─────────────────────── */
.dash-section {
  margin-bottom: 44px;
}
.dash-section-head {
  display: grid;
  grid-template-columns: 1fr auto;
  grid-template-areas:
    "eyebrow action"
    "title   action";
  gap: 4px 16px;
  align-items: center;
  /* User signale : la border-bottom 1px sous le titre de section lit
     comme un séparateur de tableau (« doesn't feel app »). Native iOS
     n'utilise pas de séparateurs entre header et content de section —
     l'espacement seul fait le travail. margin-bottom plus généreux
     pour maintenir la séparation visuelle. */
  margin-bottom: 18px;
}
.dash-section-eyebrow {
  grid-area: eyebrow;
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--brand-dark);
}
.dash-section-title {
  grid-area: title;
  font-family: var(--font-display);
  font-size: clamp(22px, 2.4vw, 30px);
  font-weight: 400;
  letter-spacing: -0.014em;
  color: var(--ink);
  line-height: 1.1;
  margin: 0;
  text-wrap: balance;
}
/* Modifiers pour les vues qui veulent une taille fixe (pages /recevoir
   où le clamp standard est trop grand pour la densité d'info). */
.dash-section-title--md {
  font-size: 22px;
}
.dash-section-title--lg {
  font-size: 24px;
}
.dash-section-title em {
  color: var(--brand-dark);
  font-style: italic;
  font-family: var(--font-display);
}
.dash-section-action {
  grid-area: action;
  font-family: var(--font-body);
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--brand-dark);
  align-self: end;
  /* Avant : underline 1.5px épais sous « Voir tout → » créait 3e ligne
     horizontale en compétition avec dash-section-head border-bottom +
     card border. Maintenant : la flèche + le brand-dark color + le bold
     portent l'affordance link sans souligner. */
  text-decoration: none;
  white-space: nowrap;
}
@media (hover: hover) and (pointer: fine) {
  .dash-section-action:hover {
    color: var(--brand-dark);
    text-decoration: underline;
    text-underline-offset: 4px;
  }
}
.dash-section-body {
  display: flex;
  flex-direction: column;
}

/* Empty state */
.dash-empty {
  text-align: center;
  padding: 42px 24px;
  background: var(--paper-soft);
  /* Border dashed retiré (lit "brouillon" pour empty state) — solid 1px
     subtil, ou rien. Pattern card-native iOS : background différencie. */
  border-radius: var(--radius);
}
.dash-empty-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 14px;
  color: var(--ink-muted);
  opacity: 0.7;
}
/* Editorial monogramme É — pattern signature L'Économe pour les empty
   states (au lieu d'emoji décoratifs anti-CLAUDE.md). Cohérent avec
   gen-loading-mark et l'OG image signature. */
.dash-empty-mark {
  font-family: var(--font-display, 'Young Serif', serif);
  font-size: 80px;
  line-height: 1;
  color: var(--brand-dark, var(--brand));
  opacity: 0.6;
  margin-bottom: 18px;
}
.dash-empty-title {
  font-family: var(--font-display);
  font-size: 20px;
  color: var(--ink);
  margin-bottom: 8px;
  text-wrap: balance;
}
.dash-empty p {
  font-family: var(--font-body);
  font-size: 14px;
  color: var(--ink-muted);
  margin: 0 0 18px;
  text-wrap: balance;
}
.dash-empty-alt {
  font-size: 12px !important;
  color: var(--ink-fade, var(--ink-muted)) !important;
  margin-top: 14px !important;
  margin-bottom: 0 !important;
}

/* Expiration color legend */
.pantry-legend {
  display: flex;
  gap: 16px;
  flex-wrap: wrap;
  margin-bottom: 16px;
  padding: 10px 14px;
  background: var(--paper-soft);
  border-radius: var(--radius-sm);
  font-size: 12px;
  color: var(--ink-muted);
}
.pantry-legend-item {
  display: flex;
  align-items: center;
  gap: 6px;
}
.pantry-legend-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  flex-shrink: 0;
}
.pantry-legend-dot--urgent {
  background: var(--danger);
}
.pantry-legend-dot--warn {
  background: var(--courge);
}
.pantry-legend-dot--ok {
  background: var(--brand-dark);
}

/* Meal item — clean editorial row */
.dash-meal {
  display: grid;
  grid-template-columns: 44px 1fr auto;
  gap: 14px;
  align-items: center;
  padding: 18px 4px;
  border-bottom: 1px solid var(--border2);
  text-decoration: none;
  color: inherit;
  transition: transform 0.25s cubic-bezier(0.22, 1, 0.36, 1);
}
@media (hover: hover) and (pointer: fine) {
  .dash-meal:hover {
    transform: translateX(12px);
  }
}
.dash-meal:last-child {
  border-bottom: none;
}
/* Emoji inline XL (plus de thumb carré) — option A */
.dash-meal-emoji {
  font-size: 34px;
  line-height: 1;
  width: 44px;
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
/* Thèmes de cover par catégorie — appliqué sur .menu-recipe-cover et .recipe-cover */
/* ── Covers recettes : brand-pure signature L'Économe
   UNE SEULE base crème, partout, toutes catégories. Aucune teinte
   coloriée — le tint même subtil lisait « brunâtre » au petit format.
   Différenciation assurée par : (1) filet 2px Vert Jean-Talon en haut,
   (2) titre italique serif large, (3) stats encrées. Rien d'autre.
   C'est LA page cookbook L'Économe — crème + vert brand, point. */
.cover-beef,
.cover-poultry,
.cover-sea,
.cover-pasta,
.cover-pizza,
.cover-green,
.cover-stew,
.cover-sweet,
.cover-breakfast,
.cover-grain,
.cover-mex,
.cover-neutral {
  background: var(--paper-sheet);
}
/* Filet vert brand seulement sur les covers sans ::after (ex : .recipe-cover legacy).
   Le menu-recipe-cover--editorial a déjà son propre filet via ::after. */
.recipe-cover.cover-beef,
.recipe-cover.cover-poultry,
.recipe-cover.cover-sea,
.recipe-cover.cover-pasta,
.recipe-cover.cover-pizza,
.recipe-cover.cover-green,
.recipe-cover.cover-stew,
.recipe-cover.cover-sweet,
.recipe-cover.cover-breakfast,
.recipe-cover.cover-grain,
.recipe-cover.cover-mex,
.recipe-cover.cover-neutral {
  border-top: 2px solid var(--brand);
}

[data-theme="dark"] .cover-beef,
[data-theme="dark"] .cover-poultry,
[data-theme="dark"] .cover-sea,
[data-theme="dark"] .cover-pasta,
[data-theme="dark"] .cover-pizza,
[data-theme="dark"] .cover-green,
[data-theme="dark"] .cover-stew,
[data-theme="dark"] .cover-sweet,
[data-theme="dark"] .cover-breakfast,
[data-theme="dark"] .cover-grain,
[data-theme="dark"] .cover-mex,
[data-theme="dark"] .cover-neutral {
  background: var(--paper-sheet);
}
.dash-meal-info {
  min-width: 0;
}
.dash-meal-name {
  font-family: var(--font-display);
  font-size: 18px;
  font-weight: 400;
  color: var(--ink);
  letter-spacing: -0.008em;
  line-height: 1.2;
  margin-bottom: 4px;
}
.dash-meal-meta {
  font-family: var(--font-body);
  font-size: 12.5px;
  color: var(--ink-muted);
  letter-spacing: 0.02em;
}
.dash-meal-price {
  font-family: var(--font-body);
  font-size: 16px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
  flex-shrink: 0;
  letter-spacing: -0.01em;
}
.dash-meal-price.is-free {
  color: var(--brand-dark);
}

/* Prediction row — la sémantique buy/wait est portée par le pill
   .dash-pred-action (couleur + bg + border). Plus besoin de
   side-stripe border-left (anti-pattern impeccable BAN 1). */
.dash-pred {
  display: block;
  padding: 14px 18px;
  border-bottom: 1px solid var(--border2);
}
.dash-pred:last-child {
  border-bottom: none;
}
.dash-pred-name {
  font-family: var(--font-display);
  font-size: 16px;
  color: var(--ink);
  margin-bottom: 4px;
  letter-spacing: -0.005em;
}
.dash-pred-msg {
  font-family: var(--font-body);
  font-size: 13px;
  color: var(--ink-muted);
  line-height: 1.5;
}
/* .dash-pred-action* (is-buy / is-wait) supprime 2026-05-09 (audit R18).
   Verdicts « Achete / Attends » retires en mai 2026 (cf. CLAUDE.md
   anti-pattern). Les classes restaient en CSS sans usage Blade. */

/* Alert detective */
.dash-alert {
  padding: 16px 18px;
  background: var(--accent-tint);
  border-radius: 12px;
  margin-top: 12px;
  border: 1px solid oklch(0.62 0.14 68 / 0.22);
}
.dash-alert-title {
  font-family: var(--font-display);
  font-size: 15px;
  color: oklch(0.42 0.12 68);
  margin-bottom: 4px;
  letter-spacing: -0.005em;
}
.dash-alert-body {
  font-family: var(--font-body);
  font-size: 13px;
  line-height: 1.55;
  color: oklch(0.4 0.1 68);
}

/* Pantry row */
.dash-pantry {
  display: grid;
  grid-template-columns: 32px 1fr auto;
  gap: 14px;
  align-items: center;
  padding: 14px 4px;
  border-bottom: 1px solid var(--border2);
}
.dash-pantry:last-child {
  border-bottom: none;
}
.dash-pantry-emoji {
  font-size: 22px;
}
.dash-pantry-name {
  font-family: var(--font-body);
  font-size: 14.5px;
  color: var(--ink);
  font-weight: 500;
}
.dash-pantry-expire {
  font-family: var(--font-body);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 4px 12px;
  border-radius: 980px;
  white-space: nowrap;
}
.dash-pantry-expire--ok {
  background: var(--accent-tint);
  color: var(--brand-dark);
}
.dash-pantry-expire--warn {
  background: var(--accent-tint);
  color: oklch(0.42 0.12 68);
}
.dash-pantry-expire--urgent {
  background: var(--danger-tint);
  color: var(--danger);
}

/* Aubaine row — éditorial deal listing */
.dash-deal {
  display: grid;
  grid-template-columns: 100px 1fr auto;
  gap: 18px;
  align-items: center;
  padding: 16px 4px;
  border-bottom: 1px solid var(--border2);
}
.dash-deal:last-child {
  border-bottom: none;
}
.dash-deal-store {
  font-family: var(--font-body);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-muted);
  padding: 6px 12px;
  border: 1px solid var(--border);
  border-radius: 980px;
  text-align: center;
  white-space: nowrap;
}
.dash-deal-name {
  font-family: var(--font-display);
  font-size: 16px;
  color: var(--ink);
  letter-spacing: -0.005em;
}
.dash-deal-prices {
  display: flex;
  align-items: baseline;
  gap: 10px;
  flex-shrink: 0;
}
.dash-deal-price {
  font-family: var(--font-body);
  font-size: 17px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  color: var(--brand-dark);
  letter-spacing: -0.01em;
}
.dash-deal-original {
  font-family: var(--font-body);
  font-size: 12.5px;
  color: var(--ink-fade);
  text-decoration: line-through;
  font-variant-numeric: tabular-nums;
}
.dash-deal-pct {
  font-family: var(--font-body);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.06em;
  padding: 4px 8px;
  border-radius: 4px;
  background: var(--accent-tint);
  color: var(--brand-dark);
}

/* ── Dashboard responsive ─────────────────────────────────── */
@media (max-width: 900px) {
  .dash-budget {
    padding: 28px 24px;
  }
  .dash-budget-grid {
    grid-template-columns: 1fr;
    gap: 32px;
    text-align: left;
  }
  .dash-budget-amount {
    font-size: clamp(48px, 14vw, 72px);
  }
  .dash-budget-ring {
    margin: 0 auto;
  }

  .dash-stats {
    grid-template-columns: 1fr;
  }
  .dash-stat {
    border-right: none;
    border-bottom: 1px solid var(--border);
    padding: 22px 4px;
  }
  .dash-stat:last-child {
    border-bottom: none;
  }

  .dash-section-head {
    grid-template-columns: 1fr;
    grid-template-areas:
      "eyebrow"
      "title"
      "action";
    gap: 8px;
  }
  .dash-section-action {
    align-self: start;
  }
}
@media (max-width: 480px) {
  .dash-meal {
    grid-template-columns: 40px 1fr auto;
    gap: 12px;
  }
  .dash-meal-emoji {
    width: 40px;
    height: 40px;
    font-size: 30px;
  }
  .dash-meal-name {
    font-size: 16px;
  }
  .dash-deal {
    grid-template-columns: 1fr auto;
    gap: 10px;
  }
  .dash-deal-store {
    grid-column: 1 / -1;
    justify-self: start;
  }
  .dash-pred {
    grid-template-columns: 1fr;
    gap: 10px;
  }
  .dash-pred-action {
    justify-self: start;
  }
}

/* ============================================================
   VOTE / COLOC / PARRAINAGE / GASPILLAGE / ZERO / ABONNEMENT /
   ESPACE-CLIENT — Vague 6 batch E + F
   ============================================================ */

/* Vote */
.vote-banner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  background: var(--paper-sheet);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 18px 24px;
  margin-bottom: 28px;
}
.vote-banner-eyebrow {
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--brand-dark);
  margin-bottom: 4px;
}
.vote-banner-meta {
  font-family: var(--font-body);
  font-size: 12px;
  color: var(--ink-muted);
}
.vote-card {
  background: var(--paper-sheet);
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  padding: 28px;
  margin-bottom: 18px;
}
.vote-card-head {
  display: grid;
  grid-template-columns: 56px 1fr auto;
  align-items: center;
  gap: 16px;
  margin-bottom: 16px;
}
.vote-card-emoji {
  font-size: 36px;
  width: 56px;
  height: 56px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--paper-soft);
  border-radius: 14px;
}
.vote-card-name {
  font-family: var(--font-display);
  font-size: 20px;
  color: var(--ink);
  margin: 0 0 4px;
  letter-spacing: -0.008em;
}
.vote-card-meta {
  font-family: var(--font-body);
  font-size: 12px;
  color: var(--ink-muted);
}
.vote-card-fav {
  font-family: var(--font-body);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  padding: 5px 12px;
  border-radius: 980px;
  background: var(--accent-tint);
  color: var(--brand-dark);
  border: 1px solid oklch(0.59 0.16 143 / 0.26);
}
.vote-members {
  display: flex;
  gap: 14px;
  margin-bottom: 14px;
  flex-wrap: wrap;
}
.vote-member {
  display: flex;
  align-items: center;
  gap: 6px;
}
.vote-member-avatar {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--brand-dark);
  color: var(--cream-fixed);
  font-family: var(--font-body);
  font-size: 10px;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
  text-transform: uppercase;
}
.vote-member-icon {
  font-family: var(--font-display);
  font-size: 14px;
  width: 18px;
  text-align: center;
}
.vote-member-icon--oui {
  color: var(--brand-dark);
}
.vote-member-icon--non {
  color: var(--danger);
}
.vote-member-icon--peut_etre {
  color: var(--danger);
}
.vote-member-icon--pending {
  color: var(--ink-fade);
}
.vote-bar {
  height: 6px;
  background: var(--paper-deep);
  border-radius: 3px;
  overflow: hidden;
}
.vote-bar-fill {
  height: 100%;
  background: var(--brand-dark);
  border-radius: 3px;
  transform-origin: left center;
  transform: scaleX(var(--progress, 0));
  transition: transform 0.5s cubic-bezier(0.22, 1, 0.36, 1);
  will-change: transform;
}
.vote-bar-meta {
  display: flex;
  justify-content: space-between;
  font-family: var(--font-body);
  font-size: 12px;
  color: var(--ink-muted);
  margin-top: 6px;
}
.vote-bar-meta strong {
  font-family: var(--font-display);
  font-size: 16px;
  color: var(--brand-dark);
}
.vote-form {
  display: flex;
  gap: 8px;
  margin-top: 18px;
  flex-wrap: wrap;
}
.vote-form input {
  flex: 1;
  min-width: 140px;
  font-family: var(--font-body);
  padding: 10px 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--paper);
  color: var(--ink);
}
.vote-form button {
  padding: 10px 16px;
  font-size: 13px;
}
.vote-form-no {
  color: var(--danger);
  border-color: oklch(0.44 0.14 25 / 0.34);
}

/* Coloc */
.coloc-onboarding {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 24px;
  max-width: 720px;
  margin: 0 auto;
}
@media (max-width: 768px) {
  .coloc-onboarding {
    grid-template-columns: 1fr;
  }
}
.coloc-onboarding-card {
  background: var(--paper-sheet);
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  padding: 36px 32px;
  text-align: center;
}
.coloc-onboarding-rank {
  font-family: var(--font-display);
  font-size: 36px;
  color: var(--brand-dark);
  margin-bottom: 8px;
}
.coloc-onboarding-title {
  font-family: var(--font-display);
  font-size: 24px;
  color: var(--ink);
  margin: 0 0 12px;
}
.coloc-onboarding-card p {
  font-family: var(--font-body);
  font-size: 13.5px;
  color: var(--ink-soft);
  margin: 0 0 22px;
}
.coloc-onboarding-card input {
  width: 100%;
  font-family: var(--font-body);
  padding: 12px 16px;
  border: 1.5px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--paper);
  color: var(--ink);
  margin-bottom: 12px;
}
.coloc-onboarding-code {
  text-align: center;
  font-family: var(--font-display) !important;
  font-size: 22px !important;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}
.coloc-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 24px;
  background: var(--paper-sheet);
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  padding: 28px 32px;
  margin-bottom: 28px;
  flex-wrap: wrap;
}
.coloc-header-eyebrow {
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--brand-dark);
  margin-bottom: 6px;
}
.coloc-header-name {
  font-family: var(--font-display);
  font-size: 28px;
  color: var(--ink);
  margin: 0 0 4px;
  letter-spacing: -0.018em;
}
.coloc-header-meta {
  font-family: var(--font-body);
  font-size: 12px;
  color: var(--ink-muted);
}
.coloc-header-code {
  text-align: center;
  background: var(--paper);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 14px 22px;
}
.coloc-header-code-label {
  font-family: var(--font-body);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-muted);
  margin-bottom: 6px;
}
.coloc-header-code-value {
  font-family: var(--font-display);
  font-size: 26px;
  letter-spacing: 0.18em;
  color: var(--brand-dark);
  font-weight: 400;
}

.coloc-balances {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: 14px;
}
.coloc-balance {
  background: var(--paper-sheet);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 22px 16px;
  text-align: center;
}
.coloc-balance.is-positive {
  border-color: oklch(0.59 0.16 143 / 0.26);
}
.coloc-balance.is-negative {
  border-color: oklch(0.44 0.14 25 / 0.26);
}
.coloc-balance-avatar {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: var(--accent-tint);
  color: var(--brand-dark);
  font-family: var(--font-body);
  font-size: 13px;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0 auto 10px;
}
.coloc-balance.is-negative .coloc-balance-avatar {
  background: var(--danger-tint);
  color: var(--danger);
}
.coloc-balance-name {
  font-family: var(--font-display);
  font-size: 14px;
  color: var(--ink);
  margin-bottom: 6px;
}
.coloc-balance-value {
  font-family: var(--font-display);
  font-size: 22px;
  letter-spacing: -0.018em;
  font-variant-numeric: tabular-nums;
}
.coloc-balance.is-positive .coloc-balance-value {
  color: var(--brand-dark);
}
.coloc-balance.is-negative .coloc-balance-value {
  color: var(--danger);
}
.coloc-balance-note {
  font-family: var(--font-body);
  font-size: 10px;
  color: var(--ink-muted);
  margin-top: 4px;
}

.coloc-turn {
  background: var(--accent-tint);
  border: 1px solid oklch(0.59 0.16 143 / 0.26);
  border-radius: var(--radius);
  padding: 22px 28px;
  margin-bottom: 28px;
  display: flex;
  align-items: center;
  gap: 18px;
  flex-wrap: wrap;
}
.coloc-turn-eyebrow {
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--brand-dark);
  margin-bottom: 4px;
}
.coloc-turn-name {
  font-family: var(--font-display);
  font-size: 22px;
  color: var(--ink);
  flex: 1;
}

.coloc-add-form {
  display: grid;
  grid-template-columns: 2fr 1fr auto;
  gap: 14px;
  align-items: end;
  padding: 22px 24px;
  background: var(--paper);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  margin-bottom: 18px;
}
@media (max-width: 768px) {
  .coloc-add-form {
    grid-template-columns: 1fr;
  }
}
.coloc-add-form .form-group {
  margin-bottom: 0;
}
.coloc-add-form .btn-main {
  padding: 13px 22px;
}
.coloc-expense {
  display: grid;
  grid-template-columns: 80px 1fr auto;
  gap: 16px;
  align-items: center;
  padding: 14px 0;
  border-bottom: 1px solid var(--border2);
}
.coloc-expense:last-child {
  border-bottom: none;
}
.coloc-expense-date {
  font-family: var(--font-body);
  font-size: 11.5px;
  color: var(--ink-muted);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
.coloc-expense-desc {
  font-family: var(--font-display);
  font-size: 16px;
  color: var(--ink);
}
.coloc-expense-payer {
  font-family: var(--font-body);
  font-size: 11.5px;
  color: var(--ink-muted);
  font-style: italic;
}
.coloc-expense-amount {
  font-family: var(--font-body);
  font-size: 16px;
  font-weight: 700;
  color: var(--brand-dark);
  font-variant-numeric: tabular-nums;
}
.coloc-actions {
  margin-top: 32px;
  text-align: center;
}
.coloc-leave {
  color: var(--danger);
  border-color: oklch(0.44 0.14 25 / 0.34);
}

/* Parrainage */
.parrainage-link {
  background: var(--paper);
  border: 1.5px solid var(--border);
  border-radius: var(--radius);
  padding: 18px 24px;
  font-family: var(--font-body);
  font-size: 13px;
  color: var(--ink);
  word-break: break-all;
  margin-bottom: 16px;
}
.parrainage-actions {
  display: flex;
  gap: 12px;
  margin-bottom: 22px;
}
.parrainage-actions .btn-main,
.parrainage-actions .btn-sec {
  flex: 1;
  padding: 12px;
}
.parrainage-code {
  font-family: var(--font-body);
  font-size: 13px;
  color: var(--ink-soft);
  background: var(--accent-tint);
  border: 1px solid oklch(0.59 0.16 143 / 0.22);
  border-radius: var(--radius-sm);
  padding: 14px 18px;
  margin: 0 0 28px;
}
.parrainage-code strong {
  font-family: var(--font-display);
  font-size: 16px;
  color: var(--brand-dark);
  letter-spacing: 0.04em;
}
.parrainage-email {
  border-top: 1px solid var(--border);
  padding-top: 22px;
}
.parrainage-email-eyebrow {
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-muted);
  margin-bottom: 12px;
}
.parrainage-email-form {
  display: flex;
  gap: 10px;
}
.parrainage-email-form input {
  flex: 1;
  font-family: var(--font-body);
  padding: 12px 16px;
  border: 1.5px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--paper);
}
.parrainage-filleul {
  display: grid;
  grid-template-columns: 44px 1fr auto;
  align-items: center;
  gap: 14px;
  padding: 14px 0;
  border-bottom: 1px solid var(--border2);
}
.parrainage-filleul:last-child {
  border-bottom: none;
}
.parrainage-filleul-avatar {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: var(--accent-tint);
  color: var(--brand-dark);
  font-family: var(--font-display);
  font-size: 18px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.parrainage-filleul-name {
  font-family: var(--font-display);
  font-size: 16px;
  color: var(--ink);
}
.parrainage-filleul-date {
  font-family: var(--font-body);
  font-size: 11.5px;
  color: var(--ink-muted);
}
.parrainage-filleul-plan {
  font-family: var(--font-body);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  padding: 5px 12px;
  border-radius: 980px;
  background: var(--paper-soft);
  color: var(--ink-muted);
  border: 1px solid var(--border);
}
.parrainage-filleul-plan.is-premium {
  background: var(--accent-tint);
  color: var(--brand-dark);
  border-color: oklch(0.59 0.16 143 / 0.26);
}

/* Gaspillage */
.gaspillage-bar {
  height: 32px;
  border-radius: 16px;
  overflow: hidden;
  display: flex;
  border: 1px solid var(--border);
}
.gaspillage-bar-good,
.gaspillage-bar-bad {
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-body);
  font-size: 12px;
  font-weight: 600;
  color: var(--cream-fixed);
}
.gaspillage-bar-good {
  background: var(--brand-dark);
}
.gaspillage-bar-bad {
  background: var(--danger);
}
.gaspillage-row {
  display: flex;
  justify-content: space-between;
  padding: 10px 0;
  border-bottom: 1px solid var(--border2);
  font-family: var(--font-body);
  font-size: 14px;
}
.gaspillage-row:last-child {
  border-bottom: none;
}
.gaspillage-row-name {
  color: var(--ink);
}
.gaspillage-row-count {
  color: var(--danger);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.gaspillage-mark {
  display: inline;
}
.gaspillage-mark-good,
.gaspillage-mark-bad {
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 6px 12px;
  border-radius: 980px;
  border: 1px solid currentColor;
  background: transparent;
  cursor: pointer;
}
.gaspillage-mark-good {
  color: var(--brand-dark);
  background: var(--accent-tint);
}
.gaspillage-mark-bad {
  color: var(--danger);
  background: var(--danger-tint);
}

/* Zéro gaspillage */
.defi {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 18px;
  align-items: center;
  padding: 20px 24px;
  background: var(--paper);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  margin-bottom: 12px;
}
.defi.is-complete {
  background: var(--accent-tint);
  border-color: oklch(0.59 0.16 143 / 0.26);
}
.defi-title {
  font-family: var(--font-display);
  font-size: 18px;
  color: var(--ink);
  margin: 0 0 4px;
}
.defi-desc {
  font-family: var(--font-body);
  font-size: 12.5px;
  color: var(--ink-soft);
  margin: 0 0 12px;
}
.defi-bar {
  height: 4px;
  background: var(--paper-deep);
  border-radius: 2px;
  overflow: hidden;
  margin-bottom: 6px;
}
.defi-bar-fill {
  height: 100%;
  width: 100%;
  background: var(--brand-dark);
  border-radius: 2px;
  transform-origin: left center;
  transform: scaleX(var(--progress, 0));
}
.defi-meta {
  display: flex;
  justify-content: space-between;
  font-family: var(--font-body);
  font-size: 11px;
  color: var(--ink-muted);
}
.defi-complete-badge {
  font-family: var(--font-body);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  padding: 5px 12px;
  border-radius: 980px;
  background: var(--brand-dark);
  color: var(--cream-fixed);
}

.achievements-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 10px;
}
.achievement {
  text-align: center;
  padding: 18px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--paper);
}
.achievement.is-locked {
  opacity: 0.45;
}
.achievement.is-unlocked {
  background: var(--accent-tint);
  border-color: oklch(0.59 0.16 143 / 0.26);
}
.achievement-name {
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.06em;
  color: var(--ink);
}

/* Abonnement compte — refacto 2026-05-11 : 2 sections (Solo + Famille +)
   chacune avec 2 cards (Mensuel + Annuel). Cohérence /tarifs public qui
   expose les 2 tiers. Funnel cassé fixé : un user qui clique « S'abonner
   Famille + » sur /tarifs peut maintenant souscrire ici. */
.abo-plans {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(20px, 2.4vw, 32px);
  align-items: stretch;
  margin-bottom: 32px;
}
@media (max-width: 900px) {
  .abo-plans {
    grid-template-columns: 1fr;
    max-width: 560px;
    margin: 0 auto 32px;
  }
}
.abo-section-title {
  font-family: var(--font-display, "Young Serif", Georgia, serif);
  font-size: clamp(24px, 3.6vw, 32px);
  font-weight: 400;
  line-height: 1.2;
  color: var(--ink);
  margin: 28px 0 10px;
  letter-spacing: -0.01em;
}
.abo-section-title em {
  font-style: italic;
  color: var(--brand-dark);
}
.abo-section-title--famille {
  margin-top: 48px;
  padding-top: 28px;
  border-top: 1px solid var(--border);
}
.abo-section-lede {
  font-family: var(--font-body);
  font-size: 15px;
  line-height: 1.6;
  color: var(--ink-soft);
  max-width: 64ch;
  margin: 0 0 18px;
}
.abo-section-lede strong {
  color: var(--ink);
  font-weight: 600;
}
.tarif.is-current {
  border-color: var(--brand-dark);
  background: var(--accent-tint);
}
.tarif-current {
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  text-align: center;
  padding: 14px;
  background: var(--brand-dark);
  color: var(--cream-fixed);
  border-radius: var(--radius-sm);
  margin-top: auto;
}
.abo-portail-lede {
  font-family: var(--font-body);
  font-size: 14.5px;
  line-height: 1.6;
  color: var(--ink-soft);
  margin: 0 0 22px;
  max-width: 60ch;
}

/* Espace client / mon compte */
.compte-name {
  font-family: var(--font-display);
  font-size: clamp(28px, 3vw, 38px);
  color: var(--ink);
  letter-spacing: -0.018em;
  line-height: 1.1;
  margin: 6px 0 4px;
}
.compte-email {
  font-family: var(--font-body);
  font-size: 13px;
  color: var(--ink-muted);
  margin-bottom: 14px;
}
.compte-verify-warning {
  display: inline-block;
  font-family: var(--font-body);
  font-size: 12px;
  color: var(--danger);
  background: var(--brick-tint);
  border: 1px solid oklch(0.59 0.16 143 / 0.26);
  border-radius: var(--radius-sm);
  padding: 8px 14px;
  margin-top: 12px;
  text-decoration: none;
}
.compte-plan {
  background: var(--paper);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 20px 24px;
  margin-bottom: 18px;
}
.compte-plan-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 12px;
}
.compte-plan-name {
  font-family: var(--font-display);
  font-size: 22px;
  color: var(--ink);
  margin-bottom: 4px;
}
.compte-plan-price {
  font-family: var(--font-body);
  font-size: 13px;
  color: var(--ink-soft);
}
.compte-plan-status {
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  padding: 6px 14px;
  border-radius: 980px;
  background: var(--accent-tint);
  color: var(--brand-dark);
}
.compte-plan-meta {
  font-family: var(--font-body);
  font-size: 12px;
  color: var(--ink-muted);
  margin: 6px 0 0;
}
.compte-plan-meta--warn {
  color: var(--danger);
}
.compte-plan-actions {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
}
/* Note rassurante sous le bouton « Gérer mon abonnement » qui ouvre
   le portail Stripe externe. Réduit l'anxiété Claudette (cible 65+
   qui ne connaît pas Stripe). Petite mais lisible. */
.compte-plan-note {
  margin-top: 12px;
  padding: 12px 14px;
  background: var(--accent-tint);
  border: 1px solid color-mix(in oklch, var(--accent, var(--brand)) 22%, transparent);
  border-radius: 8px;
  font-size: 13px;
  line-height: 1.55;
  color: var(--ink-soft);
}

/* ── Onboarding cards inline (pattern Linear/Notion) ──────────
   Section sous le hero dashboard, 3 cards dismissables
   individuellement. Voix grand-maman préservée. Disparait quand
   les 3 sont fermées. Marche sans localStorage (mode privé iOS). */
.onb-cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 14px;
  margin: 28px 0 8px;
}
.onb-card {
  position: relative;
  padding: 18px 40px 18px 18px;
  background: var(--accent-tint);
  border: 1px solid color-mix(in oklch, var(--brand) 25%, transparent);
  border-radius: 14px;
  transition:
    opacity 0.22s ease,
    transform 0.22s ease;
}
.onb-card.is-leaving {
  opacity: 0;
  transform: translateY(-4px);
}
/* .onb-card-eyebrow supprime 2026-05-09 (audit R27) : eyebrows
   numerotes « Astuce 1/3 · 2/3 · 3/3 » retires de la blade
   (CLAUDE.md anti-pattern « eyebrows numerotes »). Classe orpheline. */
.onb-card-title {
  font-family: var(--font-display);
  font-size: 17px;
  font-weight: 400;
  font-style: italic;
  letter-spacing: -0.01em;
  color: var(--ink);
  margin-bottom: 6px;
  line-height: 1.25;
}
.onb-card p {
  font-size: 15px;
  line-height: 1.55;
  color: var(--ink-soft);
  margin: 0;
}
.onb-card-close {
  position: absolute;
  top: 8px;
  right: 8px;
  width: 32px;
  height: 32px;
  border: none;
  background: transparent;
  font-size: 14px;
  color: var(--ink-muted);
  cursor: pointer;
  border-radius: 50%;
  transition:
    background 0.15s,
    color 0.15s;
}
@media (hover: hover) and (pointer: fine) {
  .onb-card-close:hover {
    background: var(--paper-soft);
    color: var(--ink);
  }
}
.onb-card-close:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 1px;
}

/* Banner urgent courriel non vérifié — fond ambre courge (urgent
   sans agressif), placé EN TÊTE de /mon-compte. Avant : petite
   ligne 11px en bas de hero. Maintenant : prominent, scannable,
   actionable en 1 tap. */
.compte-verify-banner {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 18px;
  margin: 16px 0;
  background: var(--accent-tint);
  border: 1px solid color-mix(in oklch, var(--courge) 35%, transparent);
  border-radius: 12px;
  text-decoration: none;
  color: var(--ink);
  font-size: 14px;
  line-height: 1.5;
  transition:
    transform 0.15s ease,
    border-color 0.15s ease;
}
@media (hover: hover) and (pointer: fine) {
  .compte-verify-banner:hover {
    transform: translateY(-1px);
    border-color: var(--courge);
  }
}
.compte-verify-banner-icon {
  font-size: 22px;
  flex-shrink: 0;
}
.compte-verify-banner-text {
  flex: 1;
  min-width: 0;
}
.compte-verify-banner-arrow {
  font-size: 18px;
  color: var(--courge);
  flex-shrink: 0;
}
.compte-cancel {
  color: var(--danger) !important;
  border-color: oklch(0.44 0.14 25 / 0.34) !important;
}
.compte-invoice {
  display: grid;
  grid-template-columns: 1fr auto auto auto;
  gap: 16px;
  align-items: center;
  padding: 14px 0;
  border-bottom: 1px solid var(--border2);
}
.compte-invoice:last-child {
  border-bottom: none;
}
.compte-invoice-date {
  font-family: var(--font-display);
  font-size: 16px;
  color: var(--ink);
}
.compte-invoice-num {
  font-family: var(--font-body);
  font-size: 11.5px;
  color: var(--ink-muted);
}
.compte-invoice-amount {
  font-family: var(--font-body);
  font-size: 15px;
  font-weight: 700;
  color: var(--brand-dark);
  font-variant-numeric: tabular-nums;
}
.compte-invoice-status {
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--brand-dark);
}
.compte-invoice-pdf {
  padding: 6px 12px;
  font-size: 11px;
}

/* Navigation interne en haut de /mon-compte : permet le deeplink (#abonnement,
   #stats, etc.) depuis /profil ou la sidebar. Style chip compact, scroll
   horizontal sur mobile, smooth-scroll au tap. */
.compte-jump {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 24px;
  padding: 14px;
  background: var(--paper-soft);
  border-radius: 14px;
  border: 1px solid var(--border);
}
.compte-jump a {
  padding: 8px 14px;
  background: var(--paper-sheet);
  border: 1px solid var(--border);
  border-radius: 999px;
  font-size: 13px;
  font-weight: 600;
  color: var(--ink);
  text-decoration: none;
  white-space: nowrap;
  transition:
    background 0.15s,
    border-color 0.15s;
}
@media (hover: hover) and (pointer: fine) {
  .compte-jump a:hover {
    background: var(--accent-tint);
    border-color: var(--accent);
  }
}
.compte-jump-danger {
  color: var(--danger) !important;
}
@media (hover: hover) and (pointer: fine) {
  .compte-jump-danger:hover {
    background: color-mix(in oklch, var(--danger) 12%, transparent) !important;
    border-color: var(--danger) !important;
  }
}
html {
  scroll-behavior: smooth;
  scroll-padding-top: 16px;
}

.compte-quicklinks {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 12px;
}
.compte-quicklink {
  display: block;
  padding: 18px 22px;
  background: var(--paper);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  text-decoration: none;
  transition:
    border-color 0.25s,
    transform 0.25s;
}
@media (hover: hover) and (pointer: fine) {
  .compte-quicklink:hover {
    border-color: var(--brand-dark);
    transform: translateY(-2px);
  }
}
.compte-quicklink-name {
  font-family: var(--font-display);
  font-size: 16px;
  color: var(--ink);
  margin-bottom: 4px;
}
.compte-quicklink-meta {
  font-family: var(--font-body);
  font-size: 11.5px;
  color: var(--ink-muted);
}
.compte-danger {
  border: 1px solid oklch(0.44 0.14 25 / 0.26);
  border-radius: var(--radius-xl);
  background: var(--danger-tint);
  padding: 24px 28px;
}
.compte-danger-lede {
  font-family: var(--font-body);
  font-size: 14px;
  color: var(--ink-soft);
  margin: 0 0 18px;
}

.compte-modal {
  position: fixed;
  inset: 0;
  background: oklch(0.18 0.016 120 / 0.42);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
  border: none;
  margin: 0;
  padding: 24px;
  width: 100%;
  height: 100dvh;
  inset: 0;
}
.compte-modal[hidden] {
  display: none;
}
.compte-modal-inner {
  background: var(--paper-sheet);
  border-radius: var(--radius-xl);
  padding: 36px;
  max-width: 460px;
  width: 100%;
  box-shadow: var(--shadow-lg);
}
.compte-modal-title {
  font-family: var(--font-display);
  font-size: 24px;
  color: var(--ink);
  margin: 0 0 14px;
}
.compte-modal p {
  font-family: var(--font-body);
  font-size: 14px;
  color: var(--ink-soft);
  line-height: 1.6;
  margin: 0 0 22px;
}
.compte-modal-actions {
  display: flex;
  gap: 10px;
  margin-top: 18px;
}
.compte-modal-actions > * {
  flex: 1;
}
.compte-delete-confirm {
  background: var(--danger) !important;
  color: var(--cream-fixed) !important;
}

/* ============================================================
   NEGOCIATEUR / COMPARATEUR / CONGELATION / OPTIMISATION /
   ALERTES / PREVISIONS — Vague 6 batch D
   ============================================================ */

.dash-section-actions {
  display: flex;
  gap: 14px;
  margin-bottom: 28px;
}

/* Negociateur cards */
.negociateur-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
  gap: 20px;
}
.negociateur-card {
  background: var(--paper-sheet);
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  padding: 26px;
  transition:
    border-color 0.25s,
    transform 0.25s;
}
@media (hover: hover) and (pointer: fine) {
  .negociateur-card:hover {
    transform: translateY(-2px);
  }
}
.negociateur-card.is-buy {
  border-color: color-mix(in oklch, var(--brand-dark) 45%, var(--border));
  background: color-mix(in oklch, var(--accent-tint) 55%, var(--cream-fixed));
}
.negociateur-card.is-wait {
  border-color: color-mix(in oklch, var(--danger) 40%, var(--border));
  background: color-mix(in oklch, var(--brick-tint) 55%, var(--cream-fixed));
}
.negociateur-card-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 14px;
  margin-bottom: 18px;
}
.negociateur-card-name {
  font-family: var(--font-display);
  font-size: 18px;
  color: var(--ink);
  letter-spacing: -0.005em;
  margin-bottom: 4px;
}
.negociateur-card-store {
  font-family: var(--font-body);
  font-size: 11.5px;
  color: var(--ink-muted);
  letter-spacing: 0.04em;
}
.negociateur-card-action {
  font-family: var(--font-body);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  padding: 6px 14px;
  border-radius: 980px;
  white-space: nowrap;
}
.negociateur-card.is-buy .negociateur-card-action {
  color: var(--brand-dark);
  background: var(--accent-tint);
  border: 1px solid oklch(0.59 0.16 143 / 0.26);
}
.negociateur-card.is-wait .negociateur-card-action {
  color: var(--brick-deep);
  background: var(--brick-tint);
  border: 1px solid oklch(0.59 0.16 143 / 0.26);
}
.negociateur-prices {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
  margin-bottom: 14px;
}
.negociateur-prices > div {
  background: var(--paper);
  border-radius: 10px;
  padding: 12px 14px;
}
.negociateur-price-label {
  font-family: var(--font-body);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-muted);
  margin-bottom: 6px;
}
.negociateur-price-value {
  font-family: var(--font-display);
  font-size: 22px;
  letter-spacing: -0.018em;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.negociateur-price-value--muted {
  color: var(--ink-soft);
}
.negociateur-card.is-buy .negociateur-price-value:first-of-type {
  color: var(--brand-dark);
}
.negociateur-reason {
  font-family: var(--font-body);
  font-size: 13px;
  line-height: 1.55;
  color: var(--ink-soft);
  margin: 0 0 16px;
}
.negociateur-card-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
}
.negociateur-confidence {
  display: flex;
  align-items: center;
  gap: 8px;
  font-family: var(--font-body);
  font-size: 11px;
}
.negociateur-confidence-label {
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-muted);
}
.negociateur-confidence-bar {
  width: 80px;
  height: 4px;
  background: var(--paper-deep);
  border-radius: 2px;
  overflow: hidden;
}
.negociateur-confidence-fill {
  height: 100%;
  width: 100%;
  background: var(--brand-dark);
  border-radius: 2px;
  transform-origin: left center;
  transform: scaleX(var(--progress, 0));
}
.negociateur-confidence-value {
  color: var(--ink);
  font-weight: 600;
}
.negociateur-wait {
  font-family: var(--font-display);
  font-size: 14px;
  color: var(--danger);
}
.negociateur-add {
  padding: 8px 16px;
  font-size: 12px;
}

/* Comparateur */
.comparateur-search {
  background: var(--paper-sheet);
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  padding: clamp(28px, 3vw, 40px);
  margin-bottom: 28px;
}
.comparateur-search-label {
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--brand-dark);
  display: block;
  margin-bottom: 12px;
}
.comparateur-search-row {
  display: flex;
  gap: 12px;
  align-items: stretch;
}
.comparateur-search-row input {
  flex: 1;
  font-family: var(--font-display);
  font-size: 18px;
  padding: 16px 22px;
  border: 1.5px solid var(--border);
  border-radius: var(--radius);
  background: var(--paper);
  color: var(--ink);
  transition:
    transform 0.2s,
    opacity 0.2s,
    color 0.2s,
    background 0.2s,
    border-color 0.2s,
    box-shadow 0.2s;
}
.comparateur-search-row input:focus {
  outline: none;
  border-color: var(--brand-dark);
  box-shadow: 0 0 0 4px oklch(0.59 0.16 143 / 0.14);
}
.comparateur-search-row .btn-main {
  padding: 16px 28px;
}
.comparateur-tags {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-top: 18px;
}
.comparateur-tags-label {
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-muted);
  margin-right: 4px;
}
.comparateur-tag-form {
  display: inline;
  margin: 0;
}
.comparateur-tag {
  appearance: none;
  background: var(--paper);
  border: 1px solid var(--border);
  border-radius: 980px;
  padding: 7px 14px;
  font-family: var(--font-body);
  font-size: 12px;
  font-weight: 500;
  color: var(--ink-soft);
  cursor: pointer;
  transition:
    transform 0.2s,
    opacity 0.2s,
    color 0.2s,
    background 0.2s,
    border-color 0.2s,
    box-shadow 0.2s;
}
@media (hover: hover) and (pointer: fine) {
  .comparateur-tag:hover {
    border-color: var(--brand-dark);
    color: var(--brand-dark);
    background: var(--accent-tint);
  }
}

.comparateur-row {
  display: grid;
  grid-template-columns: 100px 1fr auto auto;
  align-items: baseline;
  gap: 18px;
  padding: 16px 4px;
  border-bottom: 1px solid var(--border2);
}
.comparateur-row:last-child {
  border-bottom: none;
}
.comparateur-row.is-best {
  background: var(--accent-tint);
  margin: 0 -12px;
  padding: 16px 16px;
  border-radius: var(--radius);
  border-bottom: none;
}
.comparateur-row-store {
  font-family: var(--font-body);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-muted);
  padding: 6px 14px;
  border: 1px solid var(--border);
  border-radius: 980px;
  text-align: center;
}
.comparateur-row.is-best .comparateur-row-store {
  color: var(--brand-dark);
  border-color: var(--brand-dark);
}
.comparateur-row-name {
  font-family: var(--font-display);
  font-size: 16px;
  color: var(--ink);
}
.comparateur-row-format {
  font-family: var(--font-body);
  font-size: 11.5px;
  color: var(--ink-muted);
  margin-top: 2px;
}
.comparateur-row-price {
  font-family: var(--font-body);
  font-size: 18px;
  font-weight: 800;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.comparateur-row.is-best .comparateur-row-price {
  color: var(--brand-dark);
}
.comparateur-row-unit {
  font-family: var(--font-body);
  font-size: 11px;
  color: var(--ink-muted);
}
.comparateur-row-tag {
  font-family: var(--font-body);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--cream-fixed);
  background: var(--brand-dark);
  padding: 4px 10px;
  border-radius: 6px;
}

/* Congelation */
.congelation-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 20px;
}
.congelation-card {
  background: var(--paper-sheet);
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  padding: 28px;
  display: flex;
  flex-direction: column;
}
.congelation-card-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 14px;
  margin-bottom: 16px;
}
.congelation-card-name {
  font-family: var(--font-display);
  font-size: 19px;
  color: var(--ink);
  letter-spacing: -0.008em;
  margin-bottom: 4px;
  line-height: 1.2;
}
.congelation-card-store {
  font-family: var(--font-body);
  font-size: 11.5px;
  color: var(--ink-muted);
  letter-spacing: 0.04em;
}
.congelation-card-discount {
  font-family: var(--font-display);
  font-size: 28px;
  color: var(--brand-dark);
  letter-spacing: -0.018em;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.congelation-card-discount span {
  font-size: 0.5em;
  margin-left: 1px;
}
.congelation-prices {
  display: flex;
  align-items: baseline;
  gap: 12px;
  margin-bottom: 18px;
}
.congelation-price-now {
  font-family: var(--font-display);
  font-size: 28px;
  color: var(--ink);
  letter-spacing: -0.018em;
  font-variant-numeric: tabular-nums;
}
.congelation-price-was {
  font-family: var(--font-body);
  font-size: 14px;
  color: var(--ink-fade);
  text-decoration: line-through;
  font-variant-numeric: tabular-nums;
}
.congelation-meta {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: 0 0 22px;
  padding-bottom: 18px;
  border-bottom: 1px solid var(--border);
}
.congelation-meta > div {
  display: flex;
  justify-content: space-between;
  font-family: var(--font-body);
  font-size: 12.5px;
}
.congelation-meta dt {
  color: var(--ink-muted);
}
.congelation-meta dd {
  color: var(--ink);
  font-weight: 600;
  margin: 0;
  font-variant-numeric: tabular-nums;
}
.congelation-meta dd.is-accent {
  color: var(--brand-dark);
}
.congelation-card-foot {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
  margin-top: auto;
}
.congelation-card-foot .btn-main,
.congelation-card-foot .btn-sec {
  padding: 12px 16px;
  font-size: 13px;
}

/* Optimisation modes */
.optim-modes {
  display: flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
  padding: 18px 24px;
  background: var(--paper-sheet);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  margin-bottom: 24px;
}
.optim-modes-label {
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-muted);
}
.optim-modes-list {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}
.optim-mode {
  font-family: var(--font-body);
  font-size: 12px;
  font-weight: 600;
  padding: 8px 16px;
  border: 1px solid var(--border);
  border-radius: 980px;
  background: var(--paper);
  color: var(--ink-soft);
  text-decoration: none;
  transition:
    transform 0.2s,
    opacity 0.2s,
    color 0.2s,
    background 0.2s,
    border-color 0.2s,
    box-shadow 0.2s;
}
@media (hover: hover) and (pointer: fine) {
  .optim-mode:hover {
    border-color: var(--brand-dark);
    color: var(--brand-dark);
  }
}
.optim-mode.is-active {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--cream-fixed);
}
.optim-modes-warning {
  margin-left: auto;
  font-family: var(--font-body);
  font-size: 11.5px;
  color: var(--danger);
  font-style: italic;
  text-decoration: underline;
}

.optim-best {
  background: var(--paper-sheet);
  border: 1px solid var(--brand-dark);
  border-radius: var(--radius-xl);
  padding: 32px;
}
.optim-best-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 24px;
  padding-bottom: 24px;
  margin-bottom: 24px;
  border-bottom: 1px solid var(--border);
}
.optim-best-label {
  font-family: var(--font-body);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-muted);
  margin-bottom: 8px;
}
.optim-best-value {
  font-family: var(--font-display);
  font-size: 26px;
  color: var(--ink);
  letter-spacing: -0.018em;
  font-variant-numeric: tabular-nums;
}
.optim-best-value--accent {
  color: var(--brand-dark);
}
.optim-items {
  list-style: none;
  padding: 0;
  margin: 0;
}
.optim-item {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 16px;
  align-items: baseline;
  padding: 12px 0;
  border-bottom: 1px solid var(--border2);
}
.optim-item:last-child {
  border-bottom: none;
}
.optim-item-name {
  font-family: var(--font-body);
  font-size: 14px;
  font-weight: 600;
  color: var(--ink);
  margin-bottom: 2px;
}
.optim-item-meta {
  font-family: var(--font-body);
  font-size: 11.5px;
  color: var(--ink-muted);
}
.optim-item-price {
  font-family: var(--font-body);
  font-weight: 700;
  color: var(--brand-dark);
  font-variant-numeric: tabular-nums;
  text-align: right;
}
.optim-item-was {
  display: block;
  font-size: 11px;
  color: var(--ink-fade);
  text-decoration: line-through;
  font-weight: 500;
  margin-top: 2px;
}

.optim-routes {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
  gap: 18px;
}
.optim-route {
  background: var(--paper-sheet);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 22px 24px;
}
.optim-route.is-unprofitable {
  border-color: oklch(0.44 0.14 25 / 0.26);
}
.optim-route.is-best {
  opacity: 0.65;
}
.optim-route-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-bottom: 12px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--border);
}
.optim-route-name {
  font-family: var(--font-display);
  font-size: 18px;
  color: var(--ink);
}
.optim-route-economy {
  font-family: var(--font-display);
  font-size: 18px;
  color: var(--brand-dark);
  font-variant-numeric: tabular-nums;
}
.optim-route-meta {
  font-family: var(--font-body);
  font-size: 11.5px;
  color: var(--ink-muted);
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 14px;
}
.optim-route-sep {
  width: 3px;
  height: 3px;
  border-radius: 50%;
  background: var(--ink-fade);
}
.optim-route-items {
  font-family: var(--font-body);
  font-size: 12.5px;
}
.optim-route-item {
  display: flex;
  justify-content: space-between;
  padding: 6px 0;
  border-bottom: 1px solid var(--border2);
}
.optim-route-item:last-child {
  border-bottom: none;
}
.optim-route-item span:last-child {
  font-weight: 600;
  color: var(--brand-dark);
  font-variant-numeric: tabular-nums;
}

/* Alertes */
.alertes-triggered {
  display: flex;
  flex-direction: column;
  gap: 0;
  margin-top: 20px;
}
.alertes-triggered-item {
  padding: 12px 0;
  border-bottom: 1px solid var(--border2);
}
.alertes-triggered-item:last-child {
  border-bottom: none;
}
.alertes-triggered-name {
  font-family: var(--font-display);
  font-size: 15px;
  color: var(--ink);
  margin-bottom: 2px;
}
.alertes-triggered-meta {
  font-family: var(--font-body);
  font-size: 11px;
  color: var(--ink-muted);
}
.alertes-triggered-price {
  font-family: var(--font-body);
  font-size: 16px;
  font-weight: 800;
  color: var(--danger);
  font-variant-numeric: tabular-nums;
  margin-top: 6px;
}
.alertes-triggered-price span {
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 500;
  color: var(--ink-muted);
  margin-left: 8px;
}

.alerte-row {
  display: grid;
  grid-template-columns: 1fr auto auto;
  gap: 16px;
  align-items: center;
  padding: 14px 0;
  border-bottom: 1px solid var(--border2);
}
.alerte-row:last-child {
  border-bottom: none;
}
.alerte-row.is-paused {
  opacity: 0.55;
}
.alerte-row-name {
  font-family: var(--font-display);
  font-size: 16px;
  color: var(--ink);
  margin-bottom: 2px;
}
.alerte-row-meta {
  font-family: var(--font-body);
  font-size: 11.5px;
  color: var(--ink-muted);
  font-variant-numeric: tabular-nums;
}
.alerte-toggle {
  appearance: none;
  background: var(--paper);
  border: 1px solid var(--border);
  border-radius: 980px;
  padding: 6px 14px;
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  color: var(--ink-muted);
  cursor: pointer;
  transition:
    transform 0.2s,
    opacity 0.2s,
    color 0.2s,
    background 0.2s,
    border-color 0.2s,
    box-shadow 0.2s;
}
.alerte-toggle.is-active {
  color: var(--brand-dark);
  background: var(--accent-tint);
  border-color: oklch(0.59 0.16 143 / 0.26);
}
.pantry-row-delete-btn {
  appearance: none;
  background: transparent;
  border: none;
  width: 32px;
  height: 32px;
  border-radius: 8px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--ink-fade);
  cursor: pointer;
  transition:
    transform 0.2s,
    opacity 0.2s,
    color 0.2s,
    background 0.2s,
    border-color 0.2s,
    box-shadow 0.2s;
}
@media (hover: hover) and (pointer: fine) {
  .pantry-row-delete-btn:hover {
    background: var(--danger-tint);
    color: var(--danger);
  }
}

/* Prévisions */
.prev-legend {
  display: flex;
  gap: 24px;
  flex-wrap: wrap;
  margin-bottom: 28px;
  font-family: var(--font-body);
  font-size: 12px;
  color: var(--ink-muted);
}
.prev-legend-item {
  display: flex;
  align-items: center;
  gap: 8px;
}
.prev-legend-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
}
.prev-legend-dot--now {
  background: var(--brand-dark);
}
.prev-legend-dot--soon {
  background: var(--danger);
}
.prev-legend-dot--later {
  background: var(--ink-fade);
}

.prev-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 18px;
}
.prev-card {
  background: var(--paper-sheet);
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  padding: 22px 24px;
  transition: border-color 0.25s;
}
.prev-card--maintenant {
  border-color: oklch(0.59 0.16 143 / 0.26);
  background: var(--accent-tint);
}
.prev-card--bientot {
  border-color: oklch(0.59 0.16 143 / 0.26);
  background: var(--brick-tint);
}
.prev-card-head {
  display: grid;
  grid-template-columns: 36px 1fr auto;
  gap: 12px;
  align-items: center;
  margin-bottom: 16px;
}
.prev-card-emoji {
  font-size: 28px;
}
.prev-card-name {
  font-family: var(--font-display);
  font-size: 17px;
  color: var(--ink);
  letter-spacing: -0.005em;
  margin-bottom: 2px;
}
.prev-card-months {
  font-family: var(--font-body);
  font-size: 11px;
  color: var(--ink-muted);
}
.prev-card-tag {
  font-family: var(--font-body);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  padding: 5px 10px;
  border-radius: 980px;
  white-space: nowrap;
  border: 1px solid currentColor;
}
.prev-card--maintenant .prev-card-tag {
  color: var(--brand-dark);
}
.prev-card--bientot .prev-card-tag {
  color: var(--brick-deep);
}
.prev-card--plus_tard .prev-card-tag {
  color: var(--ink-muted);
}
.prev-card-reduction {
  margin-bottom: 14px;
}
.prev-card-reduction-head {
  display: flex;
  justify-content: space-between;
  font-family: var(--font-body);
  font-size: 11.5px;
  color: var(--ink-muted);
  margin-bottom: 6px;
}
.prev-card-reduction-head strong {
  font-family: var(--font-display);
  font-size: 16px;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.prev-card-bar {
  height: 4px;
  background: var(--paper-deep);
  border-radius: 2px;
  overflow: hidden;
}
.prev-card-fill {
  height: 100%;
  width: 100%;
  background: var(--brand-dark);
  border-radius: 2px;
  transform-origin: left center;
  transform: scaleX(var(--progress, 0));
}
.prev-card--bientot .prev-card-fill {
  background: var(--danger);
}
.prev-card-wait {
  font-family: var(--font-body);
  font-size: 12px;
  color: var(--ink-soft);
  margin-bottom: 10px;
}
.prev-card-wait strong {
  color: var(--ink);
}
.prev-card-tip {
  font-family: var(--font-body);
  font-size: 11.5px;
  color: var(--ink-muted);
  font-style: italic;
  line-height: 1.55;
  margin: 0;
}
.prev-footer-note {
  font-family: var(--font-body);
  font-size: 12px;
  color: var(--ink-muted);
  font-style: italic;
  text-align: center;
  margin: 36px 0 0;
  line-height: 1.55;
}

/* ============================================================
   SCAN ÉDITORIAL — recu, scan-frigo — Vague 6 batch C
   ============================================================ */

.scan-editorial {
  background: var(--paper-sheet);
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  padding: clamp(36px, 5vw, 64px);
  margin-bottom: 36px;
  position: relative;
  overflow: hidden;
}
.scan-editorial::before {
  content: "";
  position: absolute;
  top: -160px;
  right: -160px;
  width: 480px;
  height: 480px;
  border-radius: 50%;
  background: radial-gradient(ellipse, var(--accent-tint) 0%, transparent 65%);
  pointer-events: none;
}
.scan-editorial-eyebrow {
  position: relative;
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--brand-dark);
  margin-bottom: 16px;
}
.scan-editorial-title {
  position: relative;
  font-family: var(--font-display);
  font-size: clamp(28px, 3.4vw, 42px);
  font-weight: 400;
  color: var(--ink);
  letter-spacing: -0.018em;
  line-height: 1.06;
  margin: 0 0 18px;
  max-width: 22ch;
  text-wrap: balance;
}
.scan-editorial-title em {
  color: var(--brand-dark);
  font-style: italic;
  font-family: var(--font-display);
}
.scan-editorial-lede {
  position: relative;
  font-family: var(--font-body);
  font-size: 15px;
  line-height: 1.65;
  color: var(--ink-soft);
  margin: 0 0 28px;
  max-width: 56ch;
}
.scan-editorial-form {
  position: relative;
  display: flex;
  align-items: center;
  gap: 18px;
  flex-wrap: wrap;
}
.scan-editorial-form .btn-main {
  padding: 16px 36px;
  font-size: 15px;
}
.scan-editorial-note {
  font-family: var(--font-body);
  font-size: 12px;
  font-style: italic;
  color: var(--ink-muted);
}

.scan-editorial-drop {
  position: relative;
  border: 2px dashed var(--border);
  border-radius: var(--radius-xl);
  padding: 56px 32px;
  text-align: center;
  background: var(--paper);
  cursor: pointer;
  transition:
    border-color 0.25s,
    background 0.25s;
  margin-bottom: 18px;
}
@media (hover: hover) and (pointer: fine) {
  .scan-editorial-drop:hover,
  .scan-editorial-drop.is-drag {
    border-color: var(--brand-dark);
    background: var(--accent-tint);
  }
}
.scan-editorial-drop img {
  max-width: 100%;
  max-height: 320px;
  border-radius: 12px;
  object-fit: cover;
  margin: 0 auto;
}
.scan-editorial-placeholder {
  color: var(--ink-soft);
}
.scan-editorial-placeholder-title {
  font-family: var(--font-display);
  font-size: 22px;
  color: var(--ink);
  margin-bottom: 10px;
}
.scan-editorial-placeholder-meta {
  font-family: var(--font-body);
  font-size: 12.5px;
  color: var(--ink-muted);
  font-style: italic;
}

.scan-editorial-tips {
  position: relative;
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  font-family: var(--font-body);
  font-size: 11.5px;
  color: var(--ink-muted);
  padding: 14px 0 18px;
  letter-spacing: 0.04em;
}
.scan-editorial-tips-label {
  font-weight: 600;
  color: var(--ink-soft);
}
.scan-editorial-tips-sep {
  width: 3px;
  height: 3px;
  border-radius: 50%;
  background: var(--ink-fade);
}

.scan-editorial-loading {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  text-align: center;
  font-family: var(--font-display);
  font-size: 18px;
  font-style: italic;
  color: var(--brand-dark);
  margin-top: 24px;
  padding: 22px;
  background: var(--accent-tint);
  border: 1px solid oklch(0.59 0.16 143 / 0.22);
  border-radius: var(--radius);
}
.scan-loading-spinner {
  width: 20px;
  height: 20px;
  border-radius: 50%;
  border: 2.5px solid var(--accent-tint);
  border-top-color: var(--brand-dark);
  animation: spin 0.8s linear infinite;
}
@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

/* Dropzone */
.scan-dropzone {
  margin-top: 16px;
  padding: 28px;
  border: 2px dashed var(--border);
  border-radius: var(--radius-lg);
  text-align: center;
  transition:
    transform 0.2s,
    opacity 0.2s,
    color 0.2s,
    background 0.2s,
    border-color 0.2s,
    box-shadow 0.2s;
}
.scan-dropzone.is-over {
  border-color: var(--brand-dark);
  background: var(--accent-tint);
}
.scan-dropzone-text {
  font-size: 13px;
  color: var(--ink-muted);
  font-weight: 500;
}
.scan-dropzone.is-over .scan-dropzone-text {
  color: var(--brand-dark);
}
.scan-btn-label {
  cursor: pointer;
  display: inline-block;
}
.scan-buttons {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
}
.scan-buttons .btn-main,
.scan-buttons .btn-sec {
  flex: 1;
  min-width: 180px;
  text-align: center;
}
@media (max-width: 480px) {
  .scan-buttons {
    flex-direction: column;
  }
  .scan-buttons .btn-main,
  .scan-buttons .btn-sec {
    min-width: auto;
  }
}

.recu-price {
  font-family: var(--font-body);
  font-size: 14.5px;
  font-weight: 700;
  color: var(--brand-dark);
  font-variant-numeric: tabular-nums;
}

.recu-actions {
  display: flex;
  gap: 14px;
  flex-wrap: wrap;
  margin-top: 36px;
}
.recu-actions .btn-main,
.recu-actions .btn-sec {
  padding: 14px 24px;
}

/* Scan result selection list */
.scan-result-actions {
  display: flex;
  gap: 10px;
  align-self: end;
}
.scan-result-actions .btn-sec {
  padding: 8px 14px;
  font-size: 11.5px;
}

.scan-result-item {
  display: grid;
  grid-template-columns: 24px 36px 1fr auto;
  align-items: center;
  gap: 14px;
  padding: 14px 0;
  border-bottom: 1px solid var(--border2);
  cursor: pointer;
}
.scan-result-item:last-child {
  border-bottom: none;
}
.scan-result-checkbox {
  width: 20px;
  height: 20px;
  accent-color: var(--brand-dark);
  cursor: pointer;
}
.scan-result-emoji {
  font-size: 22px;
}
.scan-result-info {
  min-width: 0;
}
.scan-result-name {
  font-family: var(--font-display);
  font-size: 16px;
  color: var(--ink);
  margin-bottom: 3px;
  letter-spacing: -0.005em;
}
.scan-result-meta {
  font-family: var(--font-body);
  font-size: 11.5px;
  color: var(--ink-muted);
  font-variant-numeric: tabular-nums;
}
.scan-result-note {
  font-family: var(--font-body);
  font-size: 11px;
  color: var(--danger);
  font-style: italic;
  margin-top: 2px;
}
.scan-result-confidence {
  font-family: var(--font-body);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-muted);
  white-space: nowrap;
}

.dash-pull-alert {
  margin-top: 14px;
  padding: 10px 16px;
  background: var(--accent-tint);
  border: 1px solid oklch(0.62 0.14 68 / 0.26);
  border-radius: var(--radius-sm);
  font-family: var(--font-body);
  font-size: 13px;
  font-style: italic;
  color: oklch(0.42 0.12 68);
}

/* ============================================================
   NUTRITION / INFLATION / ADN / SCORE — Vague 6 batch B
   ============================================================ */

/* Nutrition bars */
.nutrition-bars {
  display: flex;
  flex-direction: column;
  gap: 18px;
}
.nutrition-bar-head {
  display: flex;
  justify-content: space-between;
  font-family: var(--font-body);
  margin-bottom: 8px;
}
.nutrition-bar-name {
  font-size: 13px;
  font-weight: 600;
  color: var(--ink);
}
.nutrition-bar-value {
  font-family: var(--font-display);
  font-size: 16px;
  letter-spacing: -0.01em;
  font-variant-numeric: tabular-nums;
}
.nutrition-bar-value--good {
  color: var(--brand-dark);
}
.nutrition-bar-value--warn {
  color: var(--danger);
}
.nutrition-bar-value--low {
  color: var(--danger);
}
.nutrition-bar-track {
  height: 4px;
  background: var(--paper-deep);
  border-radius: 2px;
  overflow: hidden;
}
.nutrition-bar-fill {
  height: 100%;
  width: 100%;
  border-radius: 2px;
  transform-origin: left center;
  transform: scaleX(var(--progress, 0));
  transition: transform 1s cubic-bezier(0.22, 1, 0.36, 1);
  will-change: transform;
}
.nutrition-bar-fill--good {
  background: var(--brand-dark);
}
.nutrition-bar-fill--warn {
  background: var(--danger);
}
.nutrition-bar-fill--low {
  background: var(--danger);
}

/* Two-column nutrition / adn grid */
.nutrition-grid,
.adn-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(24px, 3vw, 40px);
}
@media (max-width: 1024px) {
  .nutrition-grid,
  .adn-grid {
    grid-template-columns: 1fr;
  }
}

.nutrition-list {
  list-style: none;
  padding: 0;
  margin: 0;
}
.nutrition-list-item {
  font-family: var(--font-body);
  font-size: 14px;
  line-height: 1.55;
  color: var(--ink);
  padding: 12px 0 12px 26px;
  border-bottom: 1px solid var(--border2);
  position: relative;
}
.nutrition-list-item:last-child {
  border-bottom: none;
}
.nutrition-list-item::before {
  content: "";
  position: absolute;
  left: 0;
  top: 18px;
  width: 14px;
  height: 6px;
  border-left: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: rotate(-45deg);
}
.nutrition-list-item--good {
  color: var(--ink);
}
.nutrition-list-item--good::before {
  color: var(--brand-dark);
}
.nutrition-list-item--warn::before {
  border: none;
  width: 12px;
  height: 12px;
  background: none;
  top: 16px;
  transform: none;
  color: var(--danger);
}
.nutrition-list-item--warn::before {
  content: "→";
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 14px;
  border: none;
}

.nutrition-suggestions {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 14px;
}
.nutrition-suggestion {
  background: var(--paper-soft);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 18px 20px;
}
.nutrition-suggestion-day {
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--brand-dark);
  margin-bottom: 8px;
}
.nutrition-suggestion-text {
  font-family: var(--font-body);
  font-size: 13.5px;
  line-height: 1.6;
  color: var(--ink-soft);
}

/* Pull quote dans dashboard */
.dash-pull {
  background: var(--accent-tint);
  border: 1px solid oklch(0.59 0.16 143 / 0.22);
  border-radius: var(--radius-xl);
  padding: clamp(28px, 3vw, 40px) clamp(28px, 4vw, 56px);
  margin: 32px 0;
}
.dash-pull-eyebrow {
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--brand-dark);
  margin-bottom: 14px;
}
.dash-pull p {
  font-family: var(--font-display);
  font-size: clamp(18px, 2vw, 24px);
  font-style: italic;
  line-height: 1.45;
  color: var(--ink);
  margin: 0;
}

/* Inflation cards */
.inflation-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
  gap: 20px;
}
.inflation-card {
  background: var(--paper-sheet);
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  padding: 24px 26px 22px;
  transition:
    border-color 0.25s,
    transform 0.25s;
}
@media (hover: hover) and (pointer: fine) {
  .inflation-card:hover {
    border-color: var(--brand-dark);
    transform: translateY(-2px);
  }
}
.inflation-card-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 16px;
  margin-bottom: 16px;
}
.inflation-card-info {
  min-width: 0;
}
.inflation-card-name {
  font-family: var(--font-display);
  font-size: 18px;
  font-weight: 400;
  color: var(--ink);
  letter-spacing: -0.005em;
  line-height: 1.2;
  margin-bottom: 4px;
}
.inflation-card-meta {
  font-family: var(--font-body);
  font-size: 11.5px;
  color: var(--ink-muted);
  letter-spacing: 0.04em;
}
.inflation-card-variation {
  font-family: var(--font-display);
  font-size: 26px;
  letter-spacing: -0.018em;
  line-height: 1;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.inflation-card-variation span {
  font-size: 0.6em;
  margin-left: 1px;
}
.inflation-card--up .inflation-card-variation {
  color: var(--danger);
}
.inflation-card--down .inflation-card-variation {
  color: var(--brand-dark);
}
.inflation-card--flat .inflation-card-variation {
  color: var(--ink-muted);
}
.inflation-card-chart {
  width: 100%;
  height: 60px;
  margin-bottom: 16px;
}
.inflation-card-foot {
  font-family: var(--font-body);
  font-size: 11.5px;
  color: var(--ink-muted);
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  font-variant-numeric: tabular-nums;
  border-top: 1px solid var(--border2);
  padding-top: 14px;
}
.inflation-card-foot strong {
  color: var(--ink);
  font-weight: 700;
}
.inflation-card-alert {
  margin-left: auto;
  font-size: 11px;
  font-weight: 600;
  color: var(--danger);
  text-decoration: none;
  padding: 2px 8px;
  border: 1px solid var(--brick-tint);
  border-radius: 980px;
  transition:
    transform 0.2s,
    opacity 0.2s,
    color 0.2s,
    background 0.2s,
    border-color 0.2s,
    box-shadow 0.2s;
}
@media (hover: hover) and (pointer: fine) {
  .inflation-card-alert:hover {
    background: var(--brick-tint);
  }
}
.inflation-card-sep {
  width: 3px;
  height: 3px;
  border-radius: 50%;
  background: var(--ink-fade);
}

/* ADN */
.adn-progress {
  font-family: var(--font-display);
  font-size: 18px;
  color: var(--ink-soft);
  margin: 14px 0 22px;
  font-style: italic;
}
.adn-progress strong {
  color: var(--brand-dark);
  font-style: normal;
  font-weight: 400;
}

.adn-hero {
  background: var(--paper-sheet);
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  padding: clamp(40px, 5vw, 64px);
  text-align: center;
  margin-bottom: 36px;
  position: relative;
  overflow: hidden;
}
.adn-hero::before {
  content: "";
  position: absolute;
  top: -120px;
  left: 50%;
  transform: translateX(-50%);
  width: 480px;
  height: 480px;
  border-radius: 50%;
  background: radial-gradient(ellipse, var(--accent-tint) 0%, transparent 65%);
  pointer-events: none;
}
.adn-hero-eyebrow {
  position: relative;
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--brand-dark);
  margin-bottom: 18px;
}
.adn-hero-title {
  position: relative;
  font-family: var(--font-display);
  font-size: clamp(32px, 4vw, 52px);
  font-weight: 400;
  color: var(--ink);
  letter-spacing: -0.022em;
  line-height: 1.06;
  margin: 0 0 14px;
  text-wrap: balance;
}
.adn-hero-subtitle {
  position: relative;
  font-family: var(--font-display);
  font-size: 18px;
  font-style: italic;
  color: var(--brand-dark);
  margin-bottom: 16px;
}
.adn-hero-meta {
  position: relative;
  font-family: var(--font-body);
  font-size: 12px;
  color: var(--ink-muted);
  font-style: italic;
}

.adn-traits {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 24px;
}
.adn-trait {
  background: var(--paper-sheet);
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  padding: 28px 26px;
  text-align: center;
  transition: border-color 0.25s;
}
@media (hover: hover) and (pointer: fine) {
  .adn-trait:hover {
    border-color: var(--brand-dark);
  }
}
.adn-trait-rank {
  font-family: var(--font-display);
  font-size: 24px;
  color: var(--brand-dark);
  letter-spacing: -0.018em;
  margin-bottom: 6px;
}
.adn-trait-name {
  font-family: var(--font-display);
  font-size: 17px;
  color: var(--ink);
  margin-bottom: 14px;
}
.adn-trait-value {
  font-family: var(--font-display);
  font-size: 44px;
  color: var(--ink);
  letter-spacing: -0.022em;
  line-height: 1;
  margin-bottom: 14px;
  font-variant-numeric: tabular-nums;
}
.adn-trait-value span {
  font-size: 0.5em;
  color: var(--ink-muted);
}
.adn-trait-track {
  height: 3px;
  background: var(--paper-deep);
  border-radius: 2px;
  overflow: hidden;
  margin-bottom: 14px;
}
.adn-trait-fill {
  height: 100%;
  width: 100%;
  background: var(--brand-dark);
  transform-origin: left center;
  transform: scaleX(var(--progress, 0));
  transition: transform 1s cubic-bezier(0.22, 1, 0.36, 1);
  will-change: transform;
}
.adn-trait-desc {
  font-family: var(--font-body);
  font-size: 12.5px;
  color: var(--ink-muted);
  line-height: 1.55;
  margin: 0;
}

.adn-signature {
  margin-top: 22px;
  padding: 18px 22px;
  background: var(--accent-tint);
  border: 1px solid oklch(0.59 0.16 143 / 0.22);
  border-radius: var(--radius);
}
.adn-signature-eyebrow {
  font-family: var(--font-body);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--brand-dark);
  margin-bottom: 6px;
}
.adn-signature-name {
  font-family: var(--font-display);
  font-size: 18px;
  color: var(--ink);
  font-style: italic;
}

.adn-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 0;
  border-top: 1px solid var(--border);
  margin: 0;
}
.adn-stats > div {
  padding: 18px 22px;
  border-right: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
}
.adn-stats > div:last-child {
  border-right: none;
}
.adn-stats dt {
  font-family: var(--font-body);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-muted);
  margin-bottom: 8px;
}
.adn-stats dd {
  font-family: var(--font-display);
  font-size: 22px;
  color: var(--ink);
  margin: 0;
  letter-spacing: -0.012em;
}

.adn-actions {
  display: flex;
  gap: 14px;
  margin-top: 32px;
  flex-wrap: wrap;
}
.adn-actions form,
.adn-actions .btn-main,
.adn-actions .btn-sec {
  flex: 1;
  min-width: 200px;
}
.adn-actions .btn-main,
.adn-actions .btn-sec {
  padding: 14px 24px;
}

/* Score régional rows */
.score-row {
  display: grid;
  grid-template-columns: 56px 1fr auto auto;
  gap: 20px;
  align-items: baseline;
  padding: 18px 12px;
  border-bottom: 1px solid var(--border2);
}
.score-row:last-child {
  border-bottom: none;
}
.score-row.is-self {
  background: var(--accent-tint);
  margin: 0 -12px;
  padding: 18px 24px;
  border-radius: var(--radius);
  border-bottom: none;
}
.score-row-rank {
  font-family: var(--font-display);
  font-size: 26px;
  color: var(--brand-dark);
  letter-spacing: -0.018em;
  text-align: center;
}
.score-row-name {
  font-family: var(--font-display);
  font-size: 17px;
  color: var(--ink);
}
.score-row.is-self .score-row-name {
  color: var(--brand-dark);
  font-style: italic;
}
.score-row-amount {
  font-family: var(--font-body);
  font-size: 16px;
  font-weight: 700;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.score-row-pct {
  font-family: var(--font-body);
  font-size: 12px;
  color: var(--ink-muted);
  font-variant-numeric: tabular-nums;
}

/* ============================================================
   ÉPARGNE / BILAN / URGENCE — Vague 6 batch A
   ============================================================ */

/* ── Épargne — chart bar comparison + badges éditoriaux ───── */
.epargne-chart {
  display: flex;
  align-items: flex-end;
  gap: 12px;
  height: 140px;
  padding: 16px 0 0;
}
.epargne-bar {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  min-width: 0;
}
.epargne-bar-track {
  position: relative;
  width: 100%;
  max-width: 56px;
}
.epargne-bar-budget {
  width: 100%;
  background: var(--paper-soft);
  border: 1px solid var(--border);
  border-radius: 4px 4px 0 0;
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
}
.epargne-bar-real {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  background: var(--brand-dark);
  border-radius: 4px 4px 0 0;
}
.epargne-bar-label {
  font-family: var(--font-body);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.06em;
  color: var(--ink-muted);
  font-variant-numeric: tabular-nums;
}
.epargne-chart-legend {
  display: flex;
  gap: 24px;
  margin-top: 18px;
  font-family: var(--font-body);
  font-size: 11px;
  color: var(--ink-muted);
}
.epargne-chart-legend > span {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
.epargne-legend-dot {
  width: 10px;
  height: 10px;
  border-radius: 2px;
}
.epargne-legend-dot--budget {
  background: var(--paper-soft);
  border: 1px solid var(--border);
}
.epargne-legend-dot--real {
  background: var(--brand-dark);
}

.epargne-badges {
  display: flex;
  flex-direction: column;
  gap: 0;
}
.epargne-badge {
  display: grid;
  grid-template-columns: 56px 1fr auto;
  align-items: center;
  gap: 24px;
  padding: 22px 0;
  border-bottom: 1px solid var(--border2);
  transition: opacity 0.2s;
}
.epargne-badge:last-child {
  border-bottom: none;
}
.epargne-badge.is-locked {
  opacity: 0.45;
}
.epargne-badge-rank {
  font-family: var(--font-display);
  font-size: 36px;
  color: var(--brand-dark);
  letter-spacing: -0.025em;
  line-height: 1;
  text-align: center;
}
.epargne-badge.is-locked .epargne-badge-rank {
  color: var(--ink-fade);
}
.epargne-badge-name {
  font-family: var(--font-display);
  font-size: 19px;
  font-weight: 400;
  color: var(--ink);
  letter-spacing: -0.005em;
  margin-bottom: 4px;
  line-height: 1.2;
}
.epargne-badge-desc {
  font-family: var(--font-body);
  font-size: 13px;
  color: var(--ink-soft);
  line-height: 1.5;
}
.epargne-badge-status {
  font-family: var(--font-body);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-muted);
  white-space: nowrap;
}
.epargne-badge-status--done {
  color: var(--brand-dark);
}

/* ── Bilan annuel — navigation + 6-stat rule + chart ──────── */
.bilan-nav {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 18px 0 24px;
  border-bottom: 1px solid var(--border);
  margin-bottom: 26px;
  flex-wrap: wrap;
}
.bilan-nav .btn-sec {
  padding: 8px 18px;
  font-size: 13px;
}
.bilan-nav-current {
  font-family: var(--font-display);
  font-size: 28px;
  font-weight: 400;
  color: var(--ink);
  letter-spacing: -0.018em;
  font-variant-numeric: tabular-nums;
  padding: 0 10px;
}
.bilan-nav-export {
  margin-left: auto;
}

.bilan-stats {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  border-top: 2px solid var(--ink);
  border-bottom: 1px solid var(--border);
  margin-bottom: 36px;
}
.bilan-stat {
  padding: 22px 18px;
  border-right: 1px solid var(--border);
}
.bilan-stat:last-child {
  border-right: none;
}
.bilan-stat-eyebrow {
  font-family: var(--font-body);
  font-size: 9.5px;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-muted);
  margin-bottom: 12px;
}
.bilan-stat-value {
  font-family: var(--font-display);
  font-size: clamp(20px, 2.2vw, 28px);
  font-weight: 400;
  color: var(--ink);
  letter-spacing: -0.018em;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}
.bilan-stat-value--accent {
  color: var(--brand-dark);
}

.bilan-chart {
  display: flex;
  align-items: flex-end;
  gap: 14px;
  height: 160px;
  padding: 16px 0;
}
.bilan-bar {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  min-width: 0;
}
.bilan-bar-track {
  position: relative;
  width: 100%;
  max-width: 64px;
  height: 140px;
  display: flex;
  align-items: flex-end;
  justify-content: center;
}
.bilan-bar-fill {
  width: 100%;
  background: var(--brand-dark);
  border-radius: 4px 4px 0 0;
}
.bilan-bar-label {
  font-family: var(--font-body);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.1em;
  color: var(--ink-muted);
}

.bilan-best {
  text-align: center;
  padding: 36px 24px;
  background: var(--accent-tint);
  border: 1px solid oklch(0.59 0.16 143 / 0.22);
  border-radius: var(--radius-xl);
}
.bilan-best-week {
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--brand-dark);
  margin-bottom: 14px;
}
.bilan-best-amount {
  font-family: var(--font-display);
  font-size: clamp(48px, 6vw, 72px);
  color: var(--brand-dark);
  letter-spacing: -0.022em;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  margin-bottom: 14px;
}
.bilan-best-meta {
  font-family: var(--font-body);
  font-size: 13px;
  color: var(--ink-soft);
  font-style: italic;
}

.bilan-share {
  background: var(--paper-sheet);
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  padding: clamp(28px, 3vw, 44px);
}
.bilan-share .dash-section-head {
  border-bottom: 1px solid var(--border);
  padding-bottom: 18px;
  margin-bottom: 24px;
}
.bilan-share-quote {
  font-family: var(--font-display);
  font-size: clamp(20px, 2.4vw, 28px);
  font-style: italic;
  line-height: 1.36;
  color: var(--ink);
  margin: 0 0 28px;
  text-wrap: balance;
}
.bilan-share-quote strong {
  color: var(--brand-dark);
  font-weight: 400;
  font-style: normal;
  font-variant-numeric: tabular-nums;
}
.bilan-share-actions {
  display: flex;
  gap: 14px;
  flex-wrap: wrap;
}

/* ── Urgence souper — bar de temps + 3 recettes editorial ── */
.urgence-bar {
  background: var(--paper-sheet);
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  padding: 28px 32px;
  margin-bottom: 32px;
  position: relative;
  overflow: hidden;
}
.urgence-bar::before {
  content: "";
  position: absolute;
  top: -120px;
  right: -120px;
  width: 320px;
  height: 320px;
  border-radius: 50%;
  background: radial-gradient(ellipse, var(--brick-tint) 0%, transparent 65%);
  pointer-events: none;
}
.urgence-bar-inner {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 32px;
  align-items: center;
  position: relative;
}
.urgence-bar-eyebrow {
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--brick-deep);
  margin-bottom: 8px;
}
.urgence-bar-value {
  font-family: var(--font-display);
  font-size: clamp(48px, 6vw, 72px);
  color: var(--ink);
  letter-spacing: -0.025em;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}
.urgence-bar-value sub {
  font-family: var(--font-body);
  font-size: 0.24em;
  color: var(--ink-muted);
  vertical-align: baseline;
  font-weight: 500;
  margin-left: 8px;
  letter-spacing: 0.04em;
}
.urgence-bar-changer {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  justify-self: end;
}
.urgence-regen {
  margin-left: auto;
  white-space: nowrap;
}
.urgence-bar-label {
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-muted);
  margin-right: 4px;
}
.urgence-time-pill {
  display: inline-flex;
  align-items: center;
  padding: 8px 16px;
  border: 1px solid var(--border);
  border-radius: 980px;
  background: var(--paper);
  font-family: var(--font-body);
  font-size: 12.5px;
  font-weight: 600;
  color: var(--ink-soft);
  text-decoration: none;
  transition:
    transform 0.2s,
    opacity 0.2s,
    color 0.2s,
    background 0.2s,
    border-color 0.2s,
    box-shadow 0.2s;
}
@media (hover: hover) and (pointer: fine) {
  .urgence-time-pill:hover {
    border-color: var(--danger);
    color: var(--brick-deep);
    background: var(--brick-tint);
  }
}
.urgence-time-pill.is-active {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--cream-fixed);
}

.urgence-recipes {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  gap: 24px;
}
.urgence-recipe {
  background: var(--paper-sheet);
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  padding: 32px 28px 28px;
  transition:
    border-color 0.3s,
    transform 0.3s,
    box-shadow 0.3s;
}
.urgence-recipe.is-complete {
  border-color: var(--brand-dark);
  background: var(--accent-tint);
}
.urgence-recipe-head {
  display: grid;
  grid-template-columns: 48px 1fr;
  gap: 18px;
  margin-bottom: 18px;
  padding-bottom: 18px;
  border-bottom: 1px solid var(--border);
}
.urgence-recipe-rank {
  font-family: var(--font-display);
  font-size: 38px;
  color: var(--brand-dark);
  letter-spacing: -0.025em;
  line-height: 1;
  text-align: center;
}
.urgence-recipe-emoji {
  font-size: 30px;
  margin-bottom: 6px;
}
.urgence-recipe-title {
  font-family: var(--font-display);
  font-size: 22px;
  font-weight: 400;
  color: var(--ink);
  margin: 0 0 6px;
  letter-spacing: -0.012em;
  line-height: 1.18;
}
.urgence-recipe-meta {
  font-family: var(--font-body);
  font-size: 11.5px;
  color: var(--ink-muted);
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
}
.urgence-recipe-sep {
  width: 3px;
  height: 3px;
  border-radius: 50%;
  background: var(--ink-fade);
}
.urgence-recipe-urgent {
  color: var(--danger);
  font-weight: 600;
}
.urgence-recipe-ingredients {
  font-family: var(--font-body);
  font-size: 13px;
  line-height: 1.55;
  color: var(--ink-soft);
  margin: 0 0 18px;
}
.urgence-recipe-ingredients-label {
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--ink-muted);
  text-transform: uppercase;
  font-size: 10.5px;
  margin-right: 4px;
}
.urgence-recipe-start {
  width: 100%;
  padding: 14px;
  font-size: 14px;
}
.urgence-recipe-start.is-active {
  background: var(--ink);
  color: var(--cream-fixed);
  cursor: not-allowed;
}

.urgence-steps {
  margin-top: 22px;
  padding-top: 22px;
  border-top: 1px solid var(--border);
}
.urgence-steps-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: 16px;
}
.urgence-steps-label {
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-muted);
}
.urgence-steps-progress {
  font-family: var(--font-display);
  font-size: 14px;
  color: var(--brand-dark);
  font-variant-numeric: tabular-nums;
}
.urgence-steps-list {
  list-style: none;
  padding: 0;
  margin: 0;
}
.urgence-step {
  padding: 8px 0;
  border-bottom: 1px solid var(--border2);
}
.urgence-step:last-child {
  border-bottom: none;
}
.urgence-step.is-done {
  opacity: 0.55;
}
.urgence-step-label {
  display: grid;
  grid-template-columns: 0 28px 1fr;
  gap: 12px;
  align-items: baseline;
  cursor: pointer;
}
.urgence-step-checkbox {
  appearance: none;
  width: 0;
  height: 0;
  position: absolute;
  opacity: 0;
}
.urgence-step-num {
  font-family: var(--font-display);
  font-size: 18px;
  color: var(--ink-muted);
  width: 28px;
  height: 28px;
  border: 1.5px solid var(--border);
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-variant-numeric: tabular-nums;
  transition:
    transform 0.2s,
    opacity 0.2s,
    color 0.2s,
    background 0.2s,
    border-color 0.2s,
    box-shadow 0.2s;
  flex-shrink: 0;
}
.urgence-step-num.is-done {
  background: var(--brand-dark);
  border-color: var(--brand-dark);
  color: var(--cream-fixed);
}
.urgence-step-num.is-done::before {
  content: "";
  width: 6px;
  height: 11px;
  border-right: 2px solid var(--cream-fixed);
  border-bottom: 2px solid var(--cream-fixed);
  transform: rotate(42deg);
  position: relative;
  top: -2px;
}
.urgence-step-num.is-done {
  font-size: 0;
}
.urgence-step-text {
  font-family: var(--font-body);
  font-size: 14px;
  line-height: 1.55;
  color: var(--ink);
}
.urgence-step.is-done .urgence-step-text {
  text-decoration: line-through;
  color: var(--ink-muted);
}

@media (max-width: 1024px) {
  .bilan-stats {
    grid-template-columns: repeat(3, 1fr);
  }
  .bilan-stat:nth-child(3) {
    border-right: none;
  }
}
@media (max-width: 768px) {
  .urgence-bar-inner {
    grid-template-columns: 1fr;
    gap: 24px;
  }
  .urgence-bar-changer {
    justify-self: start;
  }
  .bilan-stats {
    grid-template-columns: 1fr 1fr;
  }
  .bilan-stat:nth-child(odd) {
    border-right: 1px solid var(--border);
  }
  .bilan-stat:nth-child(even) {
    border-right: none;
  }
  .bilan-stat {
    border-bottom: 1px solid var(--border);
  }
  .bilan-stat:nth-last-child(-n + 2) {
    border-bottom: none;
  }
  .bilan-nav {
    font-size: 12px;
  }
  .bilan-nav-export {
    margin-left: 0;
    flex-basis: 100%;
  }
  .epargne-badge {
    grid-template-columns: 40px 1fr;
    gap: 16px;
  }
  .epargne-badge-status {
    grid-column: 1 / -1;
    justify-self: start;
    padding-left: 56px;
    margin-top: -8px;
  }
}

/* ============================================================
   GARDE-MANGER ÉDITORIAL — Vague 5 part 3
   Inventory + add form + urgence souper en grille éditoriale
   plutôt qu'en cartes SaaS. Liste des items groupée par
   urgence d'expiration (urgent / cette semaine / en réserve).
   ============================================================ */

/* Two-column layout : add form + urgence souper */
.pantry-actions {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr);
  gap: clamp(24px, 3vw, 40px);
  margin-bottom: 44px;
  align-items: start;
}
@media (max-width: 1024px) {
  .pantry-actions {
    grid-template-columns: 1fr;
  }
}

/* Form pantry */
.pantry-form {
  margin-bottom: 0;
}
.pantry-form-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px 18px;
}
.pantry-form-grid .form-group {
  margin-bottom: 0;
}
.pantry-form-grid .form-group-wide {
  grid-column: 1 / -1;
}
.pantry-form-grid label {
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-muted);
  margin-bottom: 8px;
  display: block;
}
.pantry-form-grid input,
.pantry-form-grid select {
  width: 100%;
  font-family: var(--font-body);
  font-size: 14.5px;
  padding: 12px 16px;
  border: 1.5px solid var(--border);
  border-radius: 12px;
  background: var(--paper);
  color: var(--ink);
  transition:
    border-color 0.2s,
    box-shadow 0.2s;
}
.pantry-form-grid input:focus,
.pantry-form-grid select:focus {
  outline: none;
  border-color: var(--brand-dark);
  box-shadow: 0 0 0 4px oklch(0.59 0.16 143 / 0.16);
}
.pantry-form-submit {
  grid-column: 1 / -1;
  margin-top: 8px;
  padding: 14px 24px;
  font-size: 14.5px;
}

/* Urgence souper editorial card */
.pantry-urgence {
  background: var(--paper-sheet);
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  padding: clamp(28px, 3vw, 36px);
  position: relative;
  overflow: hidden;
}
.pantry-urgence::before {
  content: "";
  position: absolute;
  top: -120px;
  right: -120px;
  width: 320px;
  height: 320px;
  border-radius: 50%;
  background: radial-gradient(ellipse, var(--brick-tint) 0%, transparent 65%);
  pointer-events: none;
}
.pantry-urgence-eyebrow {
  position: relative;
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--brick-deep);
  margin-bottom: 14px;
}
.pantry-urgence-title {
  position: relative;
  font-family: var(--font-display);
  font-size: clamp(24px, 2.6vw, 30px);
  font-weight: 400;
  color: var(--ink);
  margin: 0 0 16px;
  letter-spacing: -0.014em;
  line-height: 1.12;
  text-wrap: balance;
}
.pantry-urgence-title em {
  color: var(--danger);
  font-style: italic;
  font-family: var(--font-display);
}
.pantry-urgence-lede {
  position: relative;
  font-family: var(--font-body);
  font-size: 14px;
  line-height: 1.62;
  color: var(--ink-soft);
  margin: 0 0 24px;
}
.pantry-urgence-lede strong {
  color: var(--ink);
  font-variant-numeric: tabular-nums;
  font-weight: 700;
}
.pantry-urgence-buttons {
  position: relative;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 10px;
}
.pantry-time {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 16px 8px 14px;
  border: 1px solid var(--border);
  border-radius: 14px;
  background: var(--paper);
  color: var(--ink);
  text-decoration: none;
  transition:
    transform 0.25s,
    opacity 0.25s,
    color 0.25s,
    background 0.25s,
    border-color 0.25s,
    box-shadow 0.25s cubic-bezier(0.22, 1, 0.36, 1);
}
@media (hover: hover) and (pointer: fine) {
  .pantry-time:hover {
    border-color: var(--danger);
    background: var(--brick-tint);
    transform: translateY(-2px);
  }
}
.pantry-time-num {
  font-family: var(--font-display);
  font-size: 28px;
  font-weight: 400;
  color: var(--ink);
  letter-spacing: -0.018em;
  font-variant-numeric: tabular-nums;
  line-height: 1;
  margin-bottom: 4px;
}
.pantry-time-lbl {
  font-family: var(--font-body);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-muted);
}
.pantry-time-active {
  background: var(--ink);
  border-color: var(--ink);
}
.pantry-time-active .pantry-time-num {
  color: var(--cream-fixed);
}
.pantry-time-active .pantry-time-lbl {
  color: oklch(0.92 0.015 85 / 0.65);
}
@media (hover: hover) and (pointer: fine) {
  .pantry-time-active:hover {
    background: oklch(0.18 0.015 110);
    border-color: oklch(0.18 0.015 110);
  }
}

/* Inventory groups */
.pantry-group {
  margin-bottom: 32px;
}
.pantry-group:last-child {
  margin-bottom: 0;
}
.pantry-group-title {
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-muted);
  padding-bottom: 12px;
  margin-bottom: 4px;
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  gap: 10px;
}
.pantry-group-title::before {
  content: "";
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: currentColor;
  flex-shrink: 0;
}
.pantry-group-urgent {
  color: var(--danger);
}
.pantry-group-warn {
  color: var(--danger);
}
.pantry-group-ok {
  color: var(--brand-dark);
}

/* Pantry row — clean editorial line */
.pantry-row {
  display: grid;
  grid-template-columns: 44px 1fr auto auto;
  align-items: center;
  gap: 16px;
  padding: 14px 0;
  border-bottom: 1px solid var(--border2);
}
.pantry-row:last-child {
  border-bottom: none;
}
.pantry-row-emoji {
  font-size: 24px;
  width: 44px;
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--paper-soft);
  border-radius: 12px;
  flex-shrink: 0;
}
.pantry-row-info {
  min-width: 0;
}
.pantry-row-name {
  font-family: var(--font-display);
  font-size: 17px;
  font-weight: 400;
  color: var(--ink);
  letter-spacing: -0.005em;
  line-height: 1.2;
  margin-bottom: 2px;
}
.pantry-row-meta {
  font-family: var(--font-body);
  font-size: 12px;
  color: var(--ink-muted);
  display: flex;
  align-items: center;
  gap: 10px;
  letter-spacing: 0.02em;
}
.pantry-row-sep {
  width: 3px;
  height: 3px;
  border-radius: 50%;
  background: var(--ink-fade);
}
.pantry-row-expire {
  font-family: var(--font-body);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 5px 12px;
  border-radius: 980px;
  white-space: nowrap;
}
.pantry-row-expire--ok {
  background: var(--accent-tint);
  color: var(--brand-dark);
}
.pantry-row-expire--warn {
  background: var(--brick-tint);
  color: var(--brick-deep);
}
.pantry-row-expire--urgent {
  background: var(--danger-tint);
  color: var(--danger);
}
.pantry-row-delete button {
  appearance: none;
  background: transparent;
  border: none;
  width: 32px;
  height: 32px;
  border-radius: 8px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--ink-fade);
  cursor: pointer;
  transition:
    transform 0.2s,
    opacity 0.2s,
    color 0.2s,
    background 0.2s,
    border-color 0.2s,
    box-shadow 0.2s;
}
@media (hover: hover) and (pointer: fine) {
  .pantry-row-delete button:hover {
    background: var(--danger-tint);
    color: var(--danger);
  }
}
/* Consommé / Gaspillé action buttons */
.pantry-row-actions {
  display: flex;
  gap: 4px;
  margin-left: auto;
  flex-shrink: 0;
}
.pantry-action-btn {
  appearance: none;
  background: transparent;
  border: 1px solid var(--border);
  width: 30px;
  height: 30px;
  border-radius: 8px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 13px;
  cursor: pointer;
  transition:
    transform 0.2s,
    opacity 0.2s,
    color 0.2s,
    background 0.2s,
    border-color 0.2s,
    box-shadow 0.2s;
}
.pantry-action-ok {
  color: var(--brand-dark);
}
@media (hover: hover) and (pointer: fine) {
  .pantry-action-ok:hover {
    background: var(--accent-tint);
    border-color: var(--brand-dark);
  }
}
.pantry-action-bad {
  color: var(--ink-fade);
}
@media (hover: hover) and (pointer: fine) {
  .pantry-action-bad:hover {
    background: var(--danger-tint);
    border-color: var(--danger);
    color: var(--danger);
  }
}

@media (max-width: 768px) {
  .pantry-form-grid {
    grid-template-columns: 1fr;
  }
  .pantry-row {
    grid-template-columns: 40px 1fr auto;
    grid-template-areas:
      "emoji info expire"
      "emoji info delete";
    gap: 4px 12px;
  }
  .pantry-row-emoji {
    grid-area: emoji;
    align-self: start;
  }
  .pantry-row-info {
    grid-area: info;
  }
  .pantry-row-expire {
    grid-area: expire;
    align-self: start;
  }
  .pantry-row-delete {
    grid-area: delete;
    align-self: end;
    justify-self: end;
  }
}

/* ============================================================
   MENU ÉDITORIAL — Vague 5 part 2
   La page menu/index vue comme une page de cookbook : day strip
   typographique en haut, recipe spread en bas avec article + side
   de la liste. Pas de bento, pas de cards SaaS.
   ============================================================ */

/* ── Day strip — typographic, no emoji at the center ──────── */
/* ── Day strip v2 : info-dense pills (jour + nom + temps + coût) ──
   Zéro emoji. Scroll horizontal mobile, grid 7 cols desktop. Active
   = bord brand + fond accent-tint. Typo éditoriale Young Serif
   numbers, Commissioner labels. */
.menu-days {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: 8px;
  margin-bottom: 36px;
  overflow-x: auto;
  scrollbar-width: none;
}
.menu-days::-webkit-scrollbar {
  display: none;
}
.menu-day {
  appearance: none;
  background: var(--paper-sheet);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 12px 10px;
  min-height: 92px;
  text-align: left;
  font-family: var(--font-body);
  cursor: pointer;
  transition:
    background 0.2s,
    border-color 0.2s,
    transform 0.15s;
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
}
@media (hover: hover) and (pointer: fine) {
  .menu-day:hover {
    background: var(--paper-soft);
    border-color: var(--ink-muted);
  }
}
/* Drag & drop affordance desktop : cursor: grab signale aux utilisateurs
   souris/trackpad qu'ils peuvent réordonner les jours. Pattern Notion/
   Trello. Mobile garde cursor par défaut (touch n'a pas de hint visuel
   nécessaire car appui long natif). */
@media (hover: hover) and (pointer: fine) {
  .menu-day[draggable="true"] {
    cursor: grab;
  }
  .menu-day[draggable="true"]:active {
    cursor: grabbing;
  }
}
.menu-day.is-active {
  background: var(--accent-tint);
  border-color: var(--brand);
  box-shadow: 0 1px 3px oklch(0.59 0.16 143 / 0.16);
}
.menu-day:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
}
.menu-day-head {
  display: flex;
  align-items: baseline;
  gap: 6px;
}
.menu-day-name {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-muted);
}
.menu-day-date {
  font-family: var(--font-display);
  font-size: 18px;
  font-weight: 400;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
  line-height: 1;
}
.menu-day.is-active .menu-day-date {
  color: var(--accent-deep);
}
.menu-day.is-active .menu-day-name {
  color: var(--accent-deep);
}
.menu-day-recipe {
  font-size: 13px;
  font-weight: 600;
  color: var(--ink);
  line-height: 1.25;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.menu-day.is-active .menu-day-recipe {
  color: var(--ink);
}
.menu-day-meta {
  font-size: 11px;
  color: var(--ink-muted);
  font-variant-numeric: tabular-nums;
  margin-top: auto;
}
.menu-day.is-active .menu-day-meta {
  color: var(--accent-deep);
}
.menu-day-empty-text {
  color: var(--ink-muted);
  font-style: italic;
  font-weight: 500;
}
.menu-day.is-empty {
  opacity: 0.7;
}
@media (hover: hover) and (pointer: fine) {
  .menu-day.is-empty:hover {
    border-color: var(--border);
    background: var(--paper-sheet);
  }
}
/* Responsive : sur mobile, le strip devient compact (day + date seulement,
   stacked). Le nom + temps + coût sont déjà affichés dans le cover
   éditorial juste en dessous — pas besoin de les dupliquer dans les pills. */
@media (max-width: 768px) {
  .menu-days {
    grid-template-columns: repeat(7, minmax(0, 1fr));
    gap: 6px;
    overflow-x: visible;
    padding-bottom: 0;
  }
  .menu-day {
    padding: 10px 4px 8px;
    min-height: 64px;
    align-items: center;
    gap: 2px;
  }
  .menu-day-head {
    flex-direction: column;
    align-items: center;
    gap: 2px;
  }
  .menu-day-name {
    font-size: 10px;
    letter-spacing: 0.1em;
  }
  .menu-day-date {
    font-size: 17px;
  }
  /* Sur mobile, on cache le nom recette + meta (déjà dans le cover) */
  .menu-day-recipe,
  .menu-day-meta {
    display: none;
  }
}
@media (prefers-reduced-motion: reduce) {
  .menu-day {
    transition: none;
  }
}

/* ── Magazine spread — recipe + shopping list side-by-side ── */
.menu-spread {
  display: grid;
  grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr);
  gap: clamp(28px, 4vw, 56px);
  margin-bottom: 48px;
}
/* Mobile (iPhone SE 4.7" et autres petits écrans) : on stacke
   verticalement la recette et la liste d'épicerie. Avant : sidebar
   collait à droite et exigeait 2-3 scrolls pour la voir.
   Maintenant : recette en entier puis liste pleine largeur. */
@media (max-width: 640px) {
  .menu-spread {
    grid-template-columns: 1fr;
    gap: 32px;
  }
}

/* Recipe article */
.menu-recipe {
  min-width: 0;
}

/* Assistant conversationnel */
.assistant-suggestions {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  margin-bottom: 24px;
}
.assistant-suggest {
  padding: 8px 14px;
  border-radius: 980px;
  background: var(--paper-sheet);
  border: 1px solid var(--border);
  font-size: 13px;
  font-weight: 500;
  color: var(--ink-soft);
  cursor: pointer;
  transition:
    transform 0.2s,
    opacity 0.2s,
    color 0.2s,
    background 0.2s,
    border-color 0.2s,
    box-shadow 0.2s;
}
@media (hover: hover) and (pointer: fine) {
  .assistant-suggest:hover {
    background: var(--accent-tint);
    border-color: var(--brand-dark);
    color: var(--brand-dark);
  }
}
.assistant-chat {
  background: var(--paper-sheet);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 20px;
  min-height: 300px;
  max-height: 60vh;
  overflow-y: auto;
  margin-bottom: 16px;
}
.assistant-message {
  display: flex;
  margin-bottom: 14px;
}
.assistant-message--bot {
  justify-content: flex-start;
}
.assistant-message--user {
  justify-content: flex-end;
}
.assistant-bubble {
  max-width: 75%;
  padding: 12px 16px;
  border-radius: 16px;
  font-size: 14.5px;
  line-height: 1.5;
}
.assistant-message--bot .assistant-bubble {
  background: var(--paper-soft);
  color: var(--ink);
  border-bottom-left-radius: 4px;
}
.assistant-message--user .assistant-bubble {
  background: var(--brand-dark);
  color: var(--cream-fixed);
  border-bottom-right-radius: 4px;
}
.assistant-form {
  display: flex;
  gap: 10px;
}
.assistant-form input {
  flex: 1;
  padding: 14px 18px;
  border-radius: var(--radius);
  border: 1px solid var(--border);
  font-size: 15px;
  background: var(--paper-sheet);
  color: var(--ink);
}
.assistant-form input:focus {
  outline: none;
  border-color: var(--brand-dark);
  box-shadow: 0 0 0 3px oklch(0.59 0.16 143 / 0.15);
}
.assistant-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 8px;
  margin-left: 4px;
}
.assistant-action-chip {
  display: inline-block;
  padding: 4px 10px;
  border-radius: 980px;
  background: var(--accent-tint);
  color: var(--brand-dark);
  font-size: 12px;
  font-weight: 600;
  border: 1px solid oklch(0.59 0.16 143 / 0.25);
}

/* Carte membre famille avec préférences */
.membre-card {
  background: var(--paper-soft);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 12px;
  margin-bottom: 8px;
}
.membre-row {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 8px;
}
.membre-prefs {
  display: flex;
  gap: 6px;
  align-items: center;
}

/* Prédictions restock sur dashboard — wrapper <details> repliable.
   Default-collapsed pour réduire la charge visuelle du tab. */
.dash-restock-collapse {
  margin-top: 20px;
  background: var(--paper-soft);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
}
.dash-restock-collapse-summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 14px 18px;
  cursor: pointer;
  list-style: none;
  user-select: none;
}
.dash-restock-collapse-summary::-webkit-details-marker {
  display: none;
}
.dash-restock-collapse-summary:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: -2px;
  border-radius: var(--radius);
}
.dash-restock-count {
  display: inline-block;
  margin-left: 4px;
  padding: 1px 7px;
  background: var(--accent-tint);
  color: var(--brand-dark, var(--brand));
  border-radius: 10px;
  font-size: 11px;
  font-weight: 700;
}
.dash-restock-collapse-cta {
  font-size: 13px;
  font-weight: 600;
  color: var(--brand-dark, var(--brand));
  letter-spacing: 0.04em;
}
/* État ouvert : bascule « Voir » → « Replier » */
.dash-restock-collapse[open] .dash-restock-collapse-cta {
  font-size: 0;
}
.dash-restock-collapse[open] .dash-restock-collapse-cta::before {
  content: "Replier";
  font-size: 13px;
}
.dash-restock-collapse[open] .dash-restock-list {
  padding: 0 18px 14px;
}
.dash-restock-title {
  font-size: 13px;
  font-weight: 700;
  color: var(--ink);
  letter-spacing: -0.2px;
}
.dash-restock-list {
  list-style: none;
  padding: 0;
  margin: 0;
}
.dash-restock-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 6px 0;
  font-size: 14px;
}
.dash-restock-name {
  color: var(--ink-soft);
  font-weight: 500;
}
.dash-restock-when {
  font-size: 12px;
  font-weight: 700;
  color: var(--brand-dark);
  text-transform: uppercase;
  letter-spacing: 0.5px;
}

/* ── Callouts tokenisés — météo, benchmark, saison ─────────────
   Remplace les inline styles rgba(58,112,82,.06) etc. qui parsemaient
   le dashboard. Un seul squelette, variantes par data-tone. */
.dash-callout {
  margin-top: 16px;
  padding: 16px 20px;
  background: var(--paper-sheet);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}
.dash-callout[data-tone="warm"] {
  background: color-mix(in oklch, var(--danger) 7%, var(--paper-sheet));
  border-color: color-mix(in oklch, var(--danger) 30%, var(--border));
}
.dash-callout[data-tone="cool"] {
  background: color-mix(in oklch, var(--ardoise) 7%, var(--paper-sheet));
  border-color: color-mix(in oklch, var(--ardoise) 30%, var(--border));
}
.dash-callout[data-tone="ok"] {
  background: color-mix(in oklch, var(--brand-dark) 6%, var(--paper-sheet));
  border-color: color-mix(in oklch, var(--brand-dark) 25%, var(--border));
}
.dash-callout[data-tone="watch"] {
  background: color-mix(in oklch, oklch(0.72 0.13 75) 6%, var(--paper-sheet));
  border-color: color-mix(in oklch, oklch(0.72 0.13 75) 35%, var(--border));
}
.dash-callout[data-tone="saison"] {
  background: linear-gradient(
    135deg,
    color-mix(in oklch, var(--brand-dark) 8%, var(--paper-sheet)),
    color-mix(in oklch, oklch(0.8 0.1 75) 8%, var(--paper-sheet))
  );
  border-color: color-mix(in oklch, var(--brand-dark) 20%, var(--border));
}
.dash-callout-meta {
  font-size: 11px;
  color: var(--ink-muted);
  margin-top: 2px;
}
.dash-callout-list {
  margin-top: 10px;
}
.dash-callout-body {
  margin-top: 10px;
  font-size: 14px;
  line-height: 1.6;
  color: var(--ink-soft);
}
.dash-callout-footnote {
  margin-top: 8px;
  font-size: 11px;
  color: var(--ink-muted);
}
.dash-callout-cta {
  margin-top: 10px;
}
.dash-callout-cta .btn-sec {
  font-size: 12px;
  padding: 8px 14px;
}
.dash-callout-hit {
  color: var(--brand-dark);
}
.dash-callout-gap {
  color: var(--brick-deep);
}

/* Saison chips — pastilles locales avec produit + % */
.dash-season-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 10px;
}
.dash-season-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 8px 12px;
  background: var(--paper-sheet);
  border-radius: 999px;
  border: 1px solid var(--border);
  font-size: 12px;
  font-weight: 600;
}
.dash-season-chip-emoji {
  font-size: 16px;
}
.dash-season-chip-pct {
  color: var(--brand-dark);
  font-weight: 700;
}

/* Historique prix dans comparateur */
.historique-meta {
  text-align: center;
  margin-top: 16px;
  font-size: 13px;
  color: var(--ink-muted);
  font-variant-numeric: tabular-nums;
}
.historique-meta strong {
  color: var(--ink);
  font-weight: 700;
}

/* Boutons export menu */
.menu-exports {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 20px;
}
.menu-export-btn {
  padding: 8px 14px;
  border-radius: 980px;
  background: var(--paper-sheet);
  border: 1px solid var(--border);
  font-size: 13px;
  font-weight: 600;
  color: var(--ink-soft);
  text-decoration: none;
  transition:
    transform 0.2s,
    opacity 0.2s,
    color 0.2s,
    background 0.2s,
    border-color 0.2s,
    box-shadow 0.2s;
}
@media (hover: hover) and (pointer: fine) {
  .menu-export-btn:hover {
    background: var(--accent-tint);
    border-color: var(--brand-dark);
    color: var(--brand-dark);
  }
}

/* Cover visuel — photo Unsplash + overlay + emoji + badges */
/* ── Recipe cover v2 — éditorial magazine (stats + typo) ─────────
   Zéro emoji géant, zéro gradient rose. Stats chiffrées à gauche
   (type tableau NYT Cooking), eyebrow caps + titre Young Serif
   italique à droite, badges inline texte en bas. */
.menu-recipe-cover--editorial {
  position: relative;
  overflow: hidden;
  display: grid;
  grid-template-columns: minmax(120px, auto) 1fr;
  gap: clamp(20px, 3vw, 36px);
  padding: clamp(24px, 3vw, 36px);
  /* Fluide vs fixe : sur viewport <360px, 220px peut clipper le titre
     long. clamp donne au card la liberté de respirer en dessous tout
     en gardant l'allure éditoriale du desktop. */
  min-height: clamp(180px, 50vw, 220px);
  /* iOS Safari : empêcher la sélection de texte longue-pression sur le
     cover éditorial — le menu contextuel « Copier · Chercher · Traduire »
     surgit sur la moindre tape longue et est difficile à fermer. Le
     titre reste visible/lisible mais non-sélectionnable, comme une
     couverture de magazine imprimée. -webkit-touch-callout:none coupe
     en plus le long-press preview sur les liens iOS Safari. */
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
  background: var(--paper-sheet);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  margin-bottom: 28px;
  box-shadow: 0 2px 12px oklch(0.22 0.02 110 / 0.06);
  isolation: isolate;
}
/* Signature L'Économe : É italique géant en filigrane Vert Jean-Talon
   qui déborde en coin bas-droit. Chaque cover devient une page de
   cookbook magazine signé. C'est LA touche wow qui dit L'Économe. */
.menu-recipe-cover--editorial::before {
  content: "É";
  position: absolute;
  right: clamp(-40px, -4vw, -20px);
  bottom: clamp(-80px, -8vw, -40px);
  font-family: var(--font-display);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(240px, 38vw, 420px);
  line-height: 0.85;
  color: var(--brand);
  opacity: 0.08;
  pointer-events: none;
  z-index: 0;
  user-select: none;
  letter-spacing: -0.04em;
}
/* Filet vert signature en haut : fine barre 2px pleine largeur */
.menu-recipe-cover--editorial::after {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 2px;
  background: var(--brand);
  z-index: 1;
}
.menu-recipe-cover--editorial > * {
  position: relative;
  z-index: 2;
}
.menu-recipe-cover-stats {
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding-right: clamp(16px, 3vw, 28px);
  border-right: 1px solid var(--border);
}
.menu-recipe-cover-stat {
  display: flex;
  align-items: baseline;
  gap: 6px;
  font-variant-numeric: tabular-nums;
}
.menu-recipe-cover-stat-num {
  font-family: var(--font-display);
  font-size: clamp(28px, 4vw, 40px);
  font-weight: 400;
  line-height: 1;
  color: var(--ink);
  font-feature-settings:
    "tnum" 1,
    "lnum" 1;
}
.menu-recipe-cover-stat-unit {
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-muted);
}
.menu-recipe-cover-body {
  display: flex;
  flex-direction: column;
  gap: 10px;
  min-width: 0;
}
.menu-recipe-cover-eyebrow {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--accent-deep);
  line-height: 1.3;
}
.menu-recipe-cover-title {
  font-family: var(--font-display);
  font-size: clamp(22px, 3.2vw, 34px);
  /* Young Serif n'a pas d'italique vrai dans Google Fonts → le navigateur
     fake l'italique par un skew transform qui étend la bounding box des
     glyphes au-delà de la baseline. Avec un line-height trop tight (1.05),
     les descenders italiques fakés (p, g, q, é, j) sortent de la ligne et
     se font clipper par overflow:hidden du parent.
     1.18 = headroom suffisant pour le faux-italique sans casser
     l'allure éditoriale du masthead. */
  line-height: 1.18;
  font-weight: 400;
  font-style: italic;
  color: var(--ink);
  letter-spacing: -0.01em;
  /* Petit padding-bottom pour que même sans badges en dessous, le
     descender du dernier mot ne tangente jamais le bord de la carte. */
  padding-bottom: 4px;
}
.menu-recipe-cover-badges {
  margin-top: auto;
  font-size: 13px;
  color: var(--ink-muted);
  font-style: italic;
  line-height: 1.5;
  /* Padding-bottom 6px : sans ça, le descender du "é" de « adapté
     météo » est coupé par overflow:hidden du parent (le « É » géant
     positionné en absolute bottom déborde et nécessite l'overflow
     hidden). 6px = headroom suffisant pour les ascenders/descenders
     italiques sans casser l'alignement visuel. */
  padding-bottom: 6px;
}
.menu-recipe-cover-badges span {
  color: var(--accent-deep);
  font-style: normal;
  font-weight: 500;
}
@media (max-width: 480px) {
  .menu-recipe-cover--editorial {
    grid-template-columns: 1fr;
    gap: 16px;
    /* Padding-bottom modeste : la cause racine du clipping (height:140px
       legacy) a été supprimée. Plus besoin de 60-90px de buffer panique
       qui rendait la carte démesurée quand le contenu était court. */
    padding-bottom: clamp(28px, 5vw, 40px);
  }
  .menu-recipe-cover-stats {
    flex-direction: row;
    flex-wrap: wrap;
    gap: 18px;
    padding-right: 0;
    padding-bottom: 14px;
    border-right: none;
    border-bottom: 1px solid var(--border);
  }
  .menu-recipe-cover-stat-num {
    font-size: 26px;
  }
  /* En mobile, la grille stacke verticalement : badges suivent le
     titre directement, donc on retire margin-top:auto. */
  .menu-recipe-cover-badges {
    margin-top: 4px;
    padding-bottom: 4px;
    line-height: 1.5;
  }
  /* Titre en mobile : line-height un peu plus aéré pour le faux-italique
     Young Serif sans skew clip. Padding-bottom petit (suffit). */
  .menu-recipe-cover-title {
    line-height: 1.22;
    padding-bottom: 4px;
  }
  /* É filigrane en mobile, taille raisonnable + position qui ne tangente
     pas les descenders du titre. */
  .menu-recipe-cover--editorial::before {
    font-size: clamp(180px, 50vw, 240px);
    bottom: clamp(-100px, -14vw, -50px);
    right: clamp(-50px, -7vw, -25px);
  }
}

/* Vote score — étoiles de la famille */
.menu-recipe-votes {
  display: flex;
  align-items: center;
  gap: 4px;
  margin-top: 10px;
}
.menu-star {
  font-size: 16px;
  color: var(--border);
}
.menu-star.is-filled {
  color: var(--courge);
}
.menu-vote-label {
  font-size: 12px;
  color: var(--ink-muted);
  margin-left: 6px;
}

/* Cuisine tags */
.menu-tag-cuisine {
  padding: 2px 8px;
  border-radius: 980px;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.3px;
  background: var(--paper-deep);
  color: var(--ink-soft);
  text-transform: capitalize;
}

/* Astuce du chef — encadré éditorial */
.menu-astuce-chef {
  display: flex;
  gap: 14px;
  padding: 16px 18px;
  background: var(--paper-sheet);
  border: 1px solid oklch(0.59 0.16 143 / 0.18);
  border-radius: var(--radius);
  margin-top: 20px;
  margin-bottom: 20px;
}
.menu-astuce-icon {
  font-size: 28px;
  flex-shrink: 0;
  line-height: 1.2;
}
.menu-astuce-label {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  color: var(--brand-dark);
  margin-bottom: 4px;
}
.menu-astuce-text {
  font-family: var(--font-display);
  font-size: 14px;
  font-style: italic;
  color: var(--ink-soft);
  line-height: 1.5;
}

/* Legacy : .menu-recipe-cover sans --editorial avait une hauteur fixe
   140px en mobile pour s'adapter au layout image+emoji ancien. Plus
   utilisé : seule .menu-recipe-cover.menu-recipe-cover--editorial
   reste référencée (menu/index.blade.php:114), et elle gère sa propre
   min-height fluide. La règle hauteur fixe clippait le titre wrappé
   sur 3+ lignes (« Morue rôtie à la chermoula, couscous aux légumes »
   se coupait à « aux »). */
@media (max-width: 640px) {
  .menu-recipe-cover-emoji {
    font-size: 56px;
  }
}

.menu-recipe-head {
  margin-bottom: 28px;
}
.menu-recipe-eyebrow {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 16px;
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--brand-dark);
}
.menu-recipe-title {
  font-family: var(--font-display);
  font-size: clamp(36px, 4.6vw, 56px);
  font-weight: 400;
  color: var(--ink);
  line-height: 1.04;
  letter-spacing: -0.022em;
  margin: 0 0 18px;
  text-wrap: balance;
}
.menu-recipe-description {
  font-family: var(--font-display);
  font-size: clamp(17px, 1.6vw, 20px);
  font-style: italic;
  line-height: 1.55;
  color: var(--ink-soft);
  max-width: 56ch;
  margin: 0;
}

/* Recipe meta — definition list, editorial */
.menu-recipe-meta {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 0;
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  margin: 28px 0 36px;
  padding: 0;
}
.menu-recipe-meta > div {
  padding: 18px 16px 18px 0;
  border-right: 1px solid var(--border);
}
.menu-recipe-meta > div:last-child {
  border-right: none;
  padding-right: 0;
}
.menu-recipe-meta dt {
  font-family: var(--font-body);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-muted);
  margin-bottom: 8px;
}
.menu-recipe-meta dd {
  font-family: var(--font-display);
  font-size: 22px;
  font-weight: 400;
  color: var(--ink);
  margin: 0;
  letter-spacing: -0.01em;
  font-variant-numeric: tabular-nums;
}

/* Recipe sections */
.menu-recipe-section {
  margin-bottom: 36px;
}
.menu-recipe-section-title {
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink-muted);
  margin: 0 0 18px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--border);
}

/* Ingredients list — editorial table */
.menu-ingredients {
  list-style: none;
  padding: 0;
  margin: 0;
}
.menu-ingredient {
  display: grid;
  grid-template-columns: 1fr auto auto auto;
  align-items: baseline;
  gap: 14px;
  padding: 14px 0;
  border-bottom: 1px solid var(--border2);
  font-family: var(--font-body);
  font-size: 14.5px;
  color: var(--ink);
}
.menu-ingredient:last-child {
  border-bottom: none;
}
.menu-ingredient-name {
  font-weight: 500;
}
.menu-ingredient-qty {
  font-size: 12.5px;
  color: var(--ink-muted);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.menu-ingredient-source {
  display: inline-flex;
  gap: 6px;
  flex-wrap: wrap;
}
.menu-ingredient-price {
  font-family: var(--font-body);
  font-size: 14px;
  font-weight: 700;
  color: var(--brand-dark);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
/* Estimation (pas de match circulaire) — muted + poids allégé pour
   signaler visuellement que c'est approximatif, sans crier. */
.menu-ingredient-price.is-est {
  color: var(--ink-muted);
  font-weight: 500;
}

/* Tags inside the recipe */
.menu-tag {
  display: inline-flex;
  align-items: center;
  font-family: var(--font-body);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.06em;
  padding: 4px 10px;
  border-radius: 980px;
  border: 1px solid currentColor;
  text-transform: none;
}
.menu-tag-bright {
  color: var(--brand-dark);
  background: var(--accent-tint);
  border-color: oklch(0.59 0.16 143 / 0.26);
}
.menu-tag-cool {
  color: oklch(0.42 0.08 240);
  background: var(--ardoise-tint);
  border-color: oklch(0.52 0.1 220 / 0.26);
}
.menu-tag-pantry {
  color: var(--brand-dark);
  background: var(--accent-tint);
  border-color: oklch(0.59 0.16 143 / 0.26);
}
.menu-tag-store {
  color: var(--ink-soft);
  background: var(--paper-sheet);
  border-color: var(--border);
}
.menu-tag-warn {
  color: var(--danger);
  background: var(--danger-tint);
  border-color: oklch(0.44 0.14 25 / 0.26);
}

/* Instructions */
.menu-instructions {
  font-family: var(--font-body);
  font-size: 14.5px;
  line-height: 1.7;
  color: var(--ink-soft);
  white-space: pre-line;
  background: var(--paper-soft);
  padding: 22px 26px;
  border-radius: var(--radius);
  border: 1px solid var(--border);
}

.menu-recipe-footer {
  margin-top: 16px;
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: stretch;
}
.menu-recipe-footer .btn-main,
.menu-recipe-footer .btn-sec {
  flex: 1 1 auto;
  min-width: 160px;
  text-align: center;
  white-space: normal;
  word-break: normal;
  overflow-wrap: break-word;
  hyphens: none;
  line-height: 1.35;
  padding: 12px 18px;
}
.menu-recipe-footer .btn-main {
  flex: 1 1 100%;
  min-width: 100%;
}
.menu-recipe-footer .menu-swap-form {
  flex: 1 1 auto;
  min-width: 160px;
  display: flex;
}
.menu-recipe-footer .menu-swap-btn {
  width: 100%;
}
@media (min-width: 720px) {
  .menu-recipe-footer .btn-main {
    flex: 1 1 auto;
    min-width: 220px;
  }
}
/* ≤ 480px : tous les boutons stack 100 % pour éviter le wrap
   char-par-char en mode-grand-maman (font-size de base augmentée). */
@media (max-width: 480px) {
  .menu-recipe-footer .btn-sec,
  .menu-recipe-footer .menu-swap-btn {
    flex: 1 1 100%;
    min-width: 100%;
  }
}

/* ── Shopping list sidebar ──────────────────────────────────── */
.menu-list {
  background: var(--paper-sheet);
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  padding: clamp(28px, 3vw, 36px);
  box-shadow: var(--shadow);
  align-self: start;
  position: sticky;
  top: 88px;
}
.menu-list-head {
  margin-bottom: 24px;
  padding-bottom: 18px;
  border-bottom: 1px solid var(--border);
}
.menu-list-eyebrow {
  font-family: var(--font-body);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--brand-dark);
  margin-bottom: 8px;
}
.menu-list-title {
  font-family: var(--font-display);
  font-size: 22px;
  font-weight: 400;
  color: var(--ink);
  letter-spacing: -0.012em;
  line-height: 1.15;
  margin: 0;
  text-wrap: balance;
}
.menu-list-title em {
  color: var(--brand-dark);
  font-style: italic;
  font-family: var(--font-display);
}

.menu-list-group {
  margin-bottom: 22px;
}
.menu-list-group:last-of-type {
  margin-bottom: 12px;
}
.menu-list-group-title {
  font-family: var(--font-body);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-muted);
  padding-bottom: 8px;
  margin-bottom: 6px;
  border-bottom: 1px solid var(--border2);
}

.menu-list-item {
  display: grid;
  grid-template-columns: 22px 1fr auto;
  align-items: center;
  gap: 12px;
  padding: 10px 0;
  font-family: var(--font-body);
  font-size: 14px;
  color: var(--ink);
  cursor: pointer;
}
.menu-list-check {
  width: 20px;
  height: 20px;
  border-radius: 5px;
  border: 1.5px solid var(--border);
  background: var(--paper);
  flex-shrink: 0;
  position: relative;
  cursor: pointer;
  transition:
    transform 0.2s,
    opacity 0.2s,
    color 0.2s,
    background 0.2s,
    border-color 0.2s,
    box-shadow 0.2s;
}
@media (hover: hover) and (pointer: fine) {
  .menu-list-check:hover {
    border-color: var(--brand-dark);
  }
}
.menu-list-check.is-on {
  background: var(--brand-dark);
  border-color: var(--brand-dark);
}
.menu-list-check.is-on::after {
  content: "";
  position: absolute;
  top: 4px;
  left: 6px;
  width: 5px;
  height: 9px;
  border-right: 2px solid var(--paper-sheet);
  border-bottom: 2px solid var(--paper-sheet);
  transform: rotate(42deg);
}
.menu-list-check:focus-visible {
  outline: 2.5px solid var(--brand-dark);
  outline-offset: 3px;
}
.menu-list-name {
  line-height: 1.4;
}
.menu-list-item.is-done .menu-list-name {
  text-decoration: line-through;
  color: var(--ink-fade);
}
.menu-list-qty {
  font-size: 11.5px;
  color: var(--ink-muted);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.menu-list-pantry {
  margin-top: 18px;
  padding: 14px 16px;
  background: var(--accent-tint);
  border: 1px solid oklch(0.59 0.16 143 / 0.22);
  border-radius: 12px;
  font-family: var(--font-body);
  font-size: 12.5px;
  line-height: 1.55;
  color: var(--brand-dark);
}
.menu-list-pantry strong {
  font-weight: 700;
}

/* Rest day panel */
.menu-rest {
  text-align: center;
  padding: 72px 24px;
  background: var(--paper-soft);
  border: 1px dashed var(--border);
  border-radius: var(--radius-xl);
  margin-bottom: 48px;
}
.menu-rest-eyebrow {
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink-muted);
  margin-bottom: 14px;
}
.menu-rest-title {
  font-family: var(--font-display);
  font-size: clamp(28px, 3.6vw, 38px);
  font-weight: 400;
  color: var(--ink);
  letter-spacing: -0.014em;
  margin: 0 0 12px;
  line-height: 1.12;
}
.menu-rest-title em {
  color: var(--brand-dark);
  font-style: italic;
  font-family: var(--font-display);
}
.menu-rest p {
  font-family: var(--font-body);
  font-size: 14.5px;
  color: var(--ink-soft);
  margin: 0;
  line-height: 1.6;
}

/* ── Empty state — magazine cover finale ────────────────────── */
.menu-empty {
  text-align: center;
  padding: clamp(64px, 9vw, 120px) 24px;
  max-width: 600px;
  margin: 0 auto;
}
.menu-empty-rule {
  width: 64px;
  height: 2px;
  background: var(--brand-dark);
  margin: 0 auto 36px;
}
.menu-empty-title {
  font-family: var(--font-display);
  font-size: clamp(34px, 4.4vw, 52px);
  font-weight: 400;
  color: var(--ink);
  letter-spacing: -0.018em;
  line-height: 1.06;
  margin: 0 0 22px;
  text-wrap: balance;
}
.menu-empty-title em {
  color: var(--brand-dark);
  font-style: italic;
  font-family: var(--font-display);
}
.menu-empty-lede {
  font-family: var(--font-body);
  font-size: 16.5px;
  line-height: 1.62;
  color: var(--ink-soft);
  margin: 0 0 32px;
  max-width: 52ch;
  margin-left: auto;
  margin-right: auto;
}
.menu-empty-form {
  margin-bottom: 22px;
}
.menu-empty-form .btn-main {
  padding: 16px 36px;
  font-size: 16px;
}
.menu-empty-note {
  font-family: var(--font-body);
  font-size: 12.5px;
  font-style: italic;
  color: var(--ink-muted);
  margin-top: 18px;
}

/* ── Menu responsive ────────────────────────────────────────── */
@media (max-width: 1024px) {
  .menu-spread {
    grid-template-columns: 1fr;
    gap: 32px;
  }
  .menu-list {
    position: static;
  }
}
@media (max-width: 768px) {
  .menu-days {
    grid-template-columns: repeat(7, 1fr);
  }
  .menu-day {
    padding: 14px 4px 12px;
  }
  .menu-day-date {
    font-size: 20px;
  }
  .menu-day-emoji,
  .menu-day-empty {
    font-size: 16px;
  }
  .menu-recipe-meta {
    grid-template-columns: 1fr 1fr;
  }
  .menu-recipe-meta > div:nth-child(2) {
    border-right: none;
  }
  .menu-recipe-meta > div:nth-child(3) {
    border-right: 1px solid var(--border);
  }
  .menu-ingredient {
    grid-template-columns: 1fr auto;
    gap: 6px 14px;
  }
  .menu-ingredient-source {
    grid-column: 1 / -1;
    margin-top: -4px;
  }
  .menu-ingredient-price {
    grid-column: 2;
  }
}
@media (max-width: 480px) {
  .menu-day-name {
    font-size: 9px;
    letter-spacing: 0.12em;
  }
  .menu-day-date {
    font-size: 18px;
  }
  .menu-recipe-meta {
    grid-template-columns: 1fr;
  }
  .menu-recipe-meta > div {
    border-right: none !important;
    border-bottom: 1px solid var(--border);
  }
  .menu-recipe-meta > div:last-child {
    border-bottom: none;
  }
}

/* ============================================================
   SURFACTURATION — liste d'alertes payé > circulaire
   ============================================================ */
.surfac-list {
  display: grid;
  gap: 14px;
}
.surfac-card {
  background: color-mix(in oklch, var(--danger-tint) 60%, var(--surface));
  border: 1px solid color-mix(in oklch, var(--danger) 22%, var(--border));
  border-radius: 14px;
  padding: 16px 18px;
  display: grid;
  gap: 12px;
}
.surfac-card-head {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
}
.surfac-card-name {
  font-weight: 700;
  font-size: 16px;
}
.surfac-card-epi {
  color: var(--ink-muted);
  font-size: 13px;
}
.surfac-card-prices {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
  font-variant-numeric: tabular-nums;
}
.surfac-price {
  display: grid;
  gap: 2px;
}
.surfac-price-label {
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-muted);
}
.surfac-price-val {
  font-weight: 600;
  font-size: 15px;
}
.surfac-price-arrow {
  color: var(--ink-muted);
  font-size: 18px;
}
.surfac-price-paid .surfac-price-val {
  color: var(--danger);
  text-decoration: line-through;
}
.surfac-price-deal .surfac-price-val {
  color: var(--brand-dark);
}
.surfac-price-diff .surfac-price-val {
  color: var(--danger);
  font-weight: 800;
}
.surfac-card-actions {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}
.surfac-form {
  display: inline;
}
.surfac-ignored {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  gap: 8px;
}
.surfac-ignored li {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  padding: 8px 12px;
  background: var(--surface-alt, #f7f4ec);
  border-radius: 8px;
  color: var(--ink-muted);
  font-size: 13px;
}

/* ============================================================
   PRÉDICTION PRIX — cards colorées par verdict
   ============================================================ */
.pred-list {
  display: grid;
  gap: 14px;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
}
.pred-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 16px 18px;
  display: grid;
  gap: 12px;
  position: relative;
}
.pred-card::before {
  content: "";
  position: absolute;
  top: 18px;
  left: 18px;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--ink-fade);
  box-shadow: 0 0 0 4px color-mix(in oklch, var(--ink-fade) 18%, transparent);
}
.pred-card .pred-head {
  padding-left: 20px;
}
.pred-achete_maintenant {
  background: color-mix(in oklch, var(--accent-tint) 55%, var(--surface));
  border-color: color-mix(in oklch, var(--brand-dark) 22%, var(--border));
}
.pred-achete_maintenant::before {
  background: var(--brand-dark);
  box-shadow: 0 0 0 4px color-mix(in oklch, var(--brand-dark) 22%, transparent);
}
.pred-attends {
  background: color-mix(in oklch, var(--accent-tint) 55%, var(--surface));
  border-color: color-mix(in oklch, var(--courge) 22%, var(--border));
}
.pred-attends::before {
  background: var(--courge);
  box-shadow: 0 0 0 4px color-mix(in oklch, var(--courge) 22%, transparent);
}
.pred-stable::before {
  background: var(--ink-muted);
  box-shadow: 0 0 0 4px color-mix(in oklch, var(--ink-muted) 18%, transparent);
}
.pred-head {
  display: flex;
  justify-content: space-between;
  gap: 10px;
  flex-wrap: wrap;
}
.pred-name {
  font-weight: 700;
  font-size: 15px;
}
.pred-epi {
  color: var(--ink-muted);
  font-size: 13px;
}
.pred-message {
  font-size: 14px;
  line-height: 1.4;
}
.pred-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 8px 14px;
  margin: 0;
  font-size: 13px;
}
.pred-grid > div {
  display: grid;
  gap: 2px;
}
.pred-grid dt {
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-muted);
  font-weight: 500;
}
.pred-grid dd {
  margin: 0;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

@media (max-width: 480px) {
  .surfac-card-prices {
    gap: 8px;
  }
  .surfac-price-arrow {
    display: none;
  }
  .pred-list {
    grid-template-columns: 1fr;
  }
}

/* ============================================================
   MOTION — prefers-reduced-motion respected fully
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 120ms !important;
    scroll-behavior: auto !important;
  }
  .content > * {
    animation: none !important;
  }
}

/* ════════════════════════════════════════════════════════════════════
   PATTERNS WOW (avril 2026) — mini cook bar, pull-to-refresh, toast,
   recipe actions sheet, sticky title morph
   Chaque pattern adapté au registre éditorial L'Économe (mono-accent,
   Young Serif pour la signature É, zéro gradient, zéro side-stripe).
   ════════════════════════════════════════════════════════════════════ */

/* ── Toast réutilisable ────────────────────────────────────── */
.le-toast {
  position: fixed;
  left: 50%;
  bottom: calc(env(safe-area-inset-bottom, 0) + 92px);
  transform: translateX(-50%) translateY(20px);
  padding: 12px 18px;
  background: var(--ink);
  color: var(--cream-fixed);
  border-radius: 14px;
  font-size: 14px;
  font-weight: 500;
  max-width: 92vw;
  text-align: center;
  opacity: 0;
  transition:
    opacity 0.25s ease,
    transform 0.35s cubic-bezier(0.22, 0.61, 0.36, 1);
  z-index: 600;
  pointer-events: none;
  box-shadow: 0 8px 24px oklch(0.18 0.016 120 / 0.25);
  font-feature-settings: "tnum" 1;
}
.le-toast.is-visible {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}
.le-toast.error {
  background: var(--danger);
  color: var(--cream-fixed);
}

/* ── Mini bar « En train de cuisiner » ─────────────────────── */
/* Position : fixe en bas, au-dessus du tabbar mobile (env safe-area).
   Mono-accent Vert Jean-Talon. Signature É Young Serif italique en
   pastille gauche (cohérence avec covers recettes). Tap → reprise. */
.cook-mini-bar {
  position: fixed;
  left: 50%;
  bottom: calc(env(safe-area-inset-bottom, 0) + 76px);
  transform: translateX(-50%);
  width: min(640px, calc(100vw - 24px));
  padding: 10px 12px 10px 14px;
  background: var(--accent);
  color: var(--cream-fixed);
  border-radius: 14px;
  display: flex;
  align-items: center;
  gap: 12px;
  z-index: 95;
  font-family: var(--font-body);
  text-decoration: none;
  cursor: pointer;
  animation: cookMiniIn 0.35s cubic-bezier(0.22, 0.61, 0.36, 1);
  box-shadow: 0 6px 22px oklch(0.59 0.16 143 / 0.28);
}
/* `display: flex` ci-dessus surcharge le défaut UA `[hidden] { display: none }`.
   Sans cette règle, JS qui set bar.hidden = true n'a aucun effet visuel. */
.cook-mini-bar[hidden] {
  display: none;
}
.cook-mini-bar:active {
  transform: translateX(-50%) scale(0.98);
}
@keyframes cookMiniIn {
  from {
    transform: translateX(-50%) translateY(24px);
    opacity: 0;
  }
  to {
    transform: translateX(-50%) translateY(0);
    opacity: 1;
  }
}
.cook-mini-icon {
  width: 32px;
  height: 32px;
  border-radius: 8px;
  background: var(--cream-fixed);
  color: var(--accent-deep);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-display);
  font-style: italic;
  font-weight: 700;
  font-size: 20px;
  line-height: 1;
  flex-shrink: 0;
}
.cook-mini-text {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 1px;
}
.cook-mini-label {
  font-size: 14px;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.cook-mini-progress {
  font-size: 11px;
  font-feature-settings: "tnum" 1;
  opacity: 0.82;
  letter-spacing: 0.01em;
}
.cook-mini-resume {
  flex-shrink: 0;
  background: var(--cream-fixed);
  color: var(--accent-deep);
  border: none;
  border-radius: 999px;
  padding: 6px 14px;
  font-size: 13px;
  font-weight: 700;
  cursor: pointer;
  font-family: var(--font-body);
}

/* ── Pull-to-refresh ── É italique géant Vert Jean-Talon ──── */
/* Reprend la signature wow des covers recettes : É italique Young Serif
   géant en accent. Le geste de pull devient un moment éditorial. */
.pull-refresh {
  position: fixed;
  top: 0;
  left: 50%;
  transform: translateX(-50%) translateY(0);
  padding-top: env(safe-area-inset-top, 0);
  z-index: 90;
  pointer-events: none;
  font-family: var(--font-display);
  font-style: italic;
  font-weight: 700;
  font-size: clamp(56px, 14vw, 88px);
  line-height: 1;
  color: var(--accent);
  opacity: 0;
  letter-spacing: -0.02em;
}
.pull-refresh.is-ready {
  color: var(--accent-deep);
}
.pull-refresh.is-loading {
  animation: pullRefreshSpin 0.9s cubic-bezier(0.45, 0, 0.55, 1) infinite;
}
@keyframes pullRefreshSpin {
  from {
    transform: translateX(-50%) translateY(80px) rotate(0deg);
  }
  to {
    transform: translateX(-50%) translateY(80px) rotate(360deg);
  }
}

/* ── Recipe actions sheet (long-press) ─────────────────────── */
/* <dialog> natif pour focus trap + Escape gratis. Slide-up depuis le bas
   façon iOS Action Sheet, mais éditorial : pas de glassmorphism, pas
   de blur exagéré, surface paper-sheet directe. */
.recipe-actions-sheet {
  border: none;
  background: transparent;
  padding: 0;
  margin: 0;
  width: 100%;
  height: 100%;
  max-width: none;
  max-height: none;
  position: fixed;
  inset: 0;
  z-index: 500;
}
.recipe-actions-sheet::backdrop {
  background: oklch(0 0 0 / 0.42);
  opacity: 0;
  transition: opacity 0.25s ease;
}
.recipe-actions-sheet.is-visible::backdrop {
  opacity: 1;
}
.recipe-actions-sheet-panel {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  background: var(--paper-sheet);
  border-radius: 18px 18px 0 0;
  padding: 8px 0 calc(env(safe-area-inset-bottom, 0) + 12px);
  transform: translateY(100%);
  transition: transform 0.35s cubic-bezier(0.22, 0.61, 0.36, 1);
  max-height: 80vh;
  overflow-y: auto;
}
.recipe-actions-sheet.is-visible .recipe-actions-sheet-panel {
  transform: translateY(0);
}
.recipe-actions-handle {
  width: 44px;
  height: 5px;
  background: oklch(0 0 0 / 0.15);
  border-radius: 3px;
  margin: 6px auto 14px;
}
.recipe-actions-name {
  font-family: var(--font-display);
  font-size: 18px;
  font-weight: 600;
  color: var(--ink);
  text-align: center;
  margin: 0 0 18px;
  padding: 0 24px;
  letter-spacing: -0.01em;
}
.recipe-actions-list {
  display: flex;
  flex-direction: column;
}
.recipe-actions-item {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 14px 24px;
  background: transparent;
  color: var(--ink);
  font-size: 16px;
  font-weight: 500;
  font-family: var(--font-body);
  border: none;
  border-top: 1px solid var(--border);
  width: 100%;
  text-align: left;
  text-decoration: none;
  cursor: pointer;
  transition: background 0.12s ease;
  min-height: 56px;
}
.recipe-actions-item:active {
  background: oklch(0 0 0 / 0.04);
}
.recipe-actions-item--danger {
  color: var(--danger);
}
.recipe-actions-icon {
  width: 28px;
  height: 28px;
  flex-shrink: 0;
  border-radius: 7px;
  background: var(--accent-tint);
  color: var(--accent-deep);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 15px;
  font-weight: 600;
}
.recipe-actions-item--danger .recipe-actions-icon {
  background: oklch(0.92 0.04 25);
  color: var(--danger);
}

/* ── Sticky title morph ────────────────────────────────────── */
/* Quand le masthead (Young Serif géant + eyebrow) sort du viewport au
   scroll, le titre apparaît inline dans la topbar. Pattern iOS Mail :
   Large Title → Small Title. Géré via IntersectionObserver. */
.tb-inline-title {
  font-family: var(--font-display);
  font-size: 16px;
  font-weight: 600;
  color: var(--ink);
  letter-spacing: -0.01em;
  opacity: 0;
  transform: translateY(8px);
  transition:
    opacity 0.25s ease,
    transform 0.25s cubic-bezier(0.22, 0.61, 0.36, 1);
  pointer-events: none;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
  min-width: 0;
  flex: 1;
  margin: 0 12px;
}
.topbar.is-title-inline .tb-inline-title {
  opacity: 1;
  transform: translateY(0);
}
.topbar.is-title-inline .ptitle {
  display: none;
}

/* ── Dark mode ─────────────────────────────────────────────── */
[data-theme="dark"] .le-toast {
  background: var(--paper-sheet);
  color: var(--ink);
}
[data-theme="dark"] .cook-mini-bar {
  box-shadow: 0 6px 22px oklch(0 0 0 / 0.35);
}
[data-theme="dark"] .recipe-actions-sheet-panel {
  background: var(--paper-sheet);
}
[data-theme="dark"] .recipe-actions-handle {
  background: oklch(1 0 0 / 0.15);
}
[data-theme="dark"] .recipe-actions-icon {
  background: oklch(1 0 0 / 0.06);
  color: var(--accent);
}
[data-theme="dark"] .recipe-actions-item--danger .recipe-actions-icon {
  background: oklch(0.32 0.08 25);
  color: oklch(0.78 0.12 25);
}

/* ── Reduced motion ────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  .cook-mini-bar {
    animation: none;
  }
  .pull-refresh.is-loading {
    animation: none;
  }
  .pull-refresh,
  .recipe-actions-sheet-panel,
  .recipe-actions-sheet::backdrop,
  .le-toast {
    transition: none !important;
  }
}

/* ════════════════════════════════════════════════════
   DEFENSIVE : empêche tout SVG orphan d'overflow le viewport
   Symptôme observé : un SVG sans width/height défini en CSS prenait
   100% de la viewport en desktop (signalé screenshot user 2026-04-27).
   Cap à max-width: 100% sur tous les SVG du content principal.
   Les SVG explicitement dimensionnés (icônes, etc.) ne sont pas
   affectés grâce à `max-width` (pas `width`).
   ════════════════════════════════════════════════════ */
/* Cible SEULEMENT les SVG sans attribut width — les SVG dimensionnés
   (icônes inline avec width="20") ne sont pas touchés.
   Cap à max-height: 60vh : un SVG sans dim ne dépassera pas 60% du viewport. */
.main svg:not([width]),
.content svg:not([width]) {
  max-width: 100%;
  max-height: 60vh;
}

/* ════════════════════════════════════════════════════
   <details>/<summary> NATIF — collapsible nav groups
   Solution définitive après 8+ commits qui essayaient de fix le click
   sur <button>. <details> est natif et fiable sur tous browsers.
   ════════════════════════════════════════════════════ */
details.nav-group-details {
  /* Container neutre — le summary et le contenu héritent de leurs
     styles existants (.nav-group-toggle, .nav-group). */
}
/* Cache le marker triangle natif (▶/▼) — on a notre propre chevron */
details.nav-group-details > summary {
  list-style: none;
  cursor: pointer;
  -webkit-user-select: none;
  user-select: none;
}
details.nav-group-details > summary::-webkit-details-marker {
  display: none;
}
details.nav-group-details > summary::marker {
  display: none;
}
/* Quand <details> est open, le sub-menu est visible nativement.
   Sync rotation chevron via [open] sélecteur (plus simple que JS). */
details.nav-group-details[open] > summary .nav-group-chevron {
  transform: rotate(90deg);
  color: var(--accent-deep);
}

/* ════════════════════════════════════════════════════
   DEFENSIVE : éléments mobile-only hidden par défaut
   Symptôme : sur desktop, les .mtab-icon SVG (mobile tabbar) sans
   width attribut s'étiraient en GÉANT car mobile-fixes.css n'est pas
   chargé sur desktop (gated `media="(max-width: 900px)"`), donc la
   règle `.mobile-tabbar { display: none }` au top de mobile-fixes.css
   ne s'appliquait jamais en desktop → tabbar visible avec icônes
   non-contraintes.
   Fix : déclarer le `display: none` dans app.css (toujours chargé).
   mobile-fixes.css peut override avec `display: grid` dans son
   @media (max-width: 768px).
   ════════════════════════════════════════════════════ */
.mobile-tabbar {
  display: none;
}
.compte-pwa-hub {
  display: none;
}
/* sidebar-close-btn (X) : visible seulement quand sidebar est en mode
   drawer mobile. mobile-fixes.css le positionne absolute top-right
   à l'intérieur de @media (max-width: 768px). Sur desktop la règle
   n'existe pas → bouton flotte au top-left du sidebar avec le logo. */
.sidebar-close-btn {
  display: none;
}

/* ════════════════════════════════════════════════════
   Pass 4 critique additions :
   - .onb-collapse : <details> wrapper qui replie les astuces
   - .dash-soft-note : note inline grand-maman (anciennement
     badge alert hors-menu)
   - .dash-pred-label : suggestion inline (vs faux-bouton)
   - .info-pop : disclosure « C'est quoi ? » sur KPI
   ════════════════════════════════════════════════════ */

.onb-collapse {
  margin: 24px 0 8px;
  /* Avant : 1px solid border lisait comme un encadrement de plus dans une
     page qui a déjà .dash-section-head border-bottom + button outlines.
     Maintenant : juste le background tint pour différencier — pas de
     framing additionnel. */
  border-radius: 14px;
  background: color-mix(in oklch, var(--accent-tint) 50%, transparent);
}
.onb-collapse[open] {
  background: var(--accent-tint);
}
.onb-collapse-summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 14px 18px;
  cursor: pointer;
  list-style: none;
  font-family: var(--font-body);
  user-select: none;
}
.onb-collapse-summary::-webkit-details-marker {
  display: none;
}
.onb-collapse-summary-text {
  font-size: 14px;
  font-weight: 500;
  color: var(--ink-soft);
}
.onb-collapse-count {
  color: var(--brand-dark, var(--brand));
  font-weight: 600;
}
.onb-collapse-summary-cta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: var(--accent-tint, oklch(0.59 0.16 143 / 0.1));
  color: var(--brand-dark, var(--brand));
  transition: background 0.2s ease, transform 0.25s cubic-bezier(0.22, 1, 0.36, 1);
}
.onb-collapse-chevron {
  transition: transform 0.28s cubic-bezier(0.22, 1, 0.36, 1);
}
/* État ouvert : chevron pivote 180° (pointe vers le haut = "replier"). */
.onb-collapse[open] .onb-collapse-chevron {
  transform: rotate(180deg);
}
@media (hover: hover) and (pointer: fine) {
  .onb-collapse-summary:hover .onb-collapse-summary-cta {
    background: var(--accent-tint, oklch(0.59 0.16 143 / 0.18));
  }
}
@media (prefers-reduced-motion: reduce) {
  .onb-collapse-chevron {
    transition: none;
  }
}
.onb-collapse-summary:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
  border-radius: 14px;
}
.onb-collapse[open] .onb-cards {
  margin: 0;
  padding: 0 14px 16px;
  border: none;
}
.onb-collapse[open] .onb-card {
  background: var(--paper-soft);
  border-color: color-mix(in oklch, var(--brand) 18%, transparent);
}

/* Note douce grand-maman (remplace badge alert hors-menu sur hero).
   Refonte impeccable BAN 1 : full border 1px au lieu de side-stripe
   border-left 3px. Background tint plus prononcé pour conserver la
   hiérarchie visuelle perdue avec la suppression du stripe. */
.dash-soft-note {
  font-family: var(--font-body);
  font-size: 14px;
  line-height: 1.5;
  color: var(--ink-soft);
  background: var(--paper-soft);
  border: 1px solid var(--border);
  padding: 12px 14px;
  border-radius: 8px;
  margin: 0 0 16px;
}
.dash-soft-note strong {
  color: var(--ink);
  font-weight: 600;
}
/* Variante alert (remplace l'override inline border-left-color
   sur les flash error). Utilisée via role="alert" + classe sœur. */
.dash-soft-note[role="alert"] {
  background: color-mix(in oklch, var(--danger, var(--canneberge, var(--ink-muted))) 6%, var(--paper-soft));
  border-color: color-mix(in oklch, var(--danger, var(--canneberge, var(--border))) 30%, var(--border));
}

/* .dash-pred-label* supprime 2026-05-09 (audit R18) : aucune
   utilisation dans les Blade. C'etait le replacement annonce de
   .dash-pred-action mais finalement le dashboard:425-430 utilise
   juste .dash-pred-name + .dash-pred-msg. Cleanup. */

/* Disclosure « C'est quoi ? » contextuelle sur KPIs.
   Bouton i discret juste après le label, ouvre/ferme un popover
   inline avec la définition du concept (Budget Fantôme, etc.). */
.info-pop {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  border: 1px solid color-mix(in oklch, var(--ink-muted) 55%, transparent);
  border-radius: 50%;
  background: transparent;
  color: var(--ink-muted);
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 600;
  font-style: italic;
  cursor: pointer;
  padding: 0;
  line-height: 1;
  position: relative;
  transition:
    background 0.15s,
    color 0.15s,
    border-color 0.15s;
}
/* Hit area étendue à 44×44px sans toucher au layout visuel — pattern
   Apple HIG / MDN. Le ::after invisible capte les taps Claudette
   (cible 65+) sans que l'icône visuelle change de taille. */
.info-pop::after {
  content: "";
  position: absolute;
  inset: -13px;
  min-width: 44px;
  min-height: 44px;
}
@media (hover: hover) and (pointer: fine) {
  .info-pop:hover,
  .info-pop[aria-expanded="true"] {
    background: var(--ink);
    color: var(--paper);
    border-color: var(--ink);
  }
}
.info-pop:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
}
/* Bulle info-pop : visible UNIQUEMENT quand le bouton est en
   aria-expanded="true" (le JS retire l'attribut [hidden] du content
   à ce moment). Le sélecteur :not([hidden]) évite l'override CSS
   du comportement natif HTML hidden — bug user-visible avant fix :
   display:block écrasait [hidden]{display:none} de la UA stylesheet
   (même spécificité, source-order tranchait). */
.info-pop-content {
  display: none;
}
.info-pop-content:not([hidden]) {
  display: block;
  margin-top: 8px;
  font-family: var(--font-body);
  font-size: 13px;
  line-height: 1.5;
  color: var(--ink-soft);
  background: var(--paper-soft);
  padding: 10px 12px;
  border-radius: 8px;
  max-width: 320px;
}

/* ════════════════════════════════════════════════════
   USAGE BANNER — Phase 3 pricing 2026-05.
   Apparaît dans le dashboard quand l'user dépasse 70% sur une feature
   IA. Discrète et collapsable (<details>). Voix grand-maman.
   ════════════════════════════════════════════════════ */
.usage-banner {
  margin: 18px 0 8px;
  border: 1px dashed color-mix(in oklch, var(--ink-muted) 35%, transparent);
  border-radius: 12px;
  background: color-mix(in oklch, var(--paper-soft) 80%, transparent);
}
.usage-banner[open] {
  background: var(--paper-soft);
  border-style: solid;
}
.usage-banner-summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 16px;
  cursor: pointer;
  list-style: none;
  user-select: none;
}
.usage-banner-summary::-webkit-details-marker {
  display: none;
}
.usage-banner-summary:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: -2px;
  border-radius: 12px;
}
.usage-banner-text {
  font-size: 13px;
  color: var(--ink-soft);
  font-weight: 500;
}
.usage-banner-cta {
  font-size: 12px;
  font-weight: 600;
  color: var(--brand-dark, var(--brand));
  letter-spacing: 0.04em;
}
.usage-banner[open] .usage-banner-cta {
  font-size: 0;
}
.usage-banner[open] .usage-banner-cta::before {
  content: "Replier";
  font-size: 12px;
}
.usage-banner-list {
  list-style: none;
  padding: 0 16px 14px;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.usage-banner-item {
  display: grid;
  grid-template-columns: minmax(140px, 1fr) 2fr auto;
  align-items: center;
  gap: 12px;
  font-size: 13px;
}
.usage-banner-item.is-full {
  color: var(--canneberge, var(--ink-muted));
}
.usage-banner-label {
  color: var(--ink);
  font-weight: 500;
}
.usage-banner-bar {
  height: 4px;
  background: var(--border);
  border-radius: 4px;
  overflow: hidden;
}
.usage-banner-bar-fill {
  display: block;
  height: 100%;
  background: var(--brand);
  border-radius: 4px;
  /* GPU : transform-origin left + scaleX au lieu de width pour éviter
     reflow. Le HTML doit set --fill (0..1) inline ou en CSS var. */
  transform-origin: left center;
  transform: scaleX(var(--fill, 0));
  transition: transform 0.3s cubic-bezier(0.22, 1, 0.36, 1);
  will-change: transform;
  width: 100%;
}
.usage-banner-item.is-full .usage-banner-bar-fill {
  background: var(--canneberge, var(--ink-muted));
}
.usage-banner-count {
  font-variant-numeric: tabular-nums;
  font-size: 12px;
  font-weight: 600;
  color: var(--ink-muted);
}
.usage-banner-upsell {
  padding: 8px 16px 14px;
  margin: 0;
  font-size: 12px;
  font-style: italic;
  color: var(--ink-muted);
  border-top: 1px dashed var(--border2);
}
.usage-banner-upsell a {
  color: var(--brand-dark, var(--brand));
  font-weight: 600;
}

/* ════════════════════════════════════════════════════
   ADMIN USERS LIST — cards stackées (responsive natif).
   Pas un tableau qui déborde sur mobile, juste des cards
   éditoriales empilées qui marchent partout.
   ════════════════════════════════════════════════════ */
.admin-users-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.admin-user-card {
  background: var(--paper-sheet, var(--paper-soft));
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 18px;
  transition:
    border-color 0.15s,
    box-shadow 0.15s;
}
.admin-user-card.is-suspended {
  opacity: 0.65;
  border-color: color-mix(in oklch, var(--canneberge, var(--ink-muted)) 25%, var(--border));
}
.admin-user-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 14px;
  margin-bottom: 14px;
  flex-wrap: wrap;
}
.admin-user-identity {
  flex: 1;
  min-width: 0;
}
.admin-user-name {
  font-family: var(--font-display);
  font-size: 17px;
  font-weight: 400;
  color: var(--ink);
  margin-bottom: 2px;
  letter-spacing: -0.005em;
}
.admin-user-email {
  font-size: 13px;
  color: var(--ink-muted);
  word-break: break-word;
}
.admin-user-meta {
  font-size: 11px;
  color: var(--ink-muted);
  margin-top: 3px;
}
.admin-user-plan {
  flex-shrink: 0;
  text-align: right;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 4px;
}
.admin-user-tag {
  display: inline-block;
  font-size: 11px;
  font-weight: 600;
  padding: 4px 10px;
  border-radius: 980px;
  letter-spacing: 0.02em;
  white-space: nowrap;
}
.admin-user-tag.is-paid {
  background: var(--accent-tint);
  color: var(--brand-dark, var(--brand));
}
.admin-user-tag.is-trial {
  background: var(--paille-tint, var(--paper-soft));
  color: var(--ink-soft);
}
.admin-user-tag.is-comped {
  background: color-mix(in oklch, var(--brand) 14%, transparent);
  color: var(--brand-dark, var(--brand));
}
.admin-user-tag.is-danger {
  background: color-mix(in oklch, var(--canneberge, var(--ink-muted)) 18%, transparent);
  color: var(--canneberge, var(--ink-muted));
}
.admin-user-tag.is-expired {
  background: var(--paper-soft);
  color: var(--ink-muted);
}
.admin-user-stats {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 12px;
  padding: 14px 0;
  border-top: 1px solid var(--border2);
  border-bottom: 1px solid var(--border2);
  margin-bottom: 14px;
}
.admin-user-stat-label {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--ink-muted);
  margin-bottom: 4px;
  font-weight: 500;
}
.admin-user-stat-value {
  font-family: var(--font-display);
  font-size: 16px;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
  font-weight: 400;
}
.admin-user-stat-value.is-muted {
  color: var(--ink-muted);
  font-size: 14px;
}
.admin-user-actions {
  text-align: right;
}
.admin-user-action {
  font-size: 13px;
  padding: 8px 14px;
}
.admin-user-empty {
  padding: 32px;
  text-align: center;
  color: var(--ink-muted);
  background: var(--paper-soft);
  border-radius: 14px;
}

/* Mobile : la zone plan tag passe sous l'identité plutôt que à côté
   pour éviter que l'email soit écrasé sur petit écran. */
@media (max-width: 480px) {
  .admin-user-head {
    flex-direction: column;
    gap: 10px;
  }
  .admin-user-plan {
    text-align: left;
    align-items: flex-start;
  }
  .admin-user-stats {
    grid-template-columns: 1fr 1fr;
  }
  .admin-user-stats .admin-user-stat:last-child {
    grid-column: 1 / -1;
  }
}

/* ════════════════════════════════════════════════════
   ÉVÉNEMENT — Forfait Réception « Recevoir un groupe »
   Phase 5 pricing 2026-05. Pay-per-event 9,99 $.
   ════════════════════════════════════════════════════ */

/* Liste événements (page index) */
.evenement-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.evenement-card {
  /* Avant : border 1px crée un cadre-dans-cadre avec le .dash-section-head
     border-bottom + le bouton outline → 3 lignes en compétition. Maintenant :
     background paper-sheet sur page paper crée la différentiation suffisante.
     L'artefact en L visible sur iOS Safari (rendering 14px radius + 1px border
     au sub-pixel) disparaît avec la suppression du border. */
  background: var(--paper-sheet, var(--paper-soft));
  border-radius: 14px;
  padding: 18px;
}
.evenement-card.is-expired {
  opacity: 0.6;
}
.evenement-card-head {
  display: flex;
  justify-content: space-between;
  gap: 14px;
  align-items: flex-start;
  margin-bottom: 14px;
  flex-wrap: wrap;
}
.evenement-card-eyebrow {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--ink-muted);
  margin-bottom: 4px;
  font-weight: 500;
}
.evenement-card-title {
  font-family: var(--font-display);
  font-size: 18px;
  font-weight: 400;
  margin: 0 0 4px;
  color: var(--ink);
  letter-spacing: -0.005em;
}
.evenement-card-meta {
  font-size: 13px;
  color: var(--ink-soft);
}
.evenement-tag {
  display: inline-block;
  font-size: 11px;
  font-weight: 600;
  padding: 4px 10px;
  border-radius: 980px;
  white-space: nowrap;
}
.evenement-tag.is-active {
  background: var(--accent-tint);
  color: var(--brand-dark, var(--brand));
}
.evenement-tag.is-warn {
  background: var(--paille-tint, var(--paper-soft));
  color: var(--ink-soft);
}
.evenement-tag.is-pending {
  background: var(--paper-soft);
  color: var(--ink-muted);
}
.evenement-tag.is-expired {
  background: var(--paper-soft);
  color: var(--ink-muted);
}
.evenement-card-actions {
  text-align: right;
}

/* ════════════════════════════════════════════════════════════════════
   CARNET DE RÉCEPTION — Page show.blade.php quand aMenuValide()
   Refonte 2026-05-06 : hybride Cookbook éditorial + Plan de bataille
   utilitaire + signature Carte premium. Registre Ricardo / NYT Cooking
   print, voix grand-maman québécoise. Print-ready.
══════════════════════════════════════════════════════════════════════ */

.ev-cookbook {
  max-width: 720px;
  margin: 0 auto;
  padding: 0 8px;
  position: relative;
}
@media (min-width: 1100px) {
  .ev-cookbook {
    max-width: 760px;
  }
}

/* ── Hero couverture magazine ───────────────────────────────── */
.ev-cover {
  text-align: center;
  padding: clamp(40px, 7vw, 72px) 16px clamp(28px, 5vw, 48px);
  margin-bottom: 0;
}
/* .ev-cover-rule, .ev-cover-kicker, .ev-cover-kicker sup retirés du DOM
   et du CSS 2026-05-08 (audit 3 agents : dead CSS + ornements
   décoratifs sans utilité user). */
.ev-cover-title {
  font-family: var(--font-display);
  font-weight: 400;
  /* Réduit de clamp(36-64px) → clamp(32-48px) : 64px sur mobile 375px
     wrappait sur 3 lignes pour les noms d'événement longs (« Anniversaire
     Mathieu 6 ans »). 48px tient en 2 lignes propres. */
  font-size: clamp(32px, 5.5vw, 48px);
  line-height: 1.04;
  letter-spacing: -0.018em;
  color: var(--ink);
  margin: 0 0 18px;
  text-wrap: balance;
}
.ev-cover-standfirst {
  font-family: var(--font-body);
  font-size: clamp(15px, 1.6vw, 18px);
  line-height: 1.55;
  color: var(--ink-soft);
  margin: 0 0 20px;
  max-width: 56ch;
  margin-left: auto;
  margin-right: auto;
}
.ev-cover-standfirst em {
  font-style: italic;
  color: var(--brand-dark, var(--brand));
}
.ev-cover-standfirst strong {
  color: var(--ink);
  font-weight: 600;
}
.ev-cover-byline {
  font-family: var(--font-body);
  font-size: 14px;
  color: var(--ink-muted);
  margin: 0;
  font-style: italic;
}
/* .ev-cover-stat / .ev-cover-stat-num retirés du DOM 2026-05-08. */

/* ── Bandeau statut subtil sous le hero ────────────────────── */
.ev-status-bar--cookbook {
  background: transparent;
  border-top: 1px solid var(--border2);
  border-bottom: 1px solid var(--border2);
  border-radius: 0;
  margin: 0 0 clamp(32px, 5vw, 56px);
  padding: 14px 18px;
  font-size: 12.5px;
}

/* ── Sommaire sticky desktop / barre fine bottom mobile ────── */
.ev-toc {
  display: none;
}
@media (min-width: 1100px) {
  .ev-toc {
    display: block;
    position: fixed;
    top: 50%;
    right: max(24px, calc((100vw - 760px) / 2 - 200px));
    transform: translateY(-50%);
    width: 180px;
    z-index: 5;
    pointer-events: auto;
  }
  .ev-toc-label {
    font-family: var(--font-body);
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    color: var(--ink-muted);
    margin: 0 0 14px;
    padding-bottom: 10px;
    border-bottom: 1px solid var(--border2);
  }
  .ev-toc-list {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 12px;
  }
  .ev-toc-link {
    display: flex;
    align-items: baseline;
    gap: 12px;
    font-family: var(--font-body);
    font-size: 13.5px;
    color: var(--ink-muted);
    text-decoration: none;
    transition: color 0.2s;
    line-height: 1.35;
  }
  @media (hover: hover) and (pointer: fine) {
    .ev-toc-link:hover {
      color: var(--ink-soft);
    }
  }
  .ev-toc-link.is-current {
    color: var(--ink);
    font-weight: 500;
  }
  .ev-toc-link.is-current .ev-toc-num {
    color: var(--brand-dark, var(--brand));
  }
  .ev-toc-num {
    font-family: var(--font-display);
    font-size: 14px;
    color: var(--ink-fade);
    flex-shrink: 0;
    min-width: 18px;
  }
}

/* ── Chapitre (kicker + titre + intro drop cap) ────────────── */
.ev-chapter {
  margin: clamp(40px, 6vw, 64px) 0;
  padding: 0 8px;
  scroll-margin-top: 80px;
}

/* ── Onglets carnet (4 chapitres) ─────────────────────────────
   Refonte 2026-05-08 : la page entière en scroll continu (~15-20
   viewports) était lourde. 4 onglets natifs sticky cohérents avec
   /garde-manger et /recettes. Tous les chapitres restent dans le
   DOM (print mode override), CSS hide/show via body.ev-tab-{X}. */
.ev-tabs {
  position: sticky;
  top: 0;
  z-index: 20;
  display: flex;
  gap: 4px;
  padding: 12px 4px;
  margin: 24px 0 0;
  background: var(--paper);
  border-bottom: 1px solid var(--border2);
  overflow-x: auto;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.ev-tabs::-webkit-scrollbar {
  display: none;
}

.ev-tab {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 10px 18px;
  font-family: var(--font-body);
  font-size: 15px;
  font-weight: 500;
  color: var(--ink-soft);
  text-decoration: none;
  border-radius: 999px;
  transition:
    color 0.15s,
    background 0.15s;
  white-space: nowrap;
}
@media (hover: hover) and (pointer: fine) {
  .ev-tab:hover {
    color: var(--ink);
    background: var(--paper-soft);
  }
}
.ev-tab.is-active {
  color: var(--brand-dark);
  background: var(--accent-tint);
  font-weight: 600;
}
.ev-tab:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
}
/* Disabled state : tab visible mais inactif (race condition Sonnet). */
.ev-tab.is-disabled {
  color: var(--ink-muted);
  opacity: 0.55;
  cursor: not-allowed;
  user-select: none;
}
@media (hover: hover) and (pointer: fine) {
  .ev-tab.is-disabled:hover {
    background: transparent;
    color: var(--ink-muted);
  }
}

/* Masquage chapitres non-actifs selon body.ev-tab-{X}. Print mode
   override avec !important plus bas pour permettre l'impression de
   tout (boutons « Imprimer le carnet complet » du colophon). */
body.ev-tab-menu .ev-chapter:not(#ev-ch-menu),
body.ev-tab-marche .ev-chapter:not(#ev-ch-marche),
body.ev-tab-cuisine .ev-chapter:not(#ev-ch-cuisine),
body.ev-tab-materiel .ev-chapter:not(#ev-ch-tour) {
  display: none;
}

/* Kicker éditorial inline (« Chapitre I » au-dessus du titre) — refonte
   2026-05-08 (audit 3 agents). Avant : numéral romain 32-44px aussi gros
   que le titre H2 = double signal éditorial qui surchargeait la page.
   Après : 12-13px uppercase letter-spaced, kicker discret qui situe
   sans crier. Display block au sein du H2 pour rester sémantique. */
.ev-chapter-kicker {
  display: block;
  font-family: var(--font-body);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-muted);
  margin: 0 0 10px;
  font-feature-settings: "lnum";
}
/* .ev-chapter-num retiré du DOM 2026-05-08 — sélecteur conservé en
   no-op au cas où une vue legacy l'utilise encore. */
.ev-chapter-num {
  display: none;
}
.ev-chapter-title {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(28px, 4vw, 38px);
  line-height: 1.05;
  letter-spacing: -0.018em;
  color: var(--ink);
  margin: 0 0 20px;
  text-wrap: balance;
}
.ev-chapter-intro {
  font-family: var(--font-body);
  font-size: clamp(15.5px, 1.5vw, 17px);
  line-height: 1.7;
  color: var(--ink);
  margin: 0 0 32px;
  max-width: 56ch;
}
/* Drop cap utilisé sur la 1re lettre des voix polyphoniques (.ev-voix-mot).
   On ne suit plus de small-caps après — c'était un tell éditorial Substack
   trop attendu. Garder juste le drop cap (signature Young Serif) en
   accent vert pour ancrer la voix sans surcharger le rythme typographique. */
.ev-dropcap {
  float: left;
  font-family: var(--font-display);
  font-size: 2.4em;
  line-height: 0.85;
  margin: 0.08em 0.1em 0 0;
  color: var(--brand-dark, var(--brand));
  font-weight: 400;
}
@media (max-width: 640px) {
  .ev-dropcap {
    font-size: 2em;
  }
}
/* Mode Grand-Maman ou prefers-contrast: more — désactive le drop cap
   parce qu'il écrase le standfirst pour Claudette presbytie. La voix
   se lit normalement, on perd juste l'ornement décoratif. */
@media (prefers-contrast: more) {
  .ev-dropcap {
    float: none;
    font-size: 1em;
    line-height: inherit;
    margin: 0;
    color: inherit;
  }
}
body.mode-grand-maman .ev-dropcap {
  float: none;
  font-size: 1em;
  line-height: inherit;
  margin: 0;
  color: inherit;
}

/* .ev-fleuron retiré du DOM 2026-05-08 (les chapitres se séparent par leur
   marge propre + kicker — pas besoin d'ornement entre). */

/* ── Menu : catégorie + plats sans card (registre cookbook) ── */
.ev-course {
  margin-bottom: clamp(28px, 4vw, 40px);
}
.ev-course-eyebrow {
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-muted);
  margin: 0 0 18px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--border2);
}
.ev-course-list {
  display: flex;
  flex-direction: column;
}
.ev-dish {
  padding: 18px 0;
  border-bottom: 1px solid var(--border2);
}
.ev-dish:last-child {
  border-bottom: none;
}
.ev-dish-name {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 22px;
  line-height: 1.2;
  color: var(--ink);
  letter-spacing: -0.008em;
  margin: 0 0 6px;
}
.ev-dish-line {
  font-family: var(--font-body);
  font-size: 14.5px;
  line-height: 1.55;
  color: var(--ink-soft);
  font-style: italic;
  margin: 0 0 8px;
  max-width: 60ch;
}
.ev-dish-meta {
  font-family: var(--font-body);
  font-size: 12.5px;
  color: var(--ink-muted);
  margin: 0;
  display: flex;
  gap: 14px;
  align-items: baseline;
  font-feature-settings:
    "tnum" 1,
    "lnum" 1;
}
.ev-dish-meta span:not(.ev-dish-cost) {
  font-style: italic;
}
.ev-dish-cost {
  font-variant-numeric: tabular-nums;
  color: var(--ink-soft);
  font-weight: 500;
  margin-left: auto;
}

/* ── Marché : enseigne + items numérotés + checkable ───────── */
.ev-stall {
  margin-bottom: clamp(28px, 4vw, 40px);
}
.ev-stall-head {
  margin-bottom: 16px;
}
/* Header enseigne sobre 2026-05-08 : avant 24px Young Serif italique
   vert × 4 enseignes = surcharge visuelle. Maintenant 17px regular
   ink — la liste de courses passe avant la signature typographique. */
.ev-stall-name {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 17px;
  color: var(--ink);
  letter-spacing: -0.005em;
  margin: 0 0 2px;
  text-transform: none;
}
/* .ev-stall-name em retiré — l'enseigne ne porte plus d'italique vert
   (le DOM n'utilise plus <em>{enseigne}</em>). */
.ev-stall-meta {
  font-family: var(--font-body);
  font-size: 13px;
  color: var(--ink-muted);
  margin: 0;
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}
.ev-stall-total {
  font-variant-numeric: tabular-nums;
  color: var(--ink-soft);
  font-weight: 600;
}
.ev-stall-list {
  list-style: none;
  padding: 0;
  margin: 0;
}
.ev-stall-item {
  border-bottom: 1px dotted var(--border2);
}
.ev-stall-item:last-child {
  border-bottom: none;
}
.ev-stall-check {
  display: grid;
  /* Grid simplifié 2026-05-08 : passé de [28px checkbox · 28px num · 1fr nom · auto prix]
     à [28px checkbox · 1fr nom · auto prix]. La numérotation 01/02/03 décorative
     a été retirée (audit 3 agents — Casey ADHD lit l'item, pas le numéro). */
  grid-template-columns: 28px 1fr auto;
  gap: 12px;
  align-items: baseline;
  padding: 14px 4px;
  min-height: 44px;
  cursor: pointer;
  transition: opacity 0.2s;
}
.ev-stall-checkbox {
  appearance: none;
  -webkit-appearance: none;
  width: 22px;
  height: 22px;
  border: 1.5px solid var(--border);
  border-radius: 4px;
  cursor: pointer;
  position: relative;
  background: var(--paper);
  transition:
    background 0.15s,
    border-color 0.15s;
  flex-shrink: 0;
  align-self: center;
}
.ev-stall-checkbox:checked {
  background: var(--brand);
  border-color: var(--brand);
}
.ev-stall-checkbox:checked::after {
  content: "";
  position: absolute;
  left: 6px;
  top: 2px;
  width: 6px;
  height: 12px;
  border-right: 2px solid var(--cream-fixed, var(--paper));
  border-bottom: 2px solid var(--cream-fixed, var(--paper));
  transform: rotate(45deg);
}
.ev-stall-checkbox:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
}
/* .ev-stall-num retiré du DOM 2026-05-08 (audit 3 agents). */
/* Liste produits sentence case 2026-05-08 (feedback user « ça crie ») :
   avant les noms arrivaient en CAPS scrapés des circulaires et étaient
   affichés bruts → SHOUTING. Blade convertit maintenant en sentence
   case. CSS reste en regular (pas de text-transform uppercase).
   Hiérarchie : nom dominant + qty/poids muted + badge solde compact. */
.ev-stall-good {
  font-family: var(--font-body);
  font-size: 15px;
  color: var(--ink);
  line-height: 1.45;
  text-transform: none;
}
.ev-stall-name-item {
  font-weight: 500;
  color: var(--ink);
}
.ev-stall-qty {
  color: var(--ink-muted);
  font-weight: 400;
  font-style: normal;
  font-size: 14px;
  margin-left: 2px;
}
/* Badge solde compact : avant « EN SOLDE, −50% » caps inline répété
   3-4× par enseigne. Maintenant chip vert discret « −50% ». */
.ev-stall-mark {
  display: inline-flex;
  align-items: center;
  margin-left: 8px;
  padding: 2px 7px;
  font-family: var(--font-body);
  font-size: 11.5px;
  font-weight: 600;
  font-style: normal;
  color: var(--brand-dark, var(--brand));
  background: var(--accent-tint);
  border-radius: 999px;
  letter-spacing: 0;
  vertical-align: 1px;
  font-variant-numeric: tabular-nums;
}
.ev-stall-price {
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
  font-weight: 500;
  color: var(--ink);
  font-size: 14px;
  align-self: center;
}
.ev-stall-check.is-done .ev-stall-good,
.ev-stall-check.is-done .ev-stall-price {
  text-decoration: line-through;
  text-decoration-thickness: 1px;
  opacity: 0.55;
}

/* ── Timeline : ordre des choses ───────────────────────────── */
.ev-timeline {
  list-style: none;
  padding: 0 0 0 0;
  margin: 0;
}
.ev-tl-step {
  border-bottom: 1px solid var(--border2);
}
.ev-tl-step:last-child {
  border-bottom: none;
}
.ev-tl-check {
  display: grid;
  grid-template-columns: 28px 1fr;
  gap: 16px;
  align-items: start;
  padding: 18px 4px;
  min-height: 44px;
  cursor: pointer;
}
.ev-tl-checkbox {
  appearance: none;
  -webkit-appearance: none;
  width: 22px;
  height: 22px;
  border: 1.5px solid var(--border);
  border-radius: 50%;
  cursor: pointer;
  position: relative;
  background: var(--paper);
  transition:
    background 0.15s,
    border-color 0.15s;
  margin-top: 2px;
}
.ev-tl-checkbox:checked {
  background: var(--brand);
  border-color: var(--brand);
}
.ev-tl-checkbox:checked::after {
  content: "";
  position: absolute;
  left: 5px;
  top: 2px;
  width: 6px;
  height: 11px;
  border-right: 2px solid var(--cream-fixed, var(--paper));
  border-bottom: 2px solid var(--cream-fixed, var(--paper));
  transform: rotate(45deg);
}
.ev-tl-checkbox:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
}
.ev-tl-body {
  min-width: 0;
}
.ev-tl-when {
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--brand-dark, var(--brand));
  margin: 0 0 6px;
}
.ev-tl-task {
  font-family: var(--font-display);
  font-weight: 400;
  /* Fluid 16-18px : sur 360-414px mobile la timeline est dense
     (6-12 étapes), 16px évite le « 1 étape = 6 lignes » screencap. */
  font-size: clamp(15px, 3.6vw, 18px);
  line-height: 1.45;
  color: var(--ink);
  letter-spacing: -0.005em;
  margin: 0;
  text-wrap: balance;
  /* Anti-régression Sonnet UPPERCASE : si la DB contient encore du
     contenu MAJUSCULE non-normalisé (ancien data), on bypass.
     Le Blade fait déjà ucfirst(mb_strtolower) mais ceinture+bretelles. */
  text-transform: none;
}
.ev-tl-dur {
  font-family: var(--font-body);
  font-size: 12.5px;
  color: var(--ink-muted);
  font-style: italic;
  margin: 6px 0 0;
}
.ev-tl-check.is-done .ev-tl-task,
.ev-tl-check.is-done .ev-tl-when,
.ev-tl-check.is-done .ev-tl-dur {
  text-decoration: line-through;
  text-decoration-thickness: 1px;
  opacity: 0.55;
}

/* ── Tour du propriétaire : matériel ─────────────────────── */
.ev-toolkit {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  grid-template-columns: 1fr;
  gap: 0;
}
@media (min-width: 600px) {
  .ev-toolkit {
    grid-template-columns: 1fr 1fr;
    column-gap: 32px;
  }
}
.ev-toolkit-item {
  border-bottom: 1px dotted var(--border2);
}
.ev-toolkit-check {
  display: grid;
  grid-template-columns: 28px 1fr auto;
  gap: 14px;
  align-items: baseline;
  padding: 14px 4px;
  min-height: 44px;
  cursor: pointer;
}
.ev-toolkit-checkbox {
  appearance: none;
  -webkit-appearance: none;
  width: 22px;
  height: 22px;
  border: 1.5px solid var(--border);
  border-radius: 4px;
  cursor: pointer;
  position: relative;
  background: var(--paper);
  align-self: center;
}
.ev-toolkit-checkbox:checked {
  background: var(--brand);
  border-color: var(--brand);
}
.ev-toolkit-checkbox:checked::after {
  content: "";
  position: absolute;
  left: 6px;
  top: 2px;
  width: 6px;
  height: 12px;
  border-right: 2px solid var(--cream-fixed, var(--paper));
  border-bottom: 2px solid var(--cream-fixed, var(--paper));
  transform: rotate(45deg);
}
.ev-toolkit-checkbox:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
}
.ev-toolkit-name {
  font-family: var(--font-body);
  font-size: 15px;
  color: var(--ink);
  line-height: 1.45;
}
.ev-toolkit-qty {
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
  font-size: 13.5px;
  color: var(--ink-soft);
  font-weight: 500;
}
.ev-toolkit-check.is-done .ev-toolkit-name,
.ev-toolkit-check.is-done .ev-toolkit-qty {
  text-decoration: line-through;
  text-decoration-thickness: 1px;
  opacity: 0.55;
}

/* ── Voix polyphonique « Le mot du marché »
   Pattern signature L'Économe : chaque chapitre du Carnet de
   réception ouvre par une voix d'artisan signée (Le chef /
   La maraîchère / Toi-même demain à 14 h / La grand-maman).
   Sonnet justifie ses choix sur les contraintes user (allergies,
   rabais semaine, nb convives). C'est l'élément unique qui
   distingue L'Économe des cookbook templates génériques.
   Le drop cap reste mais s'applique au PREMIER caractère du mot,
   plus de small-caps suite (un tell de trop). */
.ev-voix {
  margin: 0 0 32px;
  padding: 0;
  max-width: 56ch;
}
.ev-voix-mot {
  font-family: var(--font-body);
  font-size: clamp(16px, 1.6vw, 18.5px);
  line-height: 1.7;
  color: var(--ink);
  margin: 0 0 12px;
  padding: 0;
  border: none;
  text-wrap: pretty;
}
.ev-voix-mot::before,
.ev-voix-mot::after {
  content: none;
}
.ev-voix-signataire {
  font-family: var(--font-display);
  font-style: italic;
  font-size: clamp(14px, 1.2vw, 15.5px);
  color: var(--brand-dark, var(--brand));
  letter-spacing: 0.01em;
  margin: 0;
  padding-left: 4px;
}

/* Voix secondaires (chapitres II, III, IV) — refonte allègement 2026-05-08.
   Sans drop cap, plus discrète : c'est l'attribution d'auteur, pas le
   moment WOW. Le drop cap (CH I) signe la découverte ; les voix suivantes
   confirment la cohérence sans répéter le geste typographique. */
.ev-voix--secondaire .ev-voix-mot {
  font-size: clamp(15px, 1.4vw, 17px);
  font-style: italic;
  color: var(--ink-soft);
  line-height: 1.65;
  max-width: 50ch;
}

/* ── Colophon ────────────────────────────────────────────── */
.ev-colophon {
  text-align: center;
  margin-top: clamp(32px, 5vw, 56px);
  padding-top: clamp(32px, 5vw, 48px);
}
.ev-colophon-text {
  font-family: var(--font-body);
  font-size: 13.5px;
  font-style: italic;
  color: var(--ink-soft);
  line-height: 1.6;
  margin: 0 0 24px;
  max-width: 56ch;
  margin-left: auto;
  margin-right: auto;
}
.ev-colophon-text em {
  font-style: italic;
  color: var(--brand-dark, var(--brand));
}
.ev-colophon-actions {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
  justify-content: center;
  margin-bottom: 24px;
}

/* ── Print : A4 noir/blanc, masque la nav et les actions ─── */
@media print {
  body {
    background: white;
    color: black;
  }
  .ev-cookbook {
    max-width: 100%;
    padding: 0;
  }
  .ev-cover-title {
    font-size: 36px;
  }
  .ev-toc,
  .ev-status-bar,
  [data-no-print],
  .nav,
  .land-nav,
  .site-nav,
  .topbar,
  .sidebar,
  .vocal-overlay,
  footer,
  .footer-mobile-tabs {
    display: none !important;
  }
  .ev-chapter {
    page-break-inside: avoid;
  }
  .ev-dish {
    page-break-inside: avoid;
  }
  .ev-stall-checkbox,
  .ev-tl-checkbox,
  .ev-toolkit-checkbox {
    border: 1.5px solid #000 !important;
    background: white !important;
  }
  .ev-stall-checkbox:checked,
  .ev-tl-checkbox:checked,
  .ev-toolkit-checkbox:checked {
    background: white !important;
  }
  .ev-stall-checkbox:checked::after,
  .ev-tl-checkbox:checked::after,
  .ev-toolkit-checkbox:checked::after {
    border-color: var(--ink, #0c0c0a) !important;
  }
  /* En mode print : ignore le masquage par onglet (body.ev-tab-X).
     L'utilisateur veut tout imprimer (carnet complet) ou un sous-
     ensemble ciblé via .ev-print-list / .ev-print-timeline. La règle
     ev-tab-X est neutralisée d'abord, puis les modes ciblés cachent
     ce qu'il faut. */
  body[class*="ev-tab-"] .ev-chapter {
    display: block !important;
  }

  /* Modes d'impression ciblés (P1.7 audit Marie) — body classe
     dynamique appliquée par JS avant window.print(), retirée à
     l'événement afterprint. Cache les chapitres non-désirés.
     Refs .ev-fleuron retirées 2026-05-08 (élément supprimé du DOM). */
  body.ev-print-list .ev-cover ~ *:not(#ev-ch-marche):not(.ev-colophon),
  body.ev-print-list #ev-ch-menu,
  body.ev-print-list #ev-ch-cuisine,
  body.ev-print-list #ev-ch-tour {
    display: none !important;
  }
  body.ev-print-timeline .ev-cover ~ *:not(#ev-ch-cuisine):not(.ev-colophon),
  body.ev-print-timeline #ev-ch-menu,
  body.ev-print-timeline #ev-ch-marche,
  body.ev-print-timeline #ev-ch-tour {
    display: none !important;
  }
  /* Mode print-all = défaut (rien à cacher de plus) */
}

/* Disclosure des modes d'impression dans le colophon */
.ev-print-options {
  position: relative;
  display: inline-block;
}
.ev-print-summary {
  list-style: none;
  cursor: pointer;
  user-select: none;
}
.ev-print-summary::-webkit-details-marker {
  display: none;
}
.ev-print-options-body {
  position: absolute;
  bottom: calc(100% + 8px);
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 10px;
  background: var(--paper-sheet);
  border: 1px solid var(--border);
  border-radius: 10px;
  box-shadow: var(--shadow-md, 0 4px 16px rgba(0, 0, 0, 0.08));
  min-width: 240px;
  z-index: 5;
}
.ev-print-options-body .btn-sec {
  white-space: nowrap;
  text-align: left;
}

/* ─── Forfait Réception — pages create + show + index :
   Extraction des inline styles vers classes réutilisables (audit P3
   /distill, sprint a0a77ce). Pattern .ev-* pour rester sous le namespace
   evenement sans collision. ─── */

/* Form */
.ev-form {
  max-width: 680px;
}
.ev-form-group {
  margin-bottom: 20px;
}
.ev-form-group--last {
  margin-bottom: 24px;
}
.ev-form-label {
  display: block;
  font-weight: 600;
  margin-bottom: 6px;
  color: var(--ink);
}
.ev-form-input,
.ev-form-select,
.ev-form-textarea {
  width: 100%;
  padding: 10px 14px;
  border: 1px solid var(--border);
  border-radius: 8px;
  font-family: var(--font-body);
  font-size: 15px;
  background: var(--paper);
}
.ev-form-input--narrow {
  width: 200px;
}
.ev-form-hint {
  font-size: 12px;
  color: var(--ink-muted);
  margin-top: 4px;
}
.ev-form-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
  margin-bottom: 20px;
}
@media (max-width: 480px) {
  .ev-form-row {
    grid-template-columns: 1fr;
  }
}
.ev-form-prefix {
  margin-left: 8px;
  color: var(--ink-muted);
}
.ev-form-categories {
  display: grid;
  grid-template-columns: 1fr;
  gap: 8px;
}
.ev-form-categorie-label {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  cursor: pointer;
  padding: 14px;
  min-height: 44px;
  background: var(--paper-soft);
  border: 1px solid var(--border);
  border-radius: 10px;
}
.ev-form-categorie-checkbox {
  margin-top: 2px;
  width: 20px;
  height: 20px;
  cursor: pointer;
  flex-shrink: 0;
  accent-color: var(--brand);
}
.ev-form-categorie-text {
  font-size: 15px;
  line-height: 1.45;
  color: var(--ink);
}
.ev-form-categories-intro {
  font-size: 13px;
  color: var(--ink-muted);
  margin: 0 0 10px;
}
/* Pitch éducation pour les abonnés sur /recevoir/index — explique
   pourquoi le Forfait Réception est extra de l'abo (Marie persona
   feedback P2.12). Disclosure <details> pour ne pas alourdir si
   pas demandé. */
.ev-pitch-details {
  max-width: 720px;
  margin: 18px auto 0;
  padding: 0 16px;
}
.ev-pitch-summary {
  list-style: none;
  cursor: pointer;
  padding: 12px 16px;
  min-height: 44px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  background: var(--paper-soft);
  border: 1px solid var(--border);
  border-radius: 10px;
  font-size: 14px;
  font-weight: 500;
  color: var(--ink-soft);
  transition: background 0.15s;
}
@media (hover: hover) and (pointer: fine) {
  .ev-pitch-summary:hover {
    background: color-mix(in oklch, var(--brand) 4%, var(--paper-soft));
  }
}
.ev-pitch-summary::-webkit-details-marker {
  display: none;
}
.ev-pitch-details[open] .ev-pitch-summary {
  background: var(--paper-sheet);
  border-bottom-left-radius: 0;
  border-bottom-right-radius: 0;
}
.ev-pitch-summary-cta {
  font-size: 12px;
  color: var(--ink-muted);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.ev-pitch-body {
  padding: 16px 18px 18px;
  background: var(--paper-sheet);
  border: 1px solid var(--border);
  border-top: none;
  border-radius: 0 0 10px 10px;
  font-size: 14.5px;
  line-height: 1.6;
  color: var(--ink-soft);
}
.ev-pitch-body p {
  margin: 0 0 10px;
}
.ev-pitch-body strong {
  color: var(--ink);
  font-weight: 600;
}
.ev-pitch-list {
  list-style: none;
  padding: 0;
  margin: 0 0 12px;
  display: grid;
  grid-template-columns: 1fr;
  gap: 6px;
}
@media (min-width: 540px) {
  .ev-pitch-list {
    grid-template-columns: 1fr 1fr;
  }
}
.ev-pitch-list li {
  font-size: 13.5px;
  color: var(--ink);
  padding-left: 18px;
  position: relative;
}
.ev-pitch-list li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 8px;
  width: 6px;
  height: 6px;
  background: var(--brand);
  border-radius: 50%;
}
.ev-pitch-footer {
  font-size: 13px;
  color: var(--ink-muted);
  font-style: italic;
  margin: 14px 0 0;
}

/* Hint budget réactif — recalculé au changement nb_personnes ou style.
   Donne un range indicatif à Casey qui n'a aucune référence. */
.ev-budget-range {
  margin-top: 6px;
  padding: 8px 12px;
  background: var(--accent-tint);
  border-radius: 6px;
  font-size: 13px;
  line-height: 1.5;
  color: var(--ink-soft);
}
.ev-budget-range strong {
  color: var(--brand-dark, var(--brand));
  font-variant-numeric: tabular-nums;
  font-weight: 600;
}

/* ─── Style de réception : radio cards avec descriptions inline.
   Avant : <select> 7 options sans contexte → Casey clique au pif.
   Après : 7 cards radio avec 1 phrase de contexte chacune. ─── */
.ev-style-fieldset {
  border: none;
  padding: 0;
  margin: 0 0 20px;
}
.ev-style-fieldset .ev-form-label {
  margin-bottom: 12px;
}
.ev-style-cards {
  display: grid;
  grid-template-columns: 1fr;
  gap: 8px;
}
@media (min-width: 540px) {
  .ev-style-cards {
    grid-template-columns: 1fr 1fr;
  }
}
.ev-style-card {
  position: relative;
  display: grid;
  grid-template-columns: 22px 1fr;
  grid-template-rows: auto auto;
  column-gap: 12px;
  row-gap: 4px;
  align-items: start;
  padding: 14px 16px;
  min-height: 44px;
  background: var(--paper-soft);
  border: 1px solid var(--border);
  border-radius: 10px;
  cursor: pointer;
  transition:
    background 0.15s,
    border-color 0.15s;
}
@media (hover: hover) and (pointer: fine) {
  .ev-style-card:hover {
    background: color-mix(in oklch, var(--brand) 4%, var(--paper-soft));
    border-color: color-mix(in oklch, var(--brand) 25%, var(--border));
  }
}
.ev-style-card-input {
  appearance: none;
  -webkit-appearance: none;
  width: 22px;
  height: 22px;
  margin: 0;
  border: 1.5px solid var(--border);
  border-radius: 50%;
  cursor: pointer;
  position: relative;
  background: var(--paper);
  grid-row: 1 / 3;
  align-self: start;
  margin-top: 2px;
  flex-shrink: 0;
  transition:
    background 0.15s,
    border-color 0.15s;
}
.ev-style-card-input:checked {
  background: var(--brand);
  border-color: var(--brand);
  border-width: 6px;
}
.ev-style-card-input:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 3px;
}
.ev-style-card:has(.ev-style-card-input:checked) {
  background: var(--accent-tint);
  border-color: var(--brand);
}
.ev-style-card-label {
  font-size: 15px;
  font-weight: 600;
  color: var(--ink);
  line-height: 1.3;
}
.ev-style-card-desc {
  font-size: 13px;
  line-height: 1.45;
  color: var(--ink-muted);
}

/* ─── Catégories en disclosure <details> avancé. Avant 8 checkboxes
   toujours visibles = surcharge décisionnelle Casey. Après caché par
   défaut, le user qui veut customiser ouvre. Defaults intelligents
   dérivés du style appliqués via old('categories', ...) Blade. ─── */
.ev-form-categories-details {
  margin: 0 0 20px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--paper-soft);
  overflow: hidden;
}
.ev-form-categories-details[open] {
  background: var(--paper-sheet);
}
.ev-form-categories-summary {
  list-style: none;
  cursor: pointer;
  padding: 14px 18px;
  min-height: 44px;
  display: flex;
  align-items: baseline;
  gap: 10px;
  flex-wrap: wrap;
  user-select: none;
}
.ev-form-categories-summary::-webkit-details-marker {
  display: none;
}
.ev-form-categories-summary::before {
  content: "›";
  font-family: var(--font-display);
  font-size: 18px;
  color: var(--ink-muted);
  margin-right: 4px;
  transition: transform 0.2s;
  display: inline-block;
}
.ev-form-categories-details[open] .ev-form-categories-summary::before {
  transform: rotate(90deg);
}
.ev-form-categories-summary-text {
  font-size: 14.5px;
  font-weight: 600;
  color: var(--ink);
}
.ev-form-categories-summary-meta {
  font-size: 12.5px;
  color: var(--ink-muted);
  font-style: italic;
}
.ev-form-categories-body {
  padding: 0 18px 18px;
  border-top: 1px solid var(--border2);
  margin-top: 4px;
  padding-top: 14px;
}

/* Pricing récap card (above submit button) */
.ev-pricing-card {
  background: var(--accent-tint);
  border: 1px solid color-mix(in oklch, var(--brand) 25%, transparent);
  border-radius: 14px;
  padding: 18px;
  margin-bottom: 24px;
}
.ev-pricing-card-grid {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: 12px;
}
.ev-pricing-card-amount {
  display: block;
  font-size: 18px;
  color: var(--ink);
}
.ev-pricing-card-meta {
  font-size: 13px;
  color: var(--ink-muted);
}
.ev-pricing-card-detail {
  font-size: 12px;
  color: var(--ink-muted);
  text-align: right;
}
/* Note rassurante pour les users déjà abonnés (subscribed default ou
   is_comped) — clarifie que le 9,99 $ Forfait Réception est UN paiement
   unique séparé de l'abonnement mensuel. Élimine la friction P0
   identifiée par persona Claudette : « pas chargé 2x ? ». */
.ev-pricing-card-reassure {
  margin: 14px 0 0;
  padding-top: 14px;
  border-top: 1px solid color-mix(in oklch, var(--brand) 18%, var(--border));
  font-size: 13px;
  line-height: 1.55;
  color: var(--ink-soft);
  grid-column: 1 / -1;
}
.ev-pricing-card-reassure strong {
  color: var(--ink);
  font-weight: 600;
}

/* Form actions row */
.ev-form-actions {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
  align-items: center;
}

/* Validation errors block */
.ev-form-errors {
  padding: 14px;
  background: color-mix(in oklch, var(--danger, var(--canneberge, var(--ink-muted))) 8%, var(--paper-soft));
  border: 1px solid color-mix(in oklch, var(--danger, var(--canneberge, var(--border))) 35%, var(--border));
  border-radius: 8px;
  margin-bottom: 20px;
}
.ev-form-errors-list {
  margin: 8px 0 0 20px;
  padding: 0;
}

/* Status bar (page show, en-tête bandeau) */
.ev-status-bar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: 12px;
  margin-bottom: 24px;
  padding: 14px 18px;
  background: var(--paper-soft);
  border-radius: 10px;
}
.ev-status-bar-text {
  font-size: 13px;
  color: var(--ink-soft);
  line-height: 1.5;
}
.ev-status-bar-secondary {
  display: block;
  font-size: 12px;
  color: var(--ink-muted);
  margin-top: 2px;
}
.ev-status-bar-form {
  margin: 0;
}
.ev-status-bar-btn {
  font-size: 13px;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
}

/* Empty/pending sections (paiement en attente, génération en cours) */
.ev-empty-card {
  padding: 24px;
  text-align: center;
  border-radius: 14px;
}
.ev-empty-card--pending {
  background: var(--paper-soft);
  border: 1px solid var(--border);
}
.ev-empty-card--loading {
  background: var(--accent-tint);
  border: 1px solid color-mix(in oklch, var(--brand) 22%, transparent);
}
.ev-empty-card-title {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 22px;
  margin: 0 0 8px;
}

/* Bottom navigation actions (back to list, new event) */
.ev-back-actions {
  margin-top: 32px;
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
}

/* ─── Admin circulaires upload — refonte mono-accent (anti-pattern :
   les gradients brand-color hard-coded #e30613/#005daa/#e31837/#00833f
   cassaient la palette mono-accent vert Jean-Talon. Remplacés par cards
   monochromes sobres avec lift hover + bg crème). ─── */
.admin-circ-info {
  background: var(--accent-tint);
  border: 1px solid color-mix(in oklch, var(--brand) 22%, transparent);
  border-radius: 12px;
  padding: 14px 16px;
  font-size: 12px;
  color: var(--ink-soft);
  line-height: 1.6;
}
.admin-circ-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 10px;
  margin-top: 10px;
}
.admin-circ-grid--compact {
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  margin-bottom: 14px;
}
.admin-circ-link {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  padding: 18px 12px;
  min-height: 76px;
  border-radius: 12px;
  background: var(--paper-sheet, var(--paper-soft));
  border: 1px solid var(--border);
  color: var(--ink);
  text-decoration: none;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 16px;
  letter-spacing: -0.01em;
  transition:
    transform 0.15s,
    box-shadow 0.15s,
    border-color 0.15s;
}
@media (hover: hover) and (pointer: fine) {
  .admin-circ-link:hover {
    transform: translateY(-2px);
    box-shadow: var(--shadow-sm, 0 2px 8px rgba(0, 0, 0, 0.06));
    border-color: color-mix(in oklch, var(--brand) 35%, var(--border));
  }
}
.admin-circ-link-name {
  font-weight: 400;
}
.admin-circ-link-domain {
  font-family: var(--font-body);
  font-size: 10px;
  color: var(--ink-muted);
  font-weight: 500;
}
.admin-circ-fetch-form {
  margin: 0;
}
.admin-circ-fetch-btn {
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  padding: 16px 10px;
  min-height: 64px;
  border-radius: 12px;
  background: var(--accent-tint);
  border: 1px solid color-mix(in oklch, var(--brand) 30%, transparent);
  color: var(--ink);
  cursor: pointer;
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 13px;
  transition:
    transform 0.15s,
    background 0.15s;
}
.admin-circ-fetch-btn:active {
  transform: scale(0.97);
}
@media (hover: hover) and (pointer: fine) {
  .admin-circ-fetch-btn:hover {
    background: color-mix(in oklch, var(--brand) 18%, var(--paper-soft));
  }
}
.admin-circ-fetch-bolt {
  font-size: 16px;
  color: var(--brand-dark, var(--brand));
}
.admin-circ-dropzone {
  border: 2px dashed color-mix(in oklch, var(--ink-muted) 30%, transparent);
  border-radius: 14px;
  background: var(--paper-soft);
  padding: 32px 20px;
  text-align: center;
  cursor: pointer;
  transition:
    background 0.2s,
    border-color 0.2s;
}
.admin-circ-dropzone.is-dragover {
  background: var(--accent-tint);
  border-color: var(--brand);
}
.admin-circ-dropzone-icon {
  font-size: 42px;
  margin-bottom: 10px;
}
.admin-circ-dropzone-title {
  font-weight: 800;
  font-size: 15px;
  color: var(--ink);
  margin-bottom: 4px;
}
.admin-circ-dropzone-sub {
  font-size: 12px;
  color: var(--ink-muted);
  margin-bottom: 12px;
}
.admin-circ-dropzone-meta {
  font-size: 11px;
  color: var(--ink-muted);
}
.admin-circ-fileinput {
  display: none;
}
.admin-circ-file-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 12px;
  background: color-mix(in oklch, var(--brand) 4%, var(--paper-soft));
  border: 1px solid color-mix(in oklch, var(--brand) 18%, var(--border));
  border-radius: 10px;
  font-size: 12px;
}
.admin-circ-file-row.is-toobig {
  background: color-mix(in oklch, var(--danger) 6%, var(--paper-soft));
  border-color: color-mix(in oklch, var(--danger) 35%, var(--border));
}
.admin-circ-file-icon {
  font-size: 18px;
}
.admin-circ-file-meta {
  flex: 1;
  min-width: 0;
}
.admin-circ-file-name {
  font-weight: 700;
  color: var(--ink);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.admin-circ-file-size {
  font-size: 10px;
  color: var(--ink-muted);
}
.admin-circ-file-row.is-toobig .admin-circ-file-size {
  color: var(--danger);
}
.admin-circ-select {
  width: 100%;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--paper);
  font-size: 13px;
  font-family: var(--font-body);
  color: var(--ink);
}
.admin-circ-status-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 0;
  border-bottom: 1px solid var(--border2);
}
.admin-circ-status-info {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}
.admin-circ-status-name {
  font-weight: 800;
  color: var(--ink);
  min-width: 110px;
}
.admin-circ-pill-empty {
  background: var(--paper-soft);
  color: var(--ink-muted);
}
.admin-circ-history-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 0;
  border-bottom: 1px solid var(--border2);
  font-size: 13px;
}
.admin-circ-history-info {
  display: flex;
  align-items: center;
  gap: 10px;
  flex: 1;
}
.admin-circ-history-icon {
  font-size: 18px;
}
.admin-circ-history-name {
  font-weight: 700;
  color: var(--ink);
}
.admin-circ-history-meta {
  font-size: 11px;
  color: var(--ink-muted);
}
.admin-circ-delete-btn {
  background: transparent;
  border: 1px solid color-mix(in oklch, var(--danger) 35%, transparent);
  color: var(--danger);
  padding: 11px 14px;
  min-height: 44px;
  border-radius: 8px;
  cursor: pointer;
  font-size: 11px;
  font-weight: 600;
  transition: background 0.15s;
}
@media (hover: hover) and (pointer: fine) {
  .admin-circ-delete-btn:hover {
    background: color-mix(in oklch, var(--danger) 8%, transparent);
  }
}
.admin-circ-empty {
  text-align: center;
  color: var(--ink-muted);
  padding: 20px;
  font-size: 13px;
}

/* Index page hero card */
.ev-hero-card {
  text-align: center;
  padding: 32px 24px;
  background: var(--accent-tint);
  border: 1px solid color-mix(in oklch, var(--brand) 22%, transparent);
  border-radius: 14px;
}
.ev-hero-card-title {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 24px;
  margin: 0 0 10px;
}
.ev-hero-card-sub {
  margin: 0 0 20px;
  color: var(--ink-soft);
}

/* ═══════════════════════════════════════════════════════════════
   Regles desktop relocalisees depuis mobile-fixes.css (2026-05-09) :
   le fichier mobile-fixes est media-gated max-width:900px sur l app
   donc les @media (min-width:...) qu il contenait ne pouvaient
   jamais s activer. Cleanup pollution desktop.
═══════════════════════════════════════════════════════════════ */

/* .recipe-layout — RELOCALISÉ depuis mobile-fixes.css 2026-05-10 (P0
   hotfix) : la grille 2-col du détail recette vivait dans mobile-fixes,
   donc jamais active sur desktop. Bug latent depuis le début, exposé
   par le passage breakpoint 900→768. minmax(0, …) évite le débordement
   horizontal causé par les badges et les noms d'ingrédients longs. */
.recipe-layout {
  display: grid;
  grid-template-columns: minmax(0, 1.45fr) minmax(0, 1fr);
  gap: clamp(14px, 2vw, 22px);
  align-items: start;
}
@media (max-width: 1024px) {
  .recipe-layout {
    grid-template-columns: 1fr;
    gap: 16px;
  }
}

/* Sticky "Liste du soir" en desktop : quand on scrolle les
   ingredients/instructions, la colonne liste reste visible et
   cochable. Désactivée sous 1024px (déjà stackée — match le breakpoint
   de stacking ci-dessus). PR #87 Codex P2 round 1 : avant min-width:
   961px laissait sticky actif entre 961-1024px où le layout est déjà
   stacké → sticky panel sur un layout 1-colonne = comportement
   incohérent. Maintenant aligné à 1025px (juste au-dessus du stacking
   breakpoint). */
@media (min-width: 1025px) {
  .recipe-layout > :last-child .lp {
    position: sticky;
    top: 80px;
    max-height: calc(100vh - 100px);
    overflow-y: auto;
  }
}

/* Spacing fluid apres .page-masthead : evite que le bloc suivant
   colle visuellement au lede sur ecran large. */
@media (min-width: 769px) {
  .page-masthead + div,
  .page-masthead + section,
  .page-masthead + form {
    margin-top: clamp(18px, 2.2vw, 28px);
  }
}

/* Resume optimisation multi-epicerie sur menu/liste 2026-05-09 :
   surface l economie possible AVANT que Marie clique sur le bouton
   « Optimiser ». Pattern card cliquable, accent vert sobre, pas de
   gradient, touch target 44px. Affiche seulement si economie > 5$. */
.optim-resume {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 14px;
  padding: 16px 20px;
  margin-bottom: 16px;
  background: var(--accent-tint);
  border: 1px solid color-mix(in oklch, var(--brand) 22%, transparent);
  border-radius: 14px;
  text-decoration: none;
  color: inherit;
  min-height: 44px;
  transition:
    background 0.2s ease,
    border-color 0.2s ease;
}
@media (hover: hover) and (pointer: fine) {
  .optim-resume:hover {
    background: color-mix(in oklch, var(--accent-tint) 80%, var(--brand) 6%);
    border-color: color-mix(in oklch, var(--brand) 38%, transparent);
  }
}
.optim-resume:focus-visible {
  outline: 2px solid var(--brand-dark, var(--brand));
  outline-offset: 2px;
}
.optim-resume-amount {
  font-family: var(--font-display);
  font-size: 28px;
  font-weight: 400;
  color: var(--brand-dark, var(--brand));
  letter-spacing: -0.015em;
  font-variant-numeric: tabular-nums;
  flex-shrink: 0;
}
.optim-resume-text {
  flex: 1;
  font-size: 13.5px;
  line-height: 1.45;
  color: var(--ink);
  min-width: 200px;
}
.optim-resume-cta {
  font-size: 11.5px;
  font-weight: 600;
  color: var(--brand-dark, var(--brand));
  text-transform: uppercase;
  letter-spacing: 0.06em;
  flex-shrink: 0;
}
@media (max-width: 480px) {
  .optim-resume {
    padding: 14px 16px;
    gap: 10px;
  }
  .optim-resume-amount {
    font-size: 24px;
  }
  .optim-resume-text {
    font-size: 13px;
  }
}

/* ═══════════════════════════════════════════════════════════════
   Mode Grand-Maman 2026-05-09 (audit R8 P0) — CSS COMPLET.
   Avant : juste 1 regle sur .ev-dropcap. Le toggle existait dans
   profil/edit mais ne changeait quasi rien visuellement. Claudette
   activait, ne voyait aucune difference, repassait off.
   Maintenant : font-size +14%, line-height aere, contraste rampe,
   touch targets renforces a 48px, tous les muteds remontes vers ink.
═══════════════════════════════════════════════════════════════ */
body.mode-grand-maman {
  font-size: 17px; /* base 15px → 17px = +13% */
  line-height: 1.65;
}
body.mode-grand-maman h1,
body.mode-grand-maman .page-masthead-title {
  font-size: clamp(28px, 6vw, 38px);
}
body.mode-grand-maman h2,
body.mode-grand-maman .dash-section-title {
  font-size: clamp(22px, 4.5vw, 28px);
  line-height: 1.3;
}
body.mode-grand-maman h3 {
  font-size: 18px;
  line-height: 1.4;
}
/* Boutons + interactifs : touch target 48px (au lieu de 44px) */
body.mode-grand-maman .btn-main,
body.mode-grand-maman .btn-sec {
  min-height: 48px;
  font-size: 16px;
  padding: 14px 22px;
}
body.mode-grand-maman .profil-toggle-row,
body.mode-grand-maman .ev-stall-check,
body.mode-grand-maman .share-item {
  min-height: 48px;
}
body.mode-grand-maman input[type="text"],
body.mode-grand-maman input[type="email"],
body.mode-grand-maman input[type="tel"],
body.mode-grand-maman input[type="password"],
body.mode-grand-maman input[type="number"],
body.mode-grand-maman select {
  font-size: 17px;
  min-height: 48px;
  padding: 12px 16px;
}
/* Contraste : on remonte les textes mutes vers le ink (3:1 → 5:1+) */
body.mode-grand-maman {
  --ink-muted: oklch(0.4 0.014 75); /* avant ~0.46 */
  --ink-soft: oklch(0.3 0.014 75); /* avant ~0.36 */
}
/* Liens plus visibles */
body.mode-grand-maman a:not(.btn-main):not(.btn-sec) {
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1.5px;
}
/* Reduit la danse typographique (em italiques fatiguent les yeux) */
body.mode-grand-maman em {
  font-style: normal;
  font-weight: 600;
  color: var(--brand-dark, var(--brand));
}
/* Le drop cap reste neutralise (regle existante ligne 10304) */

/* ════════════════════════════════════════════════════════════════════
   REFONTE 2026-05-10 — anti-AI / anti-template app authentifiée
   - emojis decoratifs retires de liste, recette, menu, dashboard
   - dash-restock-collapse simplifie en lien
   - onboarding progress sticky
   - composer auto-hide scroll
   - astuce-bandeau eyebrow typographique
   - liste-* classes (modal QR, share row, scan btn)
   - footer trust signals mobile
   ════════════════════════════════════════════════════════════════════ */

/* Astuce bandeau — eyebrow typographique au lieu d'emoji */
.astuce-bandeau-eyebrow {
  display: inline-block;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--brand-dark, var(--brand));
  margin-right: 12px;
  padding: 3px 8px;
  border: 1px solid color-mix(in oklch, var(--brand) 22%, transparent);
  border-radius: 4px;
  vertical-align: 1px;
}

/* Liste — actions row sobre */
.liste-actions {
  display: flex;
  gap: 10px;
  margin-bottom: 16px;
  flex-wrap: wrap;
  align-items: center;
}
.liste-action-btn {
  font-size: 12px;
  letter-spacing: 0.01em;
}
.liste-share-row {
  display: flex;
  align-items: center;
  gap: 10px;
  background: color-mix(in oklch, var(--brand) 8%, transparent);
  border: 1px solid color-mix(in oklch, var(--brand) 22%, transparent);
  border-radius: 10px;
  padding: 10px 14px;
  font-size: 12px;
  flex-wrap: wrap;
}
.liste-share-url {
  font-family: ui-monospace, "SF Mono", Monaco, monospace;
  color: var(--ink-soft);
  word-break: break-all;
  flex: 1 1 200px;
}
.liste-help-text {
  font-size: 13px;
  color: var(--ink-muted);
  line-height: 1.55;
  margin-top: 6px;
}
.liste-scan-btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-top: 12px;
  font-size: 13px;
}

/* Liste — modal QR sobre */
.liste-qr-modal {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.6);
  z-index: 500;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
}
.liste-qr-modal[hidden] {
  display: none;
}
.liste-qr-modal-card {
  background: var(--paper);
  border-radius: 18px;
  padding: 28px 24px 22px;
  text-align: center;
  max-width: 320px;
  width: 100%;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.25);
}
.liste-qr-modal-title {
  font-family: var(--font-display, "Young Serif", serif);
  font-size: 17px;
  font-weight: 400;
  color: var(--ink);
  margin-bottom: 16px;
}
.liste-qr-modal-card canvas {
  border-radius: 8px;
}
.liste-qr-modal-url {
  font-size: 11px;
  color: var(--muted);
  margin-top: 12px;
  word-break: break-all;
}
.liste-qr-modal-close {
  margin-top: 16px;
  width: 100%;
}

/* Recette — bouton cuisiner étape par étape */
.recette-cuisiner-btn {
  margin-top: 14px;
  padding: 14px;
  font-size: 14px;
  text-align: center;
  display: block;
}
.recette-cuisiner-note {
  font-size: 11px;
  color: var(--muted);
  text-align: center;
  margin-top: 8px;
}

/* Dashboard — restock simplifié en lien (anciennement <details>) */
.dash-restock-link {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  margin-top: 18px;
  padding: 12px 16px;
  background: color-mix(in oklch, var(--accent-tint) 60%, transparent);
  border: 1px solid color-mix(in oklch, var(--brand) 18%, transparent);
  border-radius: 12px;
  text-decoration: none;
  color: var(--ink);
  transition:
    border-color 0.18s,
    background 0.18s;
}
@media (hover: hover) and (pointer: fine) {
  .dash-restock-link:hover {
    background: var(--accent-tint);
    border-color: color-mix(in oklch, var(--brand) 32%, transparent);
  }
}
.dash-restock-link-text {
  font-size: 13px;
  line-height: 1.55;
  color: var(--ink-soft);
}
.dash-restock-link-text strong {
  color: var(--brand-dark, var(--brand));
  font-weight: 700;
}
.dash-restock-link-cta {
  font-size: 12px;
  font-weight: 600;
  color: var(--brand-dark, var(--brand));
  flex-shrink: 0;
  letter-spacing: 0.04em;
}

/* Onboarding — styles déplacés du <style> inline 2026-05-10 */
.onb-page {
  max-width: 560px;
  margin: 0 auto;
  padding-bottom: 120px;
  position: relative;
}
.onb-progress {
  position: absolute;
  top: -4px;
  right: 0;
  font-size: 12px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-muted);
  font-weight: 600;
}
.onb-progress-current {
  color: var(--brand-dark, var(--brand));
  font-size: 16px;
  font-weight: 700;
}
.onb-progress-sep {
  margin: 0 4px;
  color: var(--muted);
}
.onb-progress-total {
  color: var(--ink-muted);
}
.onb-h1 {
  font-family: var(--font-display, "Young Serif", serif);
  font-size: 28px;
  font-weight: 400;
  line-height: 1.2;
  margin: 0 0 12px 0;
  color: var(--ink);
}
.onb-h1 em {
  color: var(--brand-dark, var(--brand));
  font-style: italic;
}
.onb-intro {
  font-size: 14.5px;
  color: var(--ink2, var(--ink-soft));
  line-height: 1.65;
  margin-bottom: 32px;
}
.onb-section {
  margin-bottom: 36px;
  padding-bottom: 32px;
  border-bottom: 1px solid var(--border2, var(--border));
}
.onb-section:last-of-type {
  border-bottom: none;
  padding-bottom: 0;
}
.onb-section-title {
  font-family: var(--font-display, "Young Serif", serif);
  font-size: 20px;
  font-weight: 400;
  color: var(--ink);
  margin: 0 0 6px 0;
  line-height: 1.25;
}
.onb-section-sub {
  font-size: 13px;
  color: var(--muted);
  margin: 0 0 18px 0;
  line-height: 1.5;
}
.onb-actions {
  position: sticky;
  bottom: 0;
  background: var(--paper);
  padding: 18px 0;
  border-top: 1px solid var(--border);
  margin-top: 24px;
  z-index: 5;
  display: flex;
  gap: 10px;
  align-items: center;
}
.onb-skip-link {
  font-size: 13px;
  color: var(--muted);
  text-decoration: underline;
  padding: 8px;
}
.onb-submit-btn {
  flex: 1;
}
/* SMS toggle (déplacé du <style> inline) */
.sms-toggle {
  background: var(--bg);
  border: 1.5px solid var(--border);
  border-radius: 10px;
  padding: 14px;
  display: flex;
  align-items: center;
  gap: 12px;
  cursor: pointer;
  transition: border-color 0.2s;
}
@media (hover: hover) and (pointer: fine) {
  .sms-toggle:hover {
    border-color: var(--brand-dark, var(--orange));
  }
}
.sms-track {
  width: 40px;
  height: 24px;
  border-radius: 12px;
  background: var(--muted2);
  transition: background 0.2s;
  position: relative;
  flex-shrink: 0;
}
.sms-thumb {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--cream-fixed);
  position: absolute;
  top: 3px;
  left: 3px;
  /* GPU : transform: translateX au lieu de left pour 60fps. Le JS
     toggle.js applique --on (0|1), CSS calcule la translation. */
  transform: translateX(calc(var(--on, 0) * 16px));
  transition: transform 0.2s cubic-bezier(0.22, 1, 0.36, 1);
  will-change: transform;
}

/* App-footer trust signals (mobile + desktop) */
.app-footer-trust {
  margin-top: 32px;
  padding: 16px 0 24px;
  font-size: 11px;
  color: var(--ink-muted);
  text-align: center;
  letter-spacing: 0.04em;
  line-height: 1.7;
}
.app-footer-trust-sep {
  margin: 0 8px;
  opacity: 0.5;
}

/* Dashboard hero refacto 2026-05-10 — version compacte sans
   double KPI concurrent. Ring + budget-line + fantome inline. */
.dash-hero-grid--compact {
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: center;
  gap: 24px;
  margin-top: 18px;
}
@media (max-width: 640px) {
  .dash-hero-grid--compact {
    grid-template-columns: 1fr;
    text-align: left;
    gap: 18px;
  }
  .dash-hero-grid--compact .dash-hero-ring {
    margin: 0 auto;
  }
}
.dash-hero-budget {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.dash-hero-budget-line {
  font-size: 15px;
  line-height: 1.5;
  color: var(--ink);
  font-weight: 500;
}
.dash-hero-budget-line strong {
  font-weight: 700;
  color: var(--brand-dark, var(--brand));
}
/* Dash hero KPI classes héritées (.dash-hero-fantome, -streak,
   -cuisinees, -kpi) retirées 2026-05-18 — KPI déplacés vers le tab
   "Ma semaine" en PR #105. Le mini-KPI hero inline est porté par
   .dash-hero-fantome-inline (différent). Audit pass 3 cleanup. */

/* Generation loading : mark sobre Young Serif au lieu de l'emoji 👨‍🍳 */
.gen-loading-mark {
  width: 64px;
  height: 64px;
  margin: 0 auto 18px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-display, "Young Serif", serif);
  font-size: 38px;
  color: var(--brand-dark, var(--brand));
  background: color-mix(in oklch, var(--brand) 10%, transparent);
  border: 1px solid color-mix(in oklch, var(--brand) 22%, transparent);
  border-radius: 50%;
  letter-spacing: -0.02em;
}

/* Composer-bar auto-hide au scroll-down (libère 52px viewport mobile).
   Réapparaît au scroll-up — pattern iOS Mail / Twitter / Notion mobile. */
@media (max-width: 900px) {
  .composer-bar {
    transition:
      transform 0.28s cubic-bezier(0.2, 0.8, 0.2, 1),
      opacity 0.18s ease;
    will-change: transform;
  }
  body.composer-hidden .composer-bar {
    transform: translateY(120%);
    opacity: 0;
    pointer-events: none;
  }
}

/* ════════════════════════════════════════════════════════════════════
   MODE GRAND-MAMAN + DARK MODE COMBO 2026-05-10 (P1 audit)
   Avant : règles mode-grand-maman:lightmode appliquaient des couleurs
   prévues pour fond paper (clair). Combinées au dark mode iOS auto,
   contraste cassé. Maintenant : règles dédiées combo qui:
   - bumpent les ink-* vers le clair (vs sombre paper en dark)
   - gardent la typo enlarged + spacing accru du Mode GM
   - préservent les liens soulignés
   ════════════════════════════════════════════════════════════════════ */

[data-theme="dark"] body.mode-grand-maman,
[data-theme="dark"] body.mode-gm {
  /* Bumper les ink-* vers les valeurs CLAIRES sur fond sombre (paper
     en dark = sombre). Sinon les overrides Mode GM appliquent du sombre
     sur sombre = invisible. */
  --ink-muted: oklch(0.78 0.014 75);
  --ink-soft: oklch(0.85 0.014 75);
  --ink: oklch(0.95 0.008 75);
}

/* Liens soulignés restent visibles en dark + GM */
[data-theme="dark"] body.mode-grand-maman a:not(.btn-main):not(.btn-sec),
[data-theme="dark"] body.mode-gm a:not(.btn-main):not(.btn-sec) {
  text-decoration-color: color-mix(in oklch, var(--brand) 70%, var(--ink-muted));
}

/* Em italiques bumpés vers brand-clair en dark + GM */
[data-theme="dark"] body.mode-grand-maman em,
[data-theme="dark"] body.mode-gm em {
  color: oklch(0.78 0.16 143); /* brand clair pour fond sombre */
}

/* Cuisine timer alarm — fallback visuel persistant 2026-05-10
   (critique P1). Audio bloqué iOS sans interaction + vibrate desktop
   inexistant → flash visuel jusqu'à click/touch dismiss. */
.cuisine-timer-alarm {
  animation: cuisine-alarm-pulse 0.9s cubic-bezier(0.4, 0, 0.6, 1) infinite;
  color: var(--danger, #c0392b) !important;
}
@keyframes cuisine-alarm-pulse {
  0%,
  100% {
    transform: scale(1);
    opacity: 1;
  }
  50% {
    transform: scale(1.06);
    opacity: 0.55;
  }
}
body.cuisine-alarm-firing {
  /* Flash léger sur le viewport entier — iOS le voit même quand la
     page est en background ou que MacBook est en attention partielle. */
  box-shadow: inset 0 0 0 4px var(--danger, #c0392b);
  transition: box-shadow 0.15s ease;
}
@media (prefers-reduced-motion: reduce) {
  .cuisine-timer-alarm {
    animation: none;
  }
}

/* ════════════════════════════════════════════════════════════════════
   RECETTE PAGE — extraction inline styles 2026-05-10 (audit P1)
   Avant : 35 occurrences `style=""` dans menu/recette.blade.php = dette
   typographique qui plombait le score Anti-Pattern. Maintenant : classes
   sémantiques. Source of truth unique pour la prochaine refonte.
   ════════════════════════════════════════════════════════════════════ */
.recipe-tags-row {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  margin-bottom: 14px;
}
.recipe-tag-pill {
  font-size: 10px;
}
.recipe-description {
  font-size: 13px;
  color: var(--muted);
  margin-bottom: 16px;
  line-height: 1.7;
}
.recipe-section-head {
  margin-bottom: 10px;
}
.recipe-ing-list {
  margin-bottom: 18px;
}
.recipe-ing-qty {
  color: var(--muted);
  font-size: 11px;
}
.recipe-ing-meta {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}
.recipe-price-trend {
  color: var(--green, var(--brand));
}
.recipe-instructions-head {
  margin-bottom: 10px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  flex-wrap: wrap;
}
.recipe-tts-btn {
  padding: 8px 14px;
  font-size: 12px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.recipe-tts-progress {
  margin-bottom: 10px;
  padding: 10px 14px;
  background: var(--green-pale, color-mix(in oklch, var(--brand) 10%, transparent));
  border-radius: 10px;
  font-size: 12px;
  color: var(--green, var(--brand));
  border: 1px solid color-mix(in oklch, var(--brand) 20%, transparent);
}
.recipe-tts-progress[hidden] {
  display: none;
}
.recipe-tts-progress-hint {
  margin-left: 8px;
  opacity: 0.7;
}
.recipe-tts-container {
  background: var(--bg, var(--paper-soft));
  border-radius: 14px;
  padding: 18px;
  font-size: 13px;
  color: var(--ink2, var(--ink-soft));
  line-height: 1.8;
  white-space: pre-line;
}
.recipe-enrichir-form {
  margin-top: 14px;
}
.recipe-enrichir-btn {
  padding: 14px;
  font-size: 14px;
}
.recipe-enrichir-note {
  font-size: 11px;
  color: var(--muted);
  text-align: center;
  margin-top: 8px;
}
.recipe-bottom-actions {
  margin-top: 14px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.recipe-bottom-link {
  text-align: center;
}

/* Generation loading mark : variant for evenement/show — same as menu */
.gen-loading-mark {
  /* déjà défini plus haut, ce duplicate est sûr */
}

/* Status alert variant — pas d'emoji ✅, juste le sémantique couleur. */
.ev-share-status--ok {
  color: var(--brand-dark, var(--brand));
  font-weight: 500;
}
.ev-share-status--ok strong {
  font-weight: 700;
}

/* ════════════════════════════════════════════════════════════════════
   PEAK-END CUISINER — cascade temporelle 2026-05-10 (war room Things 3)
   Avant : check + feedback + cookbook + actions affichés simultanément
   au moment de fierté. Bombardement de tâches.
   Maintenant : 3 stages avec animation-delay 0 / 1.4s / 3s.
   Le moment de fierté est un moment d'air, pas un formulaire.
   ════════════════════════════════════════════════════════════════════ */
.cuisine-end-stage1,
.cuisine-end-stage2,
.cuisine-end-stage3 {
  opacity: 0;
  transform: translateY(8px);
  animation: cuisine-end-fade 0.6s cubic-bezier(0.2, 0.8, 0.2, 1) forwards;
}
.cuisine-end-stage1 {
  animation-delay: 0s;
}
.cuisine-end-stage2 {
  animation-delay: 1.4s;
}
.cuisine-end-stage3 {
  animation-delay: 3s;
}
@keyframes cuisine-end-fade {
  from {
    opacity: 0;
    transform: translateY(8px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}
@media (prefers-reduced-motion: reduce) {
  .cuisine-end-stage1,
  .cuisine-end-stage2,
  .cuisine-end-stage3 {
    opacity: 1;
    transform: none;
    animation: none;
  }
}
.cuisine-end-feedback-prompt {
  font-size: 14px;
  color: var(--ink-muted);
  text-align: center;
  margin: 18px 0 12px;
  letter-spacing: 0.005em;
}

/* paper-soft 0.965 → 0.948 effectué directement dans la définition
   du token ligne 26 (war room delta luminosité). ADN tabac chaud
   préservé (hue 75 inchangée). */

/* ─────────────────────────────────────────────────────────────
   Sparkline cards (Phase 2 — Data viz partout)
   2026-05-11. Le brutal critique : pages « data » sans data viz.
   Pattern réutilisable pour Rapport finances, Surveillance, etc.
   ───────────────────────────────────────────────────────────── */
.rap-spark-card {
  padding: 18px 20px 16px;
  border-color: var(--brand);
  background: var(--paper-sheet);
}
.rap-spark-eyebrow {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--brand-dark);
  font-weight: 700;
  margin-bottom: 12px;
}
.rap-spark-svg {
  display: block;
  width: 100%;
  height: 96px;
  max-width: 480px;
  margin: 0 auto;
  overflow: visible;
}
.rap-spark-labels {
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  margin-top: 12px;
  padding: 0 4px;
  gap: 12px;
}
.rap-spark-labels span {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--ink-muted);
  line-height: 1.5;
}
.rap-spark-labels strong {
  display: block;
  font-family: var(--font-display, "Young Serif", Georgia, serif);
  font-size: 22px;
  font-weight: 400;
  letter-spacing: -0.01em;
  color: var(--brand-dark);
  text-transform: none;
  margin-top: 2px;
  font-variant-numeric: tabular-nums;
}
.rap-spark-end {
  text-align: right;
}
.rap-spark-end strong {
  color: var(--brand-dark);
}
@media (max-width: 640px) {
  .rap-spark-svg {
    height: 80px;
  }
  .rap-spark-labels strong {
    font-size: 18px;
  }
}

/* ─────────────────────────────────────────────────────────────
   Victory Lap banner (Phase 5 — 2026-05-11)
   Montré rarement (session-deduped). Pas de confetti spam.
   Subtile entrance fade + slide-down. Mark typographique Young
   Serif géant (VII / IV / X / $ / $$) à la place des emojis.
   ───────────────────────────────────────────────────────────── */
.dash-victory {
  display: flex;
  align-items: center;
  gap: 20px;
  padding: 22px 24px;
  background: var(--accent-tint);
  border: 1px solid var(--brand);
  border-radius: 18px;
  margin: 0 0 20px 0;
  position: relative;
  overflow: hidden;
  animation: dashVictoryEnter 480ms cubic-bezier(0.22, 1, 0.36, 1);
}
.dash-victory::before {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(120% 80% at 0% 0%, color-mix(in oklch, var(--brand) 12%, transparent), transparent 60%);
  pointer-events: none;
}
.dash-victory-mark {
  font-family: var(--font-display, "Young Serif", Georgia, serif);
  font-size: 56px;
  line-height: 1;
  color: var(--brand-dark);
  flex-shrink: 0;
  min-width: 64px;
  text-align: center;
  letter-spacing: -0.04em;
  font-variant-numeric: lining-nums;
}
.dash-victory-body {
  flex: 1;
  min-width: 0;
}
.dash-victory-title {
  font-family: var(--font-display, "Young Serif", Georgia, serif);
  font-size: 24px;
  line-height: 1.2;
  color: var(--ink);
  margin-bottom: 4px;
}
.dash-victory-message {
  font-size: 15px;
  line-height: 1.5;
  color: var(--ink-soft);
}
@keyframes dashVictoryEnter {
  from {
    opacity: 0;
    transform: translateY(-8px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}
@media (prefers-reduced-motion: reduce) {
  .dash-victory {
    animation: none;
  }
}
@media (max-width: 640px) {
  .dash-victory {
    gap: 14px;
    padding: 18px 18px;
  }
  .dash-victory-mark {
    font-size: 42px;
    min-width: 48px;
  }
  .dash-victory-title {
    font-size: 20px;
  }
  .dash-victory-message {
    font-size: 14px;
  }
}

/* .dash-hero-cuisinees* retirées 2026-05-18 — KPI cuisinés déplacé
   vers tab Ma semaine (.dash-week-kpi) en PR #105. Audit pass 3
   cleanup. */

/* ── Dash week KPIs : récap hebdo dans tab "Ma semaine"
   (ancien dash-hero-kpi, déplacé du hero 2026-05-18 — audit
   /critique P0 "goulot cognitif"). Chaque KPI = chiffre + label +
   sous-caption inline (recognition over recall — pas de info-pop
   "i" caché). Style éditorial sobre. ─────────────────────────── */
.dash-week-kpis {
  display: flex;
  flex-direction: column;
  gap: 16px;
  margin: 0 0 28px;
  padding: 18px 20px;
  background: var(--accent-tint, oklch(0.59 0.16 143 / 0.06));
  border: 1px solid oklch(0.59 0.16 143 / 0.15);
  border-radius: 14px;
}
.dash-week-kpi {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.dash-week-kpi-main {
  display: flex;
  align-items: baseline;
  gap: 12px;
  flex-wrap: wrap;
}
.dash-week-kpi-value {
  font-family: var(--font-display, "Young Serif", Georgia, serif);
  font-size: 26px;
  color: var(--brand-dark);
  font-variant-numeric: tabular-nums;
  line-height: 1;
  letter-spacing: -0.01em;
  flex-shrink: 0;
}
.dash-week-kpi-total {
  font-size: 18px;
  color: var(--ink-muted);
  margin-left: 2px;
}
.dash-week-kpi-label {
  font-size: 14px;
  color: var(--ink-soft);
  line-height: 1.4;
}
.dash-week-kpi-caption {
  font-size: 12.5px;
  color: var(--ink-muted);
  line-height: 1.45;
  font-style: italic;
}
.dash-week-kpi-caption em {
  font-style: normal;
  color: var(--brand-dark);
  font-weight: 600;
  letter-spacing: 0.005em;
}
@media (max-width: 640px) {
  .dash-week-kpis {
    padding: 14px 16px;
    gap: 14px;
  }
  .dash-week-kpi-value {
    font-size: 22px;
  }
  .dash-week-kpi-label {
    font-size: 13.5px;
  }
  .dash-week-kpi-caption {
    font-size: 12px;
  }
}

/* ── Hero Fantôme inline (re-introduit 2026-05-18 audit re-/critique) :
   le hero était devenu trop vide après déplacement des KPI vers tab.
   Une ligne sobre, pas une card, sous la ligne budget. ─────────── */
.dash-hero-fantome-inline {
  margin: 10px 0 0;
  font-size: 14.5px;
  line-height: 1.5;
  color: var(--ink-soft);
}
.dash-hero-fantome-inline strong {
  font-family: var(--font-display, "Young Serif", Georgia, serif);
  font-size: 18px;
  color: var(--brand-dark);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.005em;
  margin-right: 2px;
}
.dash-hero-fantome-inline-caption {
  display: block;
  font-size: 12.5px;
  color: var(--ink-muted);
  font-style: italic;
  margin-top: 2px;
}
/* Day-1 placeholder variant : caption seule sans chiffre. Garde le
   rhythm visuel du hero sans paraître vide. */
.dash-hero-fantome-inline--empty {
  margin-top: 12px;
}
.dash-hero-fantome-inline--empty .dash-hero-fantome-inline-caption {
  font-size: 13.5px;
  color: var(--ink-soft);
  margin-top: 0;
  line-height: 1.5;
}

/* ── Re-planifier link (audit /critique P1 Error recovery) : porte
   de sortie inline après dépassement budget. Pas un bouton brutal,
   un lien doux Young Serif italique. ─────────────────────────── */
.dash-hero-replan-link {
  display: inline-flex;
  align-items: center;
  margin-top: 10px;
  font-family: var(--font-display, "Young Serif", Georgia, serif);
  font-style: italic;
  font-size: 14.5px;
  color: var(--brand-dark);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
  transition: color 0.18s ease;
  min-height: 44px;
  min-width: 44px;
  padding: 8px 4px;
}
.dash-hero-replan-link:hover,
.dash-hero-replan-link:focus-visible {
  color: var(--brand);
  text-decoration-thickness: 1.5px;
}

/* ── Help line (audit /critique P1 Help & doc) : ligne discrète fin
   de dashboard, voix grand-maman, hit area généreuse 44px. ───── */
.dash-help-line {
  max-width: var(--max-w, 1200px);
  margin: 48px auto 24px;
  padding: 20px 24px;
  text-align: center;
  font-size: 14px;
  color: var(--ink-soft);
  line-height: 1.6;
  border-top: 1px solid var(--border, oklch(0.85 0.012 90));
}
.dash-help-line a {
  color: var(--brand-dark);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
  padding: 12px 8px;
  display: inline-block;
  min-height: 44px;
  min-width: 44px;
  line-height: 1.4;
  font-weight: 500;
}
.dash-help-line a:hover,
.dash-help-line a:focus-visible {
  color: var(--brand);
  text-decoration-thickness: 1.5px;
}
@media (max-width: 640px) {
  .dash-help-line {
    margin: 36px auto 18px;
    padding: 18px 18px;
    font-size: 13.5px;
  }
}

/* ─────────────────────────────────────────────────────────────
   Admin polish (Phase 7 — 2026-05-11)
   Avant : tables bland Bootstrap, zéro alternance, zéro hover.
   Maintenant : alternance lignes paper-soft, hover accent-tint,
   tabular nums.
   FIX 2026-05-16 : le box-shadow .dash-section global créait une
   « carré » visible autour de TOUTES les sections du dashboard
   user (pas juste admin — c'était un scope leak). Retiré entièrement.
   L'admin survit sans ombre, et le dashboard user retrouve son look
   native iOS app feel (background différentié, pas de framing).
   ───────────────────────────────────────────────────────────── */
.dash-section .dash-section-body table tbody tr {
  transition: background-color 0.15s ease-out;
}
.dash-section .dash-section-body table tbody tr:nth-child(even) {
  background: color-mix(in oklch, var(--paper-soft) 50%, transparent);
}
@media (hover: hover) and (pointer: fine) {
  .dash-section .dash-section-body table tbody tr:hover {
    background: var(--accent-tint);
  }
}
.dash-section .dash-section-body table th {
  background: var(--paper-soft);
  color: var(--ink-muted);
  font-weight: 700;
  padding: 12px 10px !important;
}
.dash-section .dash-section-body table td {
  padding: 12px 10px !important;
  font-variant-numeric: tabular-nums;
}
.dash-stats {
  gap: 0;
}
.dash-stat {
  position: relative;
}
.dash-stat::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 2px;
  background: var(--brand);
  opacity: 0;
  transition: opacity 0.2s;
}
@media (hover: hover) and (pointer: fine) {
  .dash-stat:hover::before {
    opacity: 0.55;
  }
}
.dash-stat-value {
  color: var(--brand-dark);
}

/* ─────────────────────────────────────────────────────────────
   Profil refonte (Décision 12 — 2026-05-11)
   Voix grand-maman, inline styles extraits en classes responsive.
   .profil-grid : 2 colonnes desktop / 1 colonne mobile.
   ───────────────────────────────────────────────────────────── */
.profil-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
  margin-bottom: 14px;
}
@media (max-width: 900px) {
  .profil-grid {
    grid-template-columns: 1fr;
  }
}

.profil-freq-row {
  display: flex;
  align-items: center;
  gap: 10px;
}
.profil-freq-label {
  text-transform: none;
  letter-spacing: 0;
  font-size: 13px;
  margin: 0;
}
.profil-freq-select {
  font-size: 14px;
  padding: 6px 10px;
  border-radius: 8px;
  border: 1px solid var(--border);
  background: var(--paper-sheet);
}

.profil-cp-input {
  text-transform: uppercase;
}
.profil-ville-confirm {
  font-size: 12px;
  color: var(--brand-dark);
  margin-top: 4px;
  font-weight: 600;
  letter-spacing: -0.005em;
}
.profil-ville-hint {
  font-size: 11px;
  color: var(--ink-muted);
  margin-top: 4px;
}

.profil-fieldset {
  border: none;
  padding: 0;
  margin: 0;
}
.profil-legend {
  padding: 0;
  margin-bottom: 8px;
}
.profil-radio-row {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}
.profil-ptag {
  flex: 1;
  min-width: 140px;
  text-align: center;
  padding: 10px 12px;
}
.profil-radio-input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
  /* Replaces inline display:none. A11y : the input garde le focus
     keyboard tab. CSP-safe (pas d'inline style). */
}
.profil-radio-ico {
  font-size: 20px;
  margin-bottom: 4px;
  line-height: 1;
}
.profil-radio-label {
  font-size: 12px;
  font-weight: 700;
}
.profil-radio-desc {
  font-size: 10px;
  color: var(--ink-muted);
  margin-top: 2px;
}

.profil-exclus-input {
  font-size: 14px;
}
.profil-exclus-hint {
  font-size: 11px;
  color: var(--ink-muted);
  margin-top: 4px;
}

.profil-membres-card {
  margin-bottom: 14px;
}
.membre-avatar {
  font-size: 18px;
  line-height: 1;
}
.membre-tel {
  font-size: 12px;
  color: var(--ink-muted);
}
.membre-supprimer {
  display: inline;
  margin-left: auto;
}
.membre-supprimer-btn {
  background: none;
  border: none;
  color: var(--danger);
  cursor: pointer;
  font-size: 12px;
  padding: 6px 10px;
  text-decoration: underline;
  text-underline-offset: 2px;
}
@media (hover: hover) and (pointer: fine) {
  .membre-supprimer-btn:hover {
    color: var(--ink);
  }
}
.membre-prefs-input {
  font-size: 12px;
  flex: 1;
}
.membre-prefs-btn {
  font-size: 12px;
  padding: 8px 14px;
}

.profil-ajouter-row {
  display: flex;
  gap: 8px;
  margin-top: 12px;
  flex-wrap: wrap;
}
.profil-ajouter-input {
  flex: 1;
  min-width: 140px;
}

.profil-pwd-card {
  margin-bottom: 14px;
}
.profil-pwd-hint {
  font-size: 11px;
  color: var(--ink-muted);
}

/* ════════════════════════════════════════════════════════════════════
   Sémantique extraite du sweep /audit (P2) — classes réutilisables pour
   les vues /rapport-finances et /detective-prix qui accumulaient des
   inline styles. Pattern projet : classes sémantiques (.rap-X / .det-X)
   plutôt qu'utility-first Tailwind-style — respecte CLAUDE.md « vanilla
   CSS, pas de Tailwind ».
   ════════════════════════════════════════════════════════════════════ */

/* Rapport-finances — composants */
.rap-eyebrow-sm {
  font-size: 11px;
  color: var(--ink-muted);
  text-transform: uppercase;
  letter-spacing: 1px;
}
.rap-eyebrow-md {
  font-size: 12px;
  color: var(--ink-muted);
  text-transform: uppercase;
  letter-spacing: 1px;
}
.rap-stat-num {
  font-family: var(--font-display);
  font-size: 24px;
}
.rap-stat-num-lg {
  font-family: var(--font-display);
  font-size: 42px;
  color: var(--brand-dark);
}
.rap-stat-num-xl {
  font-family: var(--font-display);
  font-size: 48px;
  color: var(--brand-dark);
  margin: 8px 0;
}
.rap-row-sep {
  display: flex;
  justify-content: space-between;
  padding: 8px 0;
  border-bottom: 1px solid var(--border);
}
.rap-row-sep--md {
  padding: 10px 0;
}
.rap-text-soft {
  font-size: 13px;
  color: var(--ink-soft);
}
.rap-text-muted {
  font-size: 12px;
  color: var(--ink-muted);
}
.rap-card--accent {
  background: var(--accent-tint);
  border-color: var(--brand);
}
.rap-mt-md {
  margin-top: 14px;
}

/* Detective-prix — composants */
.det-eyebrow-md {
  font-size: 12px;
  color: var(--ink-muted);
  text-transform: uppercase;
  letter-spacing: 1px;
}
.det-row-sep {
  padding: 10px 0;
  border-bottom: 1px solid var(--border);
}
.det-row-sep--lg {
  padding: 12px 0;
  border-bottom: 1px solid var(--border);
}
.det-row-sep--inline {
  display: flex;
  justify-content: space-between;
  padding: 8px 0;
  border-bottom: 1px solid var(--border);
  font-size: 13px;
}
.det-text-soft {
  font-size: 13px;
  color: var(--ink-soft);
}
.det-text-muted {
  font-size: 12px;
  color: var(--ink-muted);
}
.det-text-soft-mt {
  font-size: 13px;
  color: var(--ink-soft);
  margin-top: 6px;
}
.det-num-danger {
  font-family: var(--font-display);
  font-size: 34px;
  color: var(--danger);
}
.det-bold-danger {
  font-weight: 700;
  color: var(--danger);
}
.det-card--danger {
  margin-bottom: 14px;
  border-color: var(--danger);
}
.det-mt-md {
  margin-top: 14px;
}
.det-bold {
  font-weight: 600;
}
.det-muted {
  color: var(--ink-muted);
}

/* ════════════════════════════════════════════════════════════════════
   Ambient hint — pulse subtil sur élément clé pour first-timer
   Pattern : 3 pulses sur 6 sec, puis disparait. Pas de modal, pas de
   tour intrusif. Juste un nudge visuel discret pour ancrer l'attention
   sur le Budget Fantôme + le composer Assistant. Aria-quiet (pas de
   live region) car purely visual hint, pas critique.
   ════════════════════════════════════════════════════════════════════ */
@keyframes ambient-hint-pulse {
  0%, 100% {
    box-shadow: 0 0 0 0 oklch(0.59 0.16 143 / 0.35);
  }
  50% {
    box-shadow: 0 0 0 14px oklch(0.59 0.16 143 / 0);
  }
}
.ambient-hint {
  animation: ambient-hint-pulse 2s ease-in-out 3 0.8s;
  /* will-change:box-shadow pour eviter layout thrash sur les 3 cycles */
  will-change: box-shadow;
  border-radius: inherit;
}
@media (prefers-reduced-motion: reduce) {
  .ambient-hint {
    animation: none;
  }
}

/* ── Dislikes UX (aliments évités structurés) — 2026-05-23 ────────
   Page /profil/aliments-evites. Remplace les champs text libres legacy
   par une UI claire : groupe par membre famille, autocomplete, toggle
   intensité (jamais/parfois/trace), contexte optionnel.
   ────────────────────────────────────────────────────────────── */
.dislikes-group {
  background: var(--paper-sheet);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 22px;
  margin-bottom: 22px;
}
.dislikes-group-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 16px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--border);
}
.dislikes-group-title {
  font-family: var(--font-display, "Young Serif", Georgia, serif);
  font-weight: 400;
  font-size: 22px;
  color: var(--ink);
  margin: 0;
  letter-spacing: -0.01em;
}
.dislikes-group-count {
  font-size: 13px;
  color: var(--ink-muted);
  font-variant-numeric: tabular-nums;
}
.dislikes-empty {
  font-size: 14px;
  color: var(--ink-muted);
  font-style: italic;
  margin: 0 0 16px;
}
.dislikes-list {
  list-style: none;
  padding: 0;
  margin: 0 0 18px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.dislikes-item {
  position: relative;
  padding: 12px 14px;
  background: var(--paper);
  border: 1px solid var(--border);
  border-radius: 10px;
}
.dislikes-item-main {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
}
.dislikes-item-aliment {
  font-size: 15px;
  font-weight: 600;
  color: var(--ink);
}
.dislikes-item-intensite {
  font-size: 12.5px;
  font-weight: 500;
  padding: 3px 10px;
  border-radius: 999px;
  background: var(--accent-tint, oklch(0.59 0.16 143 / 0.1));
  color: var(--brand-dark, var(--brand));
}
.dislikes-item--parfois_ok .dislikes-item-intensite {
  background: var(--badge-warn-bg);
  color: var(--badge-warn-ink);
}
.dislikes-item--trace_ok .dislikes-item-intensite {
  background: var(--badge-neutral-bg);
  color: var(--badge-neutral-ink);
}
.dislikes-item-note {
  font-size: 13px;
  color: var(--ink-soft);
  margin-top: 4px;
  font-style: italic;
}
.dislikes-item-form {
  margin-top: 8px;
  text-align: right;
}
.dislikes-item-remove {
  background: transparent;
  border: 0;
  padding: 10px 12px;
  min-height: 44px;
  font-size: 13px;
  color: var(--ink-muted);
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 3px;
  border-radius: 6px;
}
.dislikes-item-remove:hover,
.dislikes-item-remove:focus-visible {
  color: var(--danger);
  background: var(--danger-tint);
}
.dislikes-item-remove:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
}

.dislikes-add-form {
  padding-top: 16px;
  border-top: 1px dashed var(--border);
}
.dislikes-add-row {
  display: grid;
  grid-template-columns: 2fr 1fr;
  gap: 14px;
  margin-bottom: 14px;
}
@media (max-width: 600px) {
  .dislikes-add-row {
    grid-template-columns: 1fr;
  }
}
.dislikes-add-field {
  display: flex;
  flex-direction: column;
}
.dislikes-add-field--full {
  margin-bottom: 14px;
}
.dislikes-add-label {
  font-size: 13px;
  font-weight: 600;
  color: var(--ink);
  margin-bottom: 6px;
}
.dislikes-add-hint {
  display: block;
  font-weight: 400;
  font-size: 12px;
  color: var(--ink-muted);
  font-style: italic;
  margin-top: 2px;
}
.dislikes-add-input,
.dislikes-add-select {
  padding: 11px 14px;
  min-height: 44px;
  font-size: 15px;
  font-family: inherit;
  background: var(--paper);
  border: 1px solid var(--border);
  border-radius: 10px;
  color: var(--ink);
}
.dislikes-add-input:focus,
.dislikes-add-select:focus {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
}

.dislikes-footer {
  margin-top: 32px;
  padding: 18px 20px;
  background: var(--accent-tint, oklch(0.59 0.16 143 / 0.06));
  border-radius: 12px;
  font-size: 13.5px;
  color: var(--ink-soft);
  line-height: 1.6;
}
.dislikes-footer a {
  color: var(--brand-dark, var(--brand));
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* ── Lunch École (Sprint 2 pivot 2026-05-23) ───────────────────
   Daily touch point lun-ven. Calendar 5 jours, cards par enfant,
   réutilisation visible des restes souper. Reste éditorial magazine
   (pas SaaS dashboard). */
.lunch-onboarding {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 18px;
  margin: 24px 0 32px;
}
@media (max-width: 768px) {
  .lunch-onboarding { grid-template-columns: 1fr; }
}
.lunch-onb-feature {
  background: var(--paper-sheet);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 22px;
}
.lunch-onb-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  margin-bottom: 12px;
  border-radius: 10px;
  background: var(--accent-tint, oklch(0.59 0.16 143 / 0.10));
  color: var(--brand-dark, var(--brand));
}
.lunch-onb-icon svg {
  display: block;
}
.lunch-onb-feature h3 {
  font-family: var(--font-display, "Young Serif", Georgia, serif);
  font-weight: 400;
  font-size: 18px;
  color: var(--ink);
  margin: 0 0 6px;
}
.lunch-onb-feature p {
  font-size: 14px;
  color: var(--ink-soft);
  line-height: 1.55;
  margin: 0;
}
.lunch-onb-cta {
  text-align: center;
  margin: 32px 0;
}
.lunch-onb-note {
  font-size: 12.5px;
  color: var(--ink-muted);
  margin-top: 14px;
  font-style: italic;
}

.lunch-week-nav {
  font-size: 13px;
  color: var(--brand-dark, var(--brand));
  text-decoration: underline;
  text-underline-offset: 3px;
}
.lunch-week-current {
  font-size: 13.5px;
  color: var(--ink-soft);
  font-weight: 600;
  text-align: center;
}

.lunch-empty {
  background: var(--accent-tint, oklch(0.59 0.16 143 / 0.06));
  border: 1px solid color-mix(in oklch, var(--brand) 20%, var(--border));
  border-radius: 14px;
  padding: 32px;
  text-align: center;
  margin: 24px 0;
}
.lunch-empty-text {
  font-size: 15.5px;
  color: var(--ink-soft);
  line-height: 1.6;
  margin: 0 0 20px;
  max-width: 60ch;
  margin-left: auto;
  margin-right: auto;
}

.lunch-actions {
  text-align: right;
  margin-bottom: 18px;
}

.lunch-enfant-section {
  margin-bottom: 36px;
}
.lunch-enfant-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: 14px;
  padding-bottom: 10px;
  border-bottom: 1px solid var(--border);
}
.lunch-enfant-title {
  font-family: var(--font-display, "Young Serif", Georgia, serif);
  font-weight: 400;
  font-size: 24px;
  color: var(--ink);
  margin: 0;
  letter-spacing: -0.01em;
}
.lunch-enfant-count {
  font-size: 13px;
  color: var(--ink-muted);
  font-variant-numeric: tabular-nums;
}

.lunch-calendar {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 12px;
}
@media (max-width: 1024px) {
  .lunch-calendar { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 540px) {
  .lunch-calendar { grid-template-columns: 1fr; }
}

.lunch-day {
  background: var(--paper-sheet);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 14px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  position: relative;
}
.lunch-day.is-fait {
  background: var(--accent-tint, oklch(0.59 0.16 143 / 0.05));
  border-color: color-mix(in oklch, var(--brand) 25%, var(--border));
}
.lunch-day-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--border);
}
.lunch-day-name {
  font-family: var(--font-display, "Young Serif", Georgia, serif);
  font-weight: 400;
  font-size: 16px;
  color: var(--ink);
}
.lunch-day-date {
  font-size: 12px;
  color: var(--ink-muted);
  font-variant-numeric: tabular-nums;
}
.lunch-day-content {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.lunch-item {
  font-size: 13.5px;
  line-height: 1.5;
}
.lunch-item-label {
  display: inline-block;
  font-size: 10.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--ink-muted);
  margin-right: 6px;
}
.lunch-item-text {
  color: var(--ink);
}
.lunch-item--principal .lunch-item-text {
  font-weight: 600;
}
.lunch-day-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 12px;
  padding-top: 8px;
  border-top: 1px dashed var(--border);
  font-size: 11.5px;
  color: var(--ink-muted);
}
.lunch-day-cout {
  font-weight: 600;
  color: var(--brand-dark, var(--brand));
  font-variant-numeric: tabular-nums;
}
.lunch-day-reuse {
  color: var(--brand-dark, var(--brand));
}
.lunch-day-notes {
  font-size: 12px;
  font-style: italic;
  color: var(--ink-soft);
  padding-top: 6px;
}
.lunch-day-actions {
  margin-top: auto;
  padding-top: 8px;
}
.lunch-day-toggle {
  width: 100%;
  padding: 10px;
  min-height: 44px;
  font-size: 13px;
  font-weight: 600;
  background: var(--paper);
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--ink-soft);
  cursor: pointer;
}
.lunch-day-toggle.is-on {
  background: var(--brand);
  color: var(--paper);
  border-color: var(--brand);
}
.lunch-day-toggle:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
}
.lunch-day-empty {
  font-size: 13px;
  color: var(--ink-muted);
  font-style: italic;
  padding: 20px 0;
  text-align: center;
}

.lunch-back-link {
  font-size: 13px;
  color: var(--brand-dark, var(--brand));
  text-decoration: underline;
  text-underline-offset: 3px;
}
.lunch-detail-card {
  background: var(--paper-sheet);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 24px;
  margin-bottom: 18px;
}
.lunch-detail-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: 16px;
}
.lunch-detail-head h2 {
  font-family: var(--font-display, "Young Serif", Georgia, serif);
  font-weight: 400;
  font-size: 22px;
  margin: 0;
}
.lunch-detail-cout {
  font-size: 15px;
  font-weight: 600;
  color: var(--brand-dark, var(--brand));
  font-variant-numeric: tabular-nums;
}
.lunch-detail-content {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-bottom: 16px;
}
.lunch-detail-item {
  display: flex;
  gap: 12px;
  padding: 10px 12px;
  background: var(--paper);
  border-radius: 8px;
}
.lunch-detail-label {
  flex: 0 0 100px;
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--ink-muted);
}
.lunch-detail-text {
  font-size: 15px;
  color: var(--ink);
}
.lunch-detail-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  padding: 12px 0;
  font-size: 13.5px;
  color: var(--ink-soft);
  border-top: 1px dashed var(--border);
  border-bottom: 1px dashed var(--border);
}
.lunch-detail-notes {
  font-size: 13.5px;
  font-style: italic;
  color: var(--ink-soft);
  margin: 14px 0;
}

/* ── Recette « Adapté pour toi » — annotation manuscrite éditoriale
   (sprint final dislikes loop, /impeccable 2026-05-28).
   La grand-maman montre sa pensée. Pas une badge SaaS — une ligne
   typographique au crayon vert, cohérente avec receipt-note-text
   (signature visuelle L'Économe).
   Tokens theme-aware (badges déjà tokenisés en pass précédent). */
.recette-adapte {
  display: flex;
  align-items: flex-start;
  flex-wrap: wrap;
  gap: 8px;
  margin: 12px 0 6px;
  padding: 0;
  font-size: 14.5px;
  line-height: 1.45;
  letter-spacing: -0.005em;
  /* Pas de fond, pas de bordure — ligne typographique pure */
}
.recette-adapte-pen {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  width: 18px;
  height: 18px;
  margin-top: 1px;
  color: var(--brand-dark, var(--brand));
  transform: rotate(-6deg);
  transform-origin: 50% 60%;
}
.recette-adapte-text {
  font-family: var(--font-display, "Young Serif", Georgia, serif);
  font-style: italic;
  font-weight: 400;
  color: var(--brand-dark, var(--brand));
}
/* « précisé » + « évité » partagent la couleur brand-dark — pas
   besoin de surcharger, mais on garde les sélecteurs pour future
   personnalisation et lisibilité du DOM. */
.recette-adapte--precise .recette-adapte-pen,
.recette-adapte--precise .recette-adapte-text,
.recette-adapte--evite .recette-adapte-pen,
.recette-adapte--evite .recette-adapte-text {
  color: var(--brand-dark, var(--brand));
}
/* Variante « alerte » — exception rare, recette mal-matchée.
   Couleur danger sobre, pas alarmiste. Le ton reste éditorial. */
.recette-adapte--alerte .recette-adapte-pen,
.recette-adapte--alerte .recette-adapte-text {
  color: var(--danger);
}

/* CTA « Changer cette recette » — livré uniquement quand l'alerte
   se déclenche. La voix promet l'action, le bouton la livre (fix
   critique sévère 2026-06-02 : ne plus dire « on peut la changer »
   sans bouton). Style ghost danger, hit area 44px (WCAG AAA). */
.recette-adapte-form {
  margin: 0;
  display: inline-flex;
  flex-basis: 100%;
}
.recette-adapte-cta {
  appearance: none;
  background: transparent;
  border: 1px solid var(--danger);
  color: var(--danger);
  font-family: var(--font-sans, "Commissioner", system-ui, sans-serif);
  font-size: 13.5px;
  font-weight: 500;
  letter-spacing: -0.005em;
  padding: 10px 14px;
  min-height: 44px;
  border-radius: 8px;
  cursor: pointer;
  transition: background-color 120ms ease-out, color 120ms ease-out;
}
.recette-adapte-cta:hover,
.recette-adapte-cta:focus-visible {
  background: var(--danger);
  color: var(--paper);
}
.recette-adapte-cta:focus-visible {
  outline: 2px solid var(--danger);
  outline-offset: 2px;
}

/* Mode Grand-Maman : Claudette 67 lit son menu avec lunettes —
   le body.mode-grand-maman est à 17px, donc l'annotation doit être
   ≥ 18.5px (avant on tombait à 16.5px, plus PETIT que le body, fail
   AAA — fix critique sévère 2026-06-02). */
body.mode-grand-maman .recette-adapte {
  font-size: 18.5px;
  line-height: 1.5;
}
body.mode-grand-maman .recette-adapte-pen {
  width: 24px;
  height: 24px;
}
body.mode-grand-maman .recette-adapte-pen svg {
  width: 20px;
  height: 22px;
}
body.mode-grand-maman .recette-adapte-cta {
  font-size: 15.5px;
  padding: 12px 18px;
  min-height: 48px;
}

/* ============================================================
   @CONTAINER QUERIES — modernisation responsive component-level
   (audit sévère 2026-06-04). Avant : 0 @container, tout en
   @media viewport. Maintenant : 2 surfaces où le composant
   doit s'adapter à SON conteneur, pas au viewport.

   Pattern : on déclare container-type:inline-size sur le parent
   sémantique du composant, on nomme le contexte, on écrit des
   queries qui réagissent à la largeur DISPONIBLE (utile pour
   sidebar / split views / future iframe embeds).
   ============================================================ */

/* ── 1. Recipe card : s'adapte à son colonne dans .menu-spread.
   Sur desktop large, on a 1.6fr+1fr ; sur écran intermédiaire
   ou si l'user pousse le sidebar, la colonne recette devient
   étroite. @container reagit AU CONTAINER, pas au viewport,
   donc l'UI se reflow proprement. */
.menu-recipe {
  container-type: inline-size;
  container-name: recipe;
}
@container recipe (max-width: 520px) {
  /* Titre + meta plus compacts quand la colonne recette est étroite */
  .menu-recipe-title {
    font-size: clamp(22px, 6cqi, 32px);
    line-height: 1.15;
  }
  .menu-recipe-meta {
    grid-template-columns: 1fr 1fr;
  }
  .menu-recipe-meta > div:last-child {
    grid-column: 1 / -1;
  }
}

/* ── 2. Dashboard quick tiles : 4-col devient 2-col puis 1-col
   selon la largeur DU GRID, pas du viewport. Bénéfice : si on
   imbrique un jour le dashboard dans un widget plus étroit
   (Forfait Réception preview, espace client onglets), les tiles
   s'adaptent sans toucher au layout parent. */
.dash-quick {
  container-type: inline-size;
  container-name: quick;
}
@container quick (max-width: 640px) {
  .dash-quick {
    grid-template-columns: repeat(2, 1fr);
  }
}
@container quick (max-width: 360px) {
  .dash-quick {
    grid-template-columns: 1fr;
  }
}
