/* Kale app styles, extraits de mockups/kale-home-v2.html v2.0
 * Brand: Whoop / Systèmes territory, sans-serif + mono, cool dark / off-white auto-switch
 */

/* Self-hosted fonts (latin subset, suffit pour fr) */
@font-face {
  font-family: "Instrument Sans";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/static/fonts/instrument-sans-400-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Instrument Sans";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("/static/fonts/instrument-sans-500-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "DM Mono";
  font-style: normal;
  font-weight: 300;
  font-display: swap;
  src: url("/static/fonts/dm-mono-300-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "DM Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/static/fonts/dm-mono-400-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "DM Mono";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("/static/fonts/dm-mono-500-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
  /* Dark mode (default), cool neutral.
     Sprint 34 (feedback PE "on n'y voit rien") : pivot lisibilité. Surfaces
     beaucoup plus claires, contraste massif tuile/bg. PE acceptait perdre la
     DNA Whoop pour gagner en lisibilité, je pousse les surfaces de #181A20
     à #2A2D35 (un cran "gris moyen" au lieu de "presque noir"). Le contraste
     vs bg #0A0B0E passe de ~14pt à ~28pt luminosité. Séparation tuile
     visible au premier glance.
     Texte secondaire monté en luminosité pour lisibilité aussi. */
  --bg: #0A0B0E;
  --surface: #2A2D35;
  --surface-2: #34373F;
  --hairline: #44474F;
  --hairline-soft: #3A3D44;
  --text: #F2F3F5;
  --text-2: #B0B4BB;
  --text-3: #82868D;
  --text-4: #6B6E76;
  --accent: #7DB055;
  --accent-soft: rgba(125, 176, 85, 0.18);
  --marine: #4A6E96;
  --marine-soft: rgba(74, 110, 150, 0.18);
  --rust: #D24528;
  --rust-soft: rgba(210, 69, 40, 0.18);
  --ochre: #E0A33B;
  --ochre-soft: rgba(224, 163, 59, 0.18);
  --sage: #7DB055;
  --sage-soft: rgba(125, 176, 85, 0.18);
  --sans: "Instrument Sans", -apple-system, BlinkMacSystemFont, "Helvetica Neue", sans-serif;
  --mono: "DM Mono", "SF Mono", Menlo, monospace;
  --ease: cubic-bezier(0.22, 1, 0.36, 1);

  /* Radius scale unifiée (sprint 10) - 4 valeurs canoniques */
  --r-sm: 6px;     /* inputs, small chips, buttons compacts */
  --r-md: 10px;    /* cards, dialogs, larger buttons */
  --r-lg: 14px;    /* hero cards, modal containers */
  --r-pill: 999px; /* pills, tags */

  /* Z-index scale (sprint 21, formalisée suite audit ui-ux-pro-max).
     Pas de valeurs arbitraires type z-[9999], on respecte l'échelle. */
  --z-fab: 12;
  --z-toast: 90;
  --z-action-sheet: 100;
  --z-dialog: 150;        /* indicatif, dialog natif gère son ::backdrop */
  --z-plate-overlay: 200;
  --z-ptr: 999;

  /* Font sizes scale (sprint 10) */
  --fs-3xs: 9px;
  --fs-2xs: 10px;
  --fs-xs: 11px;
  --fs-sm: 12px;
  --fs-base: 14px;
  --fs-md: 16px;
  --fs-lg: 19px;
  --fs-xl: 24px;
  --fs-2xl: 32px;
  --fs-3xl: 48px;
}

/* ============== LIGHT MODE (auto via system preference) ==============
   Off-white pur, Whoop-aligned. Pas de warmth, pas de papier.
   Accent vert signature unique, macros en heritage pour identification.
*/
@media (prefers-color-scheme: light) {
  :root {
    --bg: #FAFAFA;
    --surface: #F1F2F4;
    --surface-2: #E9EAEC;
    --hairline: #CED1D5;
    --hairline-soft: #E2E4E7;
    --text: #0A0B0E;
    --text-2: #3D3F45;
    --text-3: #6B6E76;
    --text-4: #767A82;
    --accent: #5E9438;
    --accent-soft: rgba(94, 148, 56, 0.12);
    --marine: #2B3A4F;
    --marine-soft: rgba(43, 58, 79, 0.10);
    --rust: #C13B22;
    --rust-soft: rgba(193, 59, 34, 0.14);
    --ochre: #B07520;
    --ochre-soft: rgba(176, 117, 32, 0.14);
    --sage: #5E9438;
    --sage-soft: rgba(94, 148, 56, 0.14);
  }
}

* { box-sizing: border-box; margin: 0; padding: 0; }
html, body { background: var(--bg); }
body {
  font-family: var(--sans);
  color: var(--text);
  font-size: 15px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
  /* Sprint 21 (audit ui-ux-pro-max) : évite le double-bounce overscroll
     d'iOS Safari quand on a notre propre pull-to-refresh. Le contenu
     scroll normalement, mais l'over-pull au-delà des limites n'enclenche
     pas le "rubber band" natif qui interférerait avec notre PTR custom. */
  overscroll-behavior-y: contain;

  /* App: mobile-first (480px), élargi sur tablette/desktop (720px puis 960px).
     Sprint 32 : padding lateral réduit 28px -> 16px parce que les tuiles cards
     ont leur propre padding 18px interne. Sinon trop de respiration laterale
     (= contenu rétréci). */
  max-width: 480px;
  margin: 0 auto;
  padding: 14px 16px 100px;
  min-height: 100vh;
  position: relative;
}
@media (min-width: 768px) {
  body { max-width: 720px; padding: 24px 40px 120px; font-size: 16px; }
}
@media (min-width: 1100px) {
  body { max-width: 960px; padding: 32px 56px 140px; }
}

.num { font-feature-settings: "tnum" 1, "lnum" 1; font-variant-numeric: tabular-nums lining-nums; }
.smcaps { letter-spacing: 0.18em; text-transform: uppercase; font-weight: 500; }
.mono { font-family: var(--mono); }

/* Wordmark in app */
.wordmark {
  display: flex;
  align-items: baseline;
  gap: 4px;
  font-family: var(--sans);
  font-size: 22px;
  line-height: 1;
  color: var(--text);
  margin-bottom: 40px;
}
.wordmark .dot {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--marine);
  display: inline-block;
  transform: translateY(-2px);
}

/* Day masthead */
.day {
  margin-bottom: 36px;
}
.day .name {
  font-family: var(--sans);
  font-size: 40px;
  line-height: 1;
  letter-spacing: -0.015em;
  color: var(--text-2);
  margin-bottom: 4px;
}
.day .meta {
  font-family: var(--mono);
  font-size: 10.5px;
  color: var(--text-3);
  letter-spacing: 0.18em;
  text-transform: uppercase;
}
.day .meta .sep { color: var(--text-4); margin: 0 8px; }

/* Hero number */
.hero-num {
  margin-bottom: 32px;
}
.hero-num .label {
  font-family: var(--mono);
  font-size: 10.5px;
  color: var(--text-3);
  letter-spacing: 0.22em;
  text-transform: uppercase;
  margin-bottom: 8px;
}
.hero-num .value {
  font-family: var(--mono);
  font-weight: 300;
  /* Sprint 19 : clamp pour éviter clip sur iPhone SE / petits écrans.
     Base 92px sur grand écran, descend à 64px sous 360px viewport. */
  font-size: clamp(64px, 22vw, 92px);
  line-height: 1;
  letter-spacing: -0.04em;
  color: var(--text);
  display: flex;
  align-items: baseline;
  gap: 14px;
}
.hero-num .value .unit {
  font-family: var(--sans);
  font-weight: 400;
  font-size: 22px;
  color: var(--text-3);
  letter-spacing: 0;
}
.hero-num .delta {
  margin-top: 8px;
  font-family: var(--mono);
  font-size: 11px;
  color: var(--text-3);
  letter-spacing: 0.06em;
}
.hero-num .delta .pos { color: var(--marine); }

/* Sparkline */
.sparkline-wrap {
  margin-bottom: 40px;
}
.sparkline {
  width: 100%;
  height: 60px;
  display: block;
  color: var(--text);
}
.sparkline .axis-label {
  font-family: var(--mono);
  font-size: 9px;
  fill: var(--text-4);
  letter-spacing: 0.12em;
}

/* Macro rows */
.macros {
  margin-bottom: 44px;
}
.macro-row {
  display: grid;
  grid-template-columns: 18px 1fr 92px;
  align-items: center;
  gap: 14px;
  padding: 14px 0;
  border-bottom: 1px solid var(--hairline-soft);
}
.macro-row:last-child { border-bottom: none; }
.macro-row .key {
  font-family: var(--mono);
  font-size: 13px;
  font-weight: 500;
  color: var(--text-2);
  letter-spacing: 0.04em;
}
.macro-row .bar {
  position: relative;
  height: 5px;
  background: var(--hairline);
  border-radius: 1px;
  overflow: hidden;
}
.macro-row .bar .fill {
  position: absolute;
  inset: 0;
  background: var(--marine);
  width: 0;
  transition: width 1.2s var(--ease) 0.4s;
}
.macro-row[data-macro="P"] .key { color: var(--rust); }
.macro-row[data-macro="P"] .bar .fill { background: var(--rust); }
.macro-row[data-macro="L"] .key { color: var(--ochre); }
.macro-row[data-macro="L"] .bar .fill { background: var(--ochre); }
.macro-row[data-macro="G"] .key { color: var(--sage); }
.macro-row[data-macro="G"] .bar .fill { background: var(--sage); }
.macro-row .bar .goal-mark {
  position: absolute;
  top: -3px;
  bottom: -3px;
  width: 1px;
  left: 100%;
  background: var(--text-3);
}
.delta-sep {
  color: var(--text-4);
  margin: 0 8px;
}
.ghost-btn-link {
  text-decoration: none;
  display: inline-flex;
  align-items: center;
}
.macro-row .stat {
  font-family: var(--mono);
  font-size: 11.5px;
  color: var(--text-2);
  letter-spacing: 0.04em;
  text-align: right;
  font-variant-numeric: tabular-nums;
  line-height: 1.2;
}
.macro-row .stat .goal { color: var(--text-4); }
.macro-row .stat .delta {
  display: block;
  font-size: 9.5px;
  color: var(--text-3);
  letter-spacing: 0.08em;
  margin-top: 2px;
  text-transform: uppercase;
}
.macro-row .stat .delta.up { color: var(--text-2); }

/* Card section: hairline-separated, 3-zone hierarchy (sprint 19).
   Sprint 32 (feedback PE) : refonte séparations cards.
   Avant : hairline borders entre cards, mal lisibles, mou. Pas de séparation
   visuelle nette. PE remontait "on voit pas bien les séparations entre les parties".

   Maintenant : pattern Whoop / Linear. Chaque card = tuile pleine `--surface`
   avec radius `--r-lg`, gap réel `gap: 12px` entre elles. Le contraste tuile/bg
   est immédiatement visible au glance. Plus de hairlines fines.

   Le hero reste sans tuile (=fond bg direct) pour rester le focal point sans
   container qui le rétrécit visuellement. Card-day pareil (contexte temporel
   minimaliste, pas une carte d'info).
*/

.layout-grid {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.card {
  padding: 22px 18px 24px;
  background: var(--surface);
  border-radius: var(--r-lg);
}
/* Day card et hero card : pas de tuile, ils respirent sur le fond directement.
   Le hero kcal est trop puissant pour être enfermé dans une tuile. */
.card-day,
.card-hero {
  background: transparent;
  padding-left: 0;
  padding-right: 0;
}
.card-hero { padding: 6px 0 28px; }
.card-day  { padding: 16px 0 8px; }

/* Card chips : tuile compacte, padding réduit */
.card-chips { padding: 14px 16px 16px; }

/* Card journal : tuile avec padding-top généreux. Sprint 33 : la signature
   barre accent qui était ici (::before) a été migrée dans .section-head::before
   pour homogénéité avec les autres sections. */
.card-journal {
  padding: 24px 18px 26px;
}

/* Card label header, mono small caps.
   Sprint 33 : refonte. Ancienne version avait title + rule + count en flex
   baseline. La rule (ligne hairline entre title et count) était mal lisible
   dans une tuile surface.
   Nouvelle version : segment accent 2px collé au top de la card (signature
   sémantique, identifie chaque section), title + count sur la même ligne en
   dessous. Plus glanceable, plus brand. */
/* Sprint 34 (pivot lisibilité) : section-head refait pour ne plus "crier sans
   dire". Avant : title en mono 10px ALL CAPS letter-spacing 0.24em → illisible
   au glance, vintage operator, mais pas pratique. Maintenant : sans-serif
   16px sentence case, lisible au premier coup d'œil.
   Le marker accent 24px x 3px en haut signifie "voici une section". Couleur
   ajustable par section via .section-head[data-section="..."] (markers
   sectoriels demandés par PE). */
.section-head {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 16px;
  position: relative;
  padding-top: 10px;
}
.section-head::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  width: 24px;
  height: 3px;
  background: var(--accent);
  border-radius: 0 0 3px 3px;
}
/* Markers sectoriels demandés par PE (sprint 34). 4 couleurs total, alignées
   sur la palette diag existante (accent / ochre / marine / rust). Pas 6 hues
   différentes (rainbow slop), mais regroupement sémantique : */
.section-head[data-section="trend"]::before    { background: var(--accent); }
.section-head[data-section="chips"]::before    { background: var(--accent); }
.section-head[data-section="macros"]::before   { background: var(--ochre); }
.section-head[data-section="weight"]::before   { background: var(--marine); }
.section-head[data-section="health"]::before   { background: var(--marine); }
.section-head[data-section="journal"]::before  { background: var(--rust); }

.section-head .title {
  font-family: var(--sans);
  font-size: 16px;
  font-weight: 600;
  color: var(--text);
  letter-spacing: -0.01em;
  line-height: 1.2;
}
.section-head .rule {
  flex: 1;
  height: 1px;
  background: var(--hairline-soft);
  opacity: 0;  /* Sprint 34 : le rule devient inutile avec un title plus gros */
}
.section-head .count {
  font-family: var(--mono);
  font-size: 12px;
  color: var(--text-3);
  letter-spacing: 0.04em;
}

/* Weight tracking card */
.weight-value {
  font-family: var(--mono);
  font-weight: 300;
  font-size: 48px;
  line-height: 1;
  letter-spacing: -0.03em;
  color: var(--text);
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin-bottom: 16px;
}
.weight-value .unit {
  font-size: 14px;
  color: var(--text-3);
  letter-spacing: 0;
  font-weight: 400;
}
.weight-spark {
  width: 100%;
  height: 36px;
  display: block;
  color: var(--text);
}
.weight-spark .axis-label {
  font-family: var(--mono);
  font-size: 9px;
  fill: var(--text-4);
  letter-spacing: 0.12em;
}

/* Journal entries */
.entries {
  margin-bottom: 36px;
}
.entry {
  padding: 18px 0;
  border-bottom: 1px solid var(--hairline-soft);
  display: grid;
  grid-template-columns: 48px 1fr auto;
  gap: 14px;
  align-items: baseline;
}
.entry:last-child { border-bottom: none; }
.entry .time {
  font-family: var(--mono);
  font-size: 11px;
  color: var(--text-3);
  letter-spacing: 0.04em;
  text-align: right;
}
.entry .dish {
  font-family: var(--sans);
  font-size: 19px;
  line-height: 1.35;
  color: var(--text);
  letter-spacing: -0.005em;
  cursor: pointer;
  transition: color 0.12s var(--ease);
}
.entry .dish:hover,
.entry .dish:focus {
  color: var(--accent);
  outline: none;
}
.entry .right {
  text-align: right;
  font-family: var(--mono);
  font-size: 10.5px;
  line-height: 1.4;
  color: var(--text-2);
  cursor: pointer;
  transition: color 0.12s var(--ease);
}
.entry .right:hover,
.entry .right:focus {
  outline: none;
}
.entry .right:hover .kcal,
.entry .right:focus .kcal {
  color: var(--accent);
}
.entry .right .kcal {
  font-size: 14px;
  color: var(--text);
  letter-spacing: 0.02em;
  display: block;
  margin-bottom: 1px;
}
.entry .right .macros {
  color: var(--text-3);
  letter-spacing: 0.06em;
  font-size: 9.5px;
}

/* Empty future slot */
.empty-slot {
  margin: 8px 0 36px;
  padding: 22px;
  border: 1px dashed var(--hairline);
  border-radius: 4px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  cursor: pointer;
  transition: border-color 0.3s var(--ease);
}
.empty-slot:hover { border-color: var(--marine); }
.empty-slot .label {
  font-family: var(--mono);
  font-size: 11px;
  color: var(--text-3);
  letter-spacing: 0.16em;
  text-transform: uppercase;
}
.empty-slot .ghost {
  font-family: var(--mono);
  font-size: 9.5px;
  color: var(--text-4);
  letter-spacing: 0.2em;
  text-transform: uppercase;
}

/* Demain, aged */
.demain { opacity: 0.42; margin-top: 32px; }
.demain .quiet {
  font-family: var(--mono);
  font-size: 10.5px;
  color: var(--text-3);
  margin-top: 10px;
  line-height: 1.6;
  letter-spacing: 0.04em;
}

/* Floating action, voice.
   Was absolute inside .phone, now fixed bottom-right relative to viewport. */
.fab-wrap {
  position: fixed;
  bottom: 24px;
  right: max(20px, calc(50vw - 240px + 20px));
  z-index: var(--z-fab);
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 10px;
}
/* Sprint 19 : .fab-hint supprimé (audit). Un FAB confiant n'a pas besoin
   de se légender. L'icône "+" parle d'elle-même. Hold = haptique + mic = signal. */
.fab-hint { display: none; }

/* Cross-fade icônes FAB : + par défaut, micro pendant recording */
.fab { position: relative; }
.fab .fab-icon-add,
.fab .fab-icon-mic {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  transition: opacity 0.18s var(--ease);
  pointer-events: none;
}
.fab .fab-icon-mic { opacity: 0; }
.fab.recording .fab-icon-add { opacity: 0; }
.fab.recording .fab-icon-mic { opacity: 1; }
.fab {
  width: 64px;
  height: 64px;
  border-radius: 50%;
  background: var(--marine);
  border: 1px solid color-mix(in srgb, var(--marine) 70%, white 6%);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--bg);
  cursor: pointer;
  /* Sprint 19 anti-slop : 1 seule shadow plate, on retire le inset white
     (micro-glassmorphism) et la double-shadow multi-layered. */
  box-shadow: 0 12px 28px -8px rgba(0, 0, 0, 0.55);
  transition: transform 0.18s var(--ease), box-shadow 0.3s var(--ease);
  position: relative;
}
.fab::before {
  content: "";
  position: absolute;
  inset: -4px;
  border-radius: 50%;
  border: 1px solid var(--marine);
  opacity: 0;
  /* Sprint 19 anti-slop (audit) : pas de pulse infini ni de pulse au load.
     L'user voit le FAB en bas à droite, vert, rond — pas besoin de l'annoncer.
     Le halo est gardé comme cible CSS pour les états .recording (qui pulse pendant
     la dictée active, là c'est du feedback fonctionnel pas du décoratif). */
}
.fab.recording::before {
  opacity: 0.6;
  animation: pulse 1.4s var(--ease) infinite;
}
@keyframes pulse {
  0% { transform: scale(0.95); opacity: 0.6; }
  70% { transform: scale(1.22); opacity: 0; }
  100% { transform: scale(1.22); opacity: 0; }
}
.fab:hover { transform: translateY(-2px); }
.fab:active { transform: scale(0.96); }
.fab svg { width: 22px; height: 22px; }

/* ============== STAGGER REVEAL ============== */

.reveal {
  opacity: 0;
  transform: translateY(8px);
  animation: rise 0.8s var(--ease) forwards;
}
@keyframes rise {
  to { opacity: 1; transform: translateY(0); }
}
.delay-1 { animation-delay: 0.05s; }
.delay-2 { animation-delay: 0.18s; }
.delay-3 { animation-delay: 0.32s; }
.delay-4 { animation-delay: 0.46s; }
.delay-5 { animation-delay: 0.6s; }
.delay-6 { animation-delay: 0.74s; }
.delay-7 { animation-delay: 0.88s; }
.delay-8 { animation-delay: 1.02s; }
.delay-9 { animation-delay: 1.16s; }

/* ============== ACCESSIBILITY: REDUCED MOTION ==============
   Respecte la préférence système. Coupe les animations,
   fige les reveals à leur état final, supprime le pulse FAB infini.
*/
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
  .reveal {
    opacity: 1 !important;
    transform: none !important;
  }
  .fab::before {
    display: none;
  }
}

/* ============== ACCESSIBILITY: FOCUS VISIBLE ============== */
*:focus-visible {
  outline: 2px solid var(--marine);
  outline-offset: 2px;
  border-radius: 2px;
}
.fab:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 4px;
}

/* ============== SPRINT 2 ADDITIONS ============== */

/* Wordmark settings cog */
.wordmark { position: relative; }
.wordmark-settings {
  background: transparent;
  border: 0;
  color: var(--text-3);
  margin-left: auto;
  padding: 4px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: color 0.15s var(--ease);
  position: relative;
}
/* Zone touch 44pt iOS HIG sans grossir le visuel */
.wordmark-settings::before {
  content: '';
  position: absolute;
  inset: -14px;
}
.wordmark-settings:hover { color: var(--text); }
.wordmark-settings svg { width: 16px; height: 16px; }

/* Link button (mini text-style action in section-head) */
.link-button {
  background: transparent;
  border: 0;
  font-family: var(--mono);
  font-size: 10px;
  color: var(--accent);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  cursor: pointer;
  padding: 12px 8px;
  position: relative;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
}
.link-button:hover { color: var(--text); }

/* Sprint 33 : hint compact quand <3 mesures, plutôt que chart cassé */
.weight-sparse-hint {
  margin-top: 8px;
  font-family: var(--mono);
  font-size: var(--fs-3xs);
  color: var(--text-3);
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

/* Weight delta inline (next to value au lieu de count) */
.weight-value .delta-aside {
  margin-left: 12px;
  font-family: var(--mono);
  font-size: 10px;
  color: var(--text-3);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  align-self: end;
  margin-bottom: 6px;
}

/* Fresh entry animation (htmx-inserted) */
@keyframes entry-fresh-flash {
  0%   { background: var(--accent-soft); transform: translateY(-4px); opacity: 0; }
  20%  { transform: translateY(0); opacity: 1; }
  100% { background: transparent; }
}
.entry-fresh {
  animation: entry-fresh-flash 1400ms var(--ease) forwards;
  border-radius: 4px;
}

/* ============== DIALOG (capture + settings) ============== */
.dialog {
  border: 1px solid var(--hairline);
  background: var(--surface);
  color: var(--text);
  border-radius: 12px;
  padding: 0;
  max-width: 420px;
  width: calc(100vw - 32px);
  margin: auto;
  box-shadow: 0 24px 80px -16px rgba(0, 0, 0, 0.5);
}
.dialog::backdrop {
  background: rgba(0, 0, 0, 0.5);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}
.dialog-inner {
  padding: 24px 22px 20px;
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.dialog-title {
  font-family: var(--sans);
  font-size: 18px;
  font-weight: 600;
  letter-spacing: -0.015em;
  margin: 0;
}
.dialog-sub {
  font-family: var(--sans);
  font-size: 13px;
  color: var(--text-3);
  margin: -8px 0 4px;
  line-height: 1.45;
}

/* Capture dialog specifics */
.dialog.capture .capture-mode {
  font-family: var(--mono);
  font-size: 10px;
  color: var(--accent);
  letter-spacing: 0.24em;
  text-transform: uppercase;
}
.dialog.capture .capture-state {
  font-family: var(--mono);
  font-size: 11px;
  color: var(--text-3);
  letter-spacing: 0.08em;
}
/* Sprint 18 : capture-waveform retiré (dead CSS, jamais utilisé en HTML). */
.dialog.capture textarea {
  width: 100%;
  background: var(--bg);
  border: 1px solid var(--hairline);
  border-radius: 6px;
  color: var(--text);
  padding: 10px 12px;
  font-family: var(--sans);
  font-size: 15px;
  line-height: 1.4;
  resize: vertical;
  outline: none;
  transition: border-color 0.15s var(--ease);
}
.dialog.capture textarea:focus {
  border-color: var(--accent);
}

/* Settings form labels */
.dialog.settings label {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  font-family: var(--sans);
  font-size: 14px;
  color: var(--text-2);
}
.dialog.settings label span {
  flex: 1;
}
.dialog.settings label input {
  width: 120px;
  background: var(--bg);
  border: 1px solid var(--hairline);
  border-radius: 6px;
  padding: 8px 10px;
  font-family: var(--mono);
  font-size: 14px;
  color: var(--text);
  text-align: right;
  outline: none;
  transition: border-color 0.15s var(--ease);
}
.dialog.settings label input:focus {
  border-color: var(--accent);
}

/* Action buttons row */
.capture-actions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  margin-top: 6px;
}
.ghost-btn, .primary-btn {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  padding: 10px 16px;
  border-radius: 6px;
  cursor: pointer;
  font-weight: 500;
  transition: background 0.15s var(--ease), color 0.15s var(--ease);
}
.ghost-btn {
  background: transparent;
  border: 1px solid var(--hairline);
  color: var(--text-2);
}
.ghost-btn:hover {
  border-color: var(--text-3);
  color: var(--text);
}
.primary-btn {
  background: var(--accent);
  border: 1px solid var(--accent);
  color: var(--bg);
}
.primary-btn:hover {
  opacity: 0.9;
}
.primary-btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* Safe area iOS (encoche / Dynamic Island) */
@supports (padding: max(0px)) {
  body {
    padding-top: max(14px, env(safe-area-inset-top));
    padding-bottom: max(80px, env(safe-area-inset-bottom));
  }
  .fab-wrap {
    bottom: max(24px, env(safe-area-inset-bottom));
  }
}

/* =================================================================
   HISTORY PAGE — sprint 9 + 10
   ================================================================= */
.tdee-card {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 18px 0 20px;
  margin-bottom: 18px;
  border-bottom: 1px solid var(--hairline-soft);
}
.tdee-label {
  font-family: var(--mono);
  font-size: 10px;
  color: var(--text-3);
  letter-spacing: 0.22em;
  text-transform: uppercase;
}
.tdee-value {
  display: flex;
  align-items: baseline;
  gap: 10px;
  flex-wrap: wrap;
}
.tdee-value .num {
  font-family: var(--mono);
  font-size: 32px;
  font-weight: 500;
  color: var(--text);
  letter-spacing: -0.01em;
}
.tdee-unit {
  font-family: var(--mono);
  font-size: 11px;
  color: var(--text-3);
  letter-spacing: 0.06em;
}
.tdee-delta {
  font-family: var(--mono);
  font-size: 11px;
  color: var(--text-3);
  letter-spacing: 0.02em;
}
.tdee-delta.up { color: var(--accent); }
.tdee-detail {
  font-family: var(--mono);
  font-size: 10.5px;
  color: var(--text-4);
  letter-spacing: 0.04em;
}
.back-link {
  font-family: var(--mono);
  font-size: 10px;
  color: var(--text-3);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  text-decoration: none;
  padding: 8px 0;
  display: inline-flex;
  align-items: center;
  min-height: 32px;
}
.back-link:hover { color: var(--text); }
.history-window {
  display: flex;
  gap: 6px;
  margin: 0 0 16px;
}
.history-tab {
  font-family: var(--mono);
  font-size: 11px;
  color: var(--text-3);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  text-decoration: none;
  padding: 6px 12px;
  border: 1px solid var(--hairline);
  border-radius: 999px;
  transition: border-color 0.15s var(--ease), color 0.15s var(--ease);
}
.history-tab:hover { border-color: var(--text-3); color: var(--text); }
.history-tab.active {
  border-color: var(--accent);
  color: var(--accent);
}
.history-list {
  display: flex;
  flex-direction: column;
}
.history-row {
  display: grid;
  grid-template-columns: 90px 1fr 1fr 70px;
  align-items: baseline;
  gap: 12px;
  padding: 14px 0;
  border-bottom: 1px solid var(--hairline-soft);
}
.history-row:last-child { border-bottom: none; }
.history-date {
  font-family: var(--mono);
  font-size: 11px;
  color: var(--text-3);
  letter-spacing: 0.04em;
}
.history-kcal .num-big {
  font-family: var(--mono);
  font-size: 22px;
  color: var(--text);
  letter-spacing: -0.01em;
}
.history-kcal .unit {
  font-family: var(--mono);
  font-size: 10px;
  color: var(--text-4);
  letter-spacing: 0.06em;
  margin-left: 4px;
}
.history-macros {
  font-family: var(--mono);
  font-size: 12px;
  color: var(--text-2);
  letter-spacing: 0.02em;
  display: inline-flex;
  align-items: baseline;
  gap: 1px;
  flex-wrap: wrap;
}
/* Sprint 23 (design-review) : mini-labels P/L/G inline pour clarifier la lecture
   sans contexte (sur la home le hero a "g prot · g lip · g gluc"). Ici on
   compresse en P/L/G pour ne pas alourdir la row. Label en text-4 plus discret. */
.history-macros .macro-key {
  font-size: 9px;
  color: var(--text-4);
  margin-left: 1px;
  letter-spacing: 0.04em;
}
.history-macros .macro-sep {
  color: var(--text-4);
  margin: 0 4px;
  opacity: 0.6;
}
.history-weight {
  font-family: var(--mono);
  font-size: 12px;
  color: var(--text-3);
  text-align: right;
}

/* =================================================================
   LOGIN PAGE — passcode 4 digits, sprint 9
   ================================================================= */

body.login-page {
  background: var(--bg);
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: max(40px, env(safe-area-inset-top))
           max(20px, env(safe-area-inset-right))
           max(40px, env(safe-area-inset-bottom))
           max(20px, env(safe-area-inset-left));
  max-width: 100%;
}
.login-frame {
  width: 100%;
  max-width: 380px;
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 32px;
}
.login-wordmark {
  display: inline-flex;
  align-items: baseline;
  gap: 4px;
  font-family: var(--sans);
  font-size: 36px;
  font-weight: 500;
  letter-spacing: -0.02em;
  color: var(--text);
}
.login-dot {
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--accent);
  margin-bottom: 5px;
  display: inline-block;
}
.login-label {
  font-family: var(--mono);
  font-size: 10px;
  color: var(--text-3);
  letter-spacing: 0.32em;
  text-transform: uppercase;
  margin: 0;
}
.login-form {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
  width: 100%;
}
.login-digits {
  display: flex;
  gap: 14px;
  justify-content: center;
}
.login-digit {
  width: 56px;
  height: 64px;
  background: var(--bg);
  border: 1px solid var(--hairline);
  border-radius: 10px;
  text-align: center;
  font-family: var(--mono);
  font-size: 28px;
  font-weight: 500;
  color: var(--text);
  outline: none;
  caret-color: var(--accent);
  transition: border-color 0.15s var(--ease);
}
.login-digit:focus {
  border-color: var(--accent);
}
.login-error {
  font-family: var(--mono);
  font-size: 11px;
  color: var(--rust);
  letter-spacing: 0.06em;
  margin: 0;
}
.login-fallback {
  width: 100%;
  padding: 12px 14px;
  background: var(--bg);
  border: 1px solid var(--hairline);
  border-radius: 8px;
  font-family: var(--mono);
  font-size: 16px;
  text-align: center;
  color: var(--text);
  outline: none;
}

@media (max-width: 380px) {
  .login-digit { width: 48px; height: 56px; font-size: 24px; }
  .login-digits { gap: 10px; }
}

/* =================================================================
   ONBOARDING PAGE — refonte operator/Whoop, sprint 6.10
   ================================================================= */

body.onboarding-page {
  background: var(--bg);
  padding-top: max(24px, env(safe-area-inset-top));
  padding-bottom: 0;
}

/* ===== Hero ===== */
.ob-hero {
  padding: 32px 0 40px;
  text-align: center;
}
.ob-wordmark {
  display: inline-flex;
  align-items: baseline;
  gap: 4px;
  font-family: var(--sans);
  font-size: 32px;
  font-weight: 500;
  letter-spacing: -0.02em;
  color: var(--text);
  margin-bottom: 32px;
}
.ob-wordmark-text { line-height: 1; }
.ob-wordmark-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--accent);
  margin-bottom: 4px;
  display: inline-block;
}
.ob-headline {
  font-family: var(--sans);
  font-size: 32px;
  font-weight: 500;
  line-height: 1.1;
  letter-spacing: -0.02em;
  color: var(--text);
  margin: 0 0 12px;
}
.ob-subhead {
  font-family: var(--mono);
  font-size: 12px;
  color: var(--text-3);
  letter-spacing: 0.04em;
  margin: 0;
  line-height: 1.5;
}

/* ===== Form layout ===== */
.ob-form {
  display: flex;
  flex-direction: column;
  gap: 28px;
  padding-bottom: 140px; /* place pour le sticky CTA */
}
.ob-section {
  display: flex;
  flex-direction: column;
}
.ob-section-title {
  font-family: var(--mono);
  font-size: 10px;
  font-weight: 500;
  color: var(--text-3);
  letter-spacing: 0.24em;
  text-transform: uppercase;
  margin: 0 0 4px;
  padding-bottom: 14px;
  border-bottom: 1px solid var(--hairline-soft);
}

/* ===== Big-number rows (mesures) ===== */
.ob-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 22px 4px 18px;
  border-bottom: 1px solid var(--hairline-soft);
  cursor: text;
  position: relative;
  min-height: 64px;
}
.ob-row:last-of-type {
  border-bottom: none;
}
.ob-row-label {
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 400;
  color: var(--text-3);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  flex-shrink: 0;
}
.ob-row-input {
  display: inline-flex;
  align-items: baseline;
  gap: 8px;
  margin-left: auto;
}
.ob-row input[type="number"] {
  font-family: var(--mono);
  font-size: 32px;
  font-weight: 500;
  color: var(--text);
  background: transparent;
  border: 0;
  padding: 0;
  outline: none;
  width: auto;
  max-width: 140px;
  letter-spacing: -0.01em;
  text-align: right;
  -moz-appearance: textfield;
  transition: color 0.15s var(--ease);
}
.ob-row input[type="number"]::-webkit-outer-spin-button,
.ob-row input[type="number"]::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
.ob-row input:focus {
  color: var(--accent);
}
.ob-row-unit {
  font-family: var(--mono);
  font-size: 13px;
  color: var(--text-3);
  letter-spacing: 0.06em;
  text-transform: lowercase;
  flex-shrink: 0;
}
.ob-row-hint {
  font-family: var(--mono);
  font-size: 10px;
  color: var(--text-4);
  letter-spacing: 0.06em;
  margin: 14px 4px 0;
  line-height: 1.55;
}

/* Select dans une ob-row (palier de départ) */
.ob-row-select {
  cursor: pointer;
}
.ob-row-select .ob-row-input {
  flex: 1;
  justify-content: flex-end;
  position: relative;
  padding-right: 20px;
}
.ob-row-select .ob-row-input::after {
  content: "";
  position: absolute;
  right: 0;
  top: 50%;
  transform: translateY(-30%) rotate(45deg);
  width: 7px;
  height: 7px;
  border-right: 1.5px solid var(--text-3);
  border-bottom: 1.5px solid var(--text-3);
  pointer-events: none;
}
.ob-row select {
  font-family: var(--mono);
  font-size: 15px;
  font-weight: 500;
  color: var(--text);
  background: transparent;
  border: 0;
  outline: none;
  appearance: none;
  -webkit-appearance: none;
  text-align: right;
  cursor: pointer;
  padding: 0;
  letter-spacing: 0.02em;
}

/* ===== Protocoles ===== */
.ob-protocols {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding-top: 14px;
}
.ob-proto {
  display: grid;
  grid-template-columns: 40px 1fr 18px;
  align-items: center;
  gap: 14px;
  padding: 18px 18px;
  border: 1px solid var(--hairline);
  border-radius: 12px;
  cursor: pointer;
  background: var(--bg);
  transition: border-color 0.18s var(--ease), background 0.18s var(--ease), transform 0.1s var(--ease);
  position: relative;
  min-height: 72px;
}
.ob-proto:hover {
  border-color: var(--text-3);
}
.ob-proto:active {
  transform: scale(0.992);
}
.ob-proto input[type="radio"] {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}
.ob-proto:has(input:checked) {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 7%, transparent);
}
.proto-code {
  font-family: var(--mono);
  font-size: 18px;
  font-weight: 500;
  color: var(--text-3);
  letter-spacing: 0.04em;
  transition: color 0.18s var(--ease);
}
.ob-proto:has(input:checked) .proto-code {
  color: var(--accent);
}
.proto-body {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}
.proto-name {
  font-family: var(--sans);
  font-size: 15px;
  font-weight: 500;
  color: var(--text);
  line-height: 1.25;
  letter-spacing: -0.005em;
}
.proto-spec {
  font-family: var(--mono);
  font-size: 11px;
  color: var(--text-3);
  letter-spacing: 0.04em;
  line-height: 1.4;
}
.proto-check {
  width: 18px;
  height: 18px;
  border: 1px solid var(--text-3);
  border-radius: 50%;
  position: relative;
  transition: border-color 0.18s var(--ease);
  justify-self: end;
}
.ob-proto:has(input:checked) .proto-check {
  border-color: var(--accent);
}
.ob-proto:has(input:checked) .proto-check::after {
  content: "";
  position: absolute;
  inset: 3px;
  border-radius: 50%;
  background: var(--accent);
}

/* ===== Formula recap ===== */
.ob-formula {
  font-family: var(--mono);
  font-size: 10.5px;
  color: var(--text-4);
  letter-spacing: 0.05em;
  line-height: 1.7;
  margin: 12px 4px 0;
  padding: 16px 0 0;
  border-top: 1px solid var(--hairline-soft);
}
.ob-formula span {
  color: var(--text-3);
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  font-size: 9.5px;
  margin-right: 4px;
}

/* ===== Sticky CTA ===== */
.ob-cta-sticky {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  padding: 32px max(20px, env(safe-area-inset-right))
           max(20px, env(safe-area-inset-bottom))
           max(20px, env(safe-area-inset-left));
  z-index: 10;
  pointer-events: none;
  background: linear-gradient(to top, var(--bg) 30%, color-mix(in srgb, var(--bg) 80%, transparent) 70%, transparent 100%);
}
.ob-cta {
  pointer-events: auto;
  width: 100%;
  max-width: 480px;
  margin: 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  padding: 16px 24px;
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--bg);
  background: var(--accent);
  border: 0;
  border-radius: 12px;
  cursor: pointer;
  min-height: 56px;
  transition: transform 0.1s var(--ease), opacity 0.15s var(--ease);
  box-shadow: 0 6px 24px color-mix(in srgb, var(--accent) 35%, transparent);
}
.ob-cta:hover {
  opacity: 0.92;
}
.ob-cta:active {
  transform: scale(0.985);
}
.ob-cta svg {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
}
/* Sprint 24 (redesign-existing-projects) : loading state CTA.
   Swap label + grise. Le user voit que ça calcule, pas de double submit. */
.ob-cta .ob-cta-loading { display: none; }
.ob-cta.is-loading {
  opacity: 0.72;
  cursor: progress;
  background: color-mix(in srgb, var(--accent) 80%, var(--text-3));
}
.ob-cta.is-loading .ob-cta-label,
.ob-cta.is-loading svg { display: none; }
.ob-cta.is-loading .ob-cta-loading {
  display: inline;
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--bg);
}

/* Desktop ≥768px : centre, plus respiré */
@media (min-width: 768px) {
  body.onboarding-page {
    max-width: 560px;
    padding-top: max(40px, env(safe-area-inset-top));
  }
  .ob-hero { padding: 48px 0 56px; }
  .ob-headline { font-size: 40px; }
  .ob-row input[type="number"] { font-size: 38px; }
  .ob-cta-sticky {
    padding: 32px max(40px, env(safe-area-inset-right))
             max(32px, env(safe-area-inset-bottom))
             max(40px, env(safe-area-inset-left));
  }
}

/* ============== SPRINT 3 ADDITIONS ============== */

/* App header (wordmark + cog) */
.app-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 8px;
}

/* Layout grid : sur desktop, 2 colonnes pour day/hero/trend/macros/weight */
.layout-grid {
  display: flex;
  flex-direction: column;
  gap: 0;
}
@media (min-width: 768px) {
  .layout-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    grid-template-areas:
      "day    hero"
      "trend  macros"
      "weight weight"
      "journal journal";
    gap: 0 28px;
  }
  .card-day     { grid-area: day; }
  .card-hero    { grid-area: hero; }
  .card-trend   { grid-area: trend; }
  .card-macros  { grid-area: macros; }
  .card-weight  { grid-area: weight; }
  .card-journal { grid-area: journal; }
}
@media (min-width: 1100px) {
  .layout-grid {
    grid-template-columns: 1fr 1fr 1fr;
    grid-template-areas:
      "day     hero   hero"
      "trend   macros weight"
      "journal journal journal";
    gap: 0 32px;
  }
}

/* Empty state */
.empty-state {
  font-family: var(--mono);
  font-size: 11px;
  color: var(--text-3);
  letter-spacing: 0.04em;
  margin: 18px 0 0;
}

/* ============== MEAL SECTIONS ============== */
.meal-section {
  margin-bottom: 8px;
}
.meal-section + .meal-section {
  margin-top: 8px;
  padding-top: 8px;
}
.meal-section-head {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 16px 0 6px;
}
.meal-label {
  font-family: var(--mono);
  font-size: 9.5px;
  color: var(--accent);
  letter-spacing: 0.24em;
  text-transform: uppercase;
  font-weight: 500;
}
.meal-rule {
  flex: 1;
  height: 1px;
  background: var(--hairline);
  transform: translateY(-1px);
}
.meal-kcal {
  font-family: var(--mono);
  font-size: 10px;
  color: var(--text-3);
  letter-spacing: 0.06em;
}
.meal-add-btn {
  background: transparent;
  border: 1px solid var(--hairline);
  color: var(--text-3);
  width: 28px;
  height: 28px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  cursor: pointer;
  transition: border-color 0.15s var(--ease), color 0.15s var(--ease), background 0.15s var(--ease);
  position: relative;
  flex-shrink: 0;
}
/* Zone touch 44pt via overlay invisible */
.meal-add-btn::before {
  content: '';
  position: absolute;
  inset: -8px;
}
.meal-add-btn:active {
  background: var(--accent-soft);
  transform: scale(0.95);
}
.meal-add-btn:hover {
  border-color: var(--accent);
  color: var(--accent);
}
.meal-add-btn svg {
  width: 12px;
  height: 12px;
}
.meal-entries {
  display: flex;
  flex-direction: column;
}
.meal-empty {
  font-family: var(--mono);
  font-size: 10.5px;
  color: var(--text-4);
  letter-spacing: 0.04em;
  padding: 10px 0 14px 4px;
}

/* Entry actions (duplicate + delete) à droite de chaque entry, masqués jusqu'au hover/tap */
.entry {
  position: relative;
  grid-template-columns: 48px 1fr auto auto !important;
}
.entry-actions {
  display: flex;
  gap: 6px;
  align-items: center;
  opacity: 0;
  transition: opacity 0.15s var(--ease);
  margin-left: 8px;
}
.entry:hover .entry-actions,
.entry:focus-within .entry-actions {
  opacity: 1;
}
@media (hover: none) {
  .entry-actions { opacity: 0.65; }
}
.entry-action-btn {
  background: transparent;
  border: 0;
  padding: 8px;
  min-width: 32px;
  min-height: 32px;
  cursor: pointer;
  color: var(--text-3);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 6px;
  transition: color 0.15s var(--ease), background 0.15s var(--ease);
  position: relative;
}
/* Zone touch 44pt via overlay (visu compact mais hit-area généreuse) */
.entry-action-btn::before {
  content: '';
  position: absolute;
  inset: -6px;
}
.entry-action-btn:hover {
  color: var(--accent);
  background: var(--accent-soft);
}
.entry-action-btn.destructive:hover {
  color: var(--rust);
  background: var(--rust-soft);
}
.entry-action-btn svg {
  width: 14px;
  height: 14px;
}

/* ============== TWO FABs (text + voice) ============== */
.fab-wrap {
  align-items: center;
  flex-direction: row !important;
  gap: 12px;
}
.fab-stack {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 10px;
}
.fab-secondary,
.fab-tertiary {
  width: 48px;
  height: 48px;
  background: var(--surface);
  border: 1px solid var(--hairline);
  color: var(--text-2);
  box-shadow:
    0 8px 20px -8px rgba(0, 0, 0, 0.4),
    0 2px 6px -2px rgba(0, 0, 0, 0.3);
}
.fab-secondary:hover,
.fab-tertiary:hover {
  background: var(--surface-2);
  color: var(--text);
}
.fab-secondary svg,
.fab-tertiary svg {
  width: 18px;
  height: 18px;
}
.fab-primary {
  /* hérite du .fab classique */
  touch-action: none;  /* éviter le scroll pendant le hold */
  user-select: none;
}
.fab-primary.recording {
  background: var(--rust);
  border-color: var(--rust);
  transform: scale(1.08);
  box-shadow:
    0 0 0 6px rgba(210, 69, 40, 0.18),
    0 0 0 12px rgba(210, 69, 40, 0.08),
    0 18px 36px -10px rgba(210, 69, 40, 0.55);
  transition: transform 0.15s var(--ease), box-shadow 0.3s var(--ease), background 0.2s var(--ease);
}
.fab-primary.recording::before {
  animation-duration: 1.4s;
  border-color: var(--rust);
  opacity: 0.5;
}

/* Recording sheet (Wispr-style bottom sheet pendant hold) */
.recording-sheet {
  position: fixed;
  left: 50%;
  bottom: 110px;
  transform: translateX(-50%) translateY(20px);
  opacity: 0;
  pointer-events: none;
  z-index: 11;
  width: calc(100vw - 32px);
  max-width: 420px;
  transition: opacity 0.22s var(--ease), transform 0.22s var(--ease);
}
.recording-sheet.active {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}
.recording-sheet-inner {
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: 14px;
  padding: 18px 20px;
  box-shadow:
    0 24px 60px -12px rgba(0, 0, 0, 0.5),
    0 0 0 1px var(--hairline);
  /* Sprint 19 : backdrop-filter retiré (audit, glassmorphism prohibé) */
}
.recording-state {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 12px;
}
.recording-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--rust);
  box-shadow: 0 0 12px rgba(210, 69, 40, 0.7);
  animation: rec-pulse 1.2s ease-in-out infinite;
}
@keyframes rec-pulse {
  0%, 100% { transform: scale(1); opacity: 1; }
  50%      { transform: scale(0.75); opacity: 0.6; }
}
.recording-label {
  font-family: var(--mono);
  font-size: 10px;
  color: var(--text-3);
  letter-spacing: 0.18em;
  text-transform: uppercase;
}
.recording-transcript {
  font-family: var(--sans);
  font-size: 17px;
  line-height: 1.4;
  color: var(--text);
  min-height: 28px;
  margin-bottom: 10px;
  font-weight: 500;
}
.recording-hint {
  font-family: var(--mono);
  font-size: 9.5px;
  color: var(--text-4);
  letter-spacing: 0.08em;
}

/* ===== Capture dialog refondu (sprint 5) ===== */

/* Header avec titre + close button */
.dialog.capture .capture-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 4px;
}
.dialog.capture .capture-mode {
  font-family: var(--mono);
  font-size: 10px;
  color: var(--text-3);
  letter-spacing: 0.22em;
  text-transform: uppercase;
  transition: color 0.2s var(--ease);
}
.dialog.capture .capture-mode.error {
  color: var(--rust, #c75432);
}
.capture-close {
  width: 32px;
  height: 32px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: 1px solid var(--hairline-soft);
  border-radius: 50%;
  color: var(--text-3);
  cursor: pointer;
  transition: border-color 0.15s var(--ease), color 0.15s var(--ease);
  flex-shrink: 0;
}
.capture-close:hover { border-color: var(--text-3); color: var(--text); }
.capture-close svg { width: 14px; height: 14px; }

/* Row de chips pour choisir la section meal */
.capture-section-row {
  display: flex;
  gap: 6px;
  overflow-x: auto;
  scrollbar-width: none;
  margin: 0 -4px 4px;
  padding: 4px;
  -webkit-overflow-scrolling: touch;
  scroll-snap-type: x proximity;
}
.capture-section-row::-webkit-scrollbar { display: none; }
.capture-chip {
  flex: 1 0 auto;
  min-width: 80px;
  min-height: 52px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  padding: 8px 10px;
  background: var(--bg);
  border: 1px solid var(--hairline);
  border-radius: 8px;
  cursor: pointer;
  scroll-snap-align: start;
  transition: border-color 0.15s var(--ease), background 0.15s var(--ease), transform 0.1s var(--ease);
}
.capture-chip:hover { border-color: var(--text-3); }
.capture-chip:active { transform: scale(0.97); }
.capture-chip .chip-label {
  font-family: var(--sans);
  font-size: 12px;
  font-weight: 500;
  color: var(--text-2);
  letter-spacing: 0.01em;
  line-height: 1.1;
}
.capture-chip .chip-time {
  font-family: var(--mono);
  font-size: 9px;
  color: var(--text-4);
  letter-spacing: 0.05em;
  line-height: 1;
}
.capture-chip.active {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 8%, transparent);
}
.capture-chip.active .chip-label { color: var(--text); }
.capture-chip.active .chip-time { color: color-mix(in srgb, var(--accent) 80%, var(--text-3)); }

/* ===== Photo plate analyzing overlay ===== */
/* IMPORTANT : règle [hidden] AVANT la règle de display, sinon le CSS
   `display: flex` override l'attribut HTML `hidden` et l'overlay reste
   visible. Bug critique remonté sur iOS, sprint 17. */
.plate-analyzing[hidden],
.action-sheet[hidden],
.action-sheet-backdrop[hidden],
.capture-suggestions[hidden] {
  display: none !important;
}
.plate-analyzing {
  position: fixed;
  inset: 0;
  /* Sprint 19 : background opaque (was rgba+blur). Glassmorphism prohibé. */
  background: var(--bg);
  z-index: var(--z-plate-overlay);
  display: flex;
  align-items: center;
  justify-content: center;
}
.plate-analyzing-inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  padding: 32px 40px;
}
.plate-analyzing-spinner {
  width: 48px;
  height: 48px;
  border: 2px solid color-mix(in srgb, var(--accent) 25%, transparent);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: spin 0.9s linear infinite;
}
.plate-analyzing-label {
  font-family: var(--sans);
  font-size: 17px;
  color: var(--text);
  letter-spacing: -0.005em;
  display: inline-flex;
  align-items: baseline;
}
.plate-analyzing-label .dots span {
  animation: dot 1.4s infinite;
  opacity: 0.3;
}
.plate-analyzing-label .dots span:nth-child(1) { animation-delay: 0s; }
.plate-analyzing-label .dots span:nth-child(2) { animation-delay: 0.2s; }
.plate-analyzing-label .dots span:nth-child(3) { animation-delay: 0.4s; }
@keyframes dot {
  0%, 60%, 100% { opacity: 0.3; }
  30% { opacity: 1; }
}
.plate-analyzing-sub {
  font-family: var(--mono);
  font-size: 11px;
  color: var(--text-3);
  letter-spacing: 0.16em;
  text-transform: uppercase;
}
.plate-analyzing-cancel {
  margin-top: 24px;
  padding: 10px 28px;
  background: transparent;
  border: 1px solid var(--hairline);
  border-radius: var(--r-pill);
  font-family: var(--mono);
  font-size: 11px;
  color: var(--text-2);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  cursor: pointer;
  transition: border-color 0.15s var(--ease), color 0.15s var(--ease);
}
.plate-analyzing-cancel:hover {
  border-color: var(--rust);
  color: var(--rust);
}

/* ===== Action sheet (tap court FAB mic) ===== */
.action-sheet-backdrop {
  position: fixed;
  inset: 0;
  /* Sprint 19 : backdrop-filter retiré (audit). Background un peu plus opaque
     pour compenser visuellement la perte du blur. */
  background: rgba(10, 11, 14, 0.78);
  opacity: 0;
  transition: opacity 0.22s var(--ease);
  z-index: var(--z-action-sheet);
}
.action-sheet-backdrop.open { opacity: 1; }
.action-sheet {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  padding: 8px 14px max(28px, env(safe-area-inset-bottom));
  background: var(--surface);
  border-top-left-radius: 22px;
  border-top-right-radius: 22px;
  z-index: calc(var(--z-action-sheet) + 1);
  transform: translateY(100%);
  transition: transform 0.28s cubic-bezier(0.32, 0.72, 0, 1);
  box-shadow: 0 -10px 40px -10px rgba(0, 0, 0, 0.5);
  max-width: 560px;
  margin: 0 auto;
}
.action-sheet.open { transform: translateY(0); }
.action-sheet-handle {
  width: 36px;
  height: 4px;
  background: var(--text-4);
  border-radius: 999px;
  margin: 0 auto 14px;
  opacity: 0.6;
}
.action-item {
  display: flex;
  align-items: center;
  gap: 14px;
  width: 100%;
  padding: 14px 8px;
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--hairline-soft);
  text-align: left;
  cursor: pointer;
  transition: background 0.12s var(--ease);
  min-height: 64px;
}
.action-item:last-of-type { border-bottom: none; }
.action-item:hover, .action-item:focus {
  background: var(--surface-2);
  outline: none;
}
.action-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 42px;
  height: 42px;
  border-radius: 12px;
  flex-shrink: 0;
}
.action-icon svg { width: 20px; height: 20px; }
.action-body {
  display: flex;
  flex-direction: column;
  gap: 2px;
  flex: 1;
  min-width: 0;
}
.action-title {
  font-family: var(--sans);
  font-size: 15px;
  font-weight: 500;
  color: var(--text);
  line-height: 1.2;
}
.action-sub {
  font-family: var(--mono);
  font-size: 10.5px;
  color: var(--text-3);
  letter-spacing: 0.04em;
}
.action-cancel {
  justify-content: center;
  margin-top: 8px;
  padding: 14px;
  background: color-mix(in srgb, var(--text-4) 18%, transparent);
  border: 0 !important;
  border-radius: 12px;
}
.action-cancel-label {
  font-family: var(--mono);
  font-size: 11px;
  color: var(--text);
  letter-spacing: 0.18em;
  text-transform: uppercase;
}

/* ===== Day calendar nav ===== */
.day-nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
.day-nav-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: transparent;
  border: 1px solid var(--hairline-soft);
  color: var(--text-3);
  cursor: pointer;
  text-decoration: none;
  transition: border-color 0.15s var(--ease), color 0.15s var(--ease);
  flex-shrink: 0;
}
.day-nav-btn:hover { border-color: var(--accent); color: var(--accent); }
.day-nav-btn svg { width: 16px; height: 16px; }
.day-nav-btn-disabled {
  opacity: 0.25;
  cursor: not-allowed;
  pointer-events: none;
}
.day-name-btn {
  flex: 1;
  background: transparent;
  border: 0;
  padding: 6px 8px;
  cursor: pointer;
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  position: relative;
  min-height: 44px;
}
.day-name-btn .name {
  font-family: var(--sans);
  font-size: 17px;
  color: var(--text);
  letter-spacing: -0.005em;
}
.day-not-today {
  font-family: var(--mono);
  font-size: 10px;
  color: var(--accent);
  letter-spacing: 0.06em;
}
.day-name-btn input[type="date"] {
  position: absolute;
  inset: 0;
  opacity: 0;
  pointer-events: none;
}
.day-back-today {
  display: inline-block;
  margin-top: 8px;
  font-family: var(--mono);
  font-size: 10px;
  color: var(--text-3);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  text-decoration: none;
  text-align: center;
  width: 100%;
  padding: 6px 0;
}
.day-back-today:hover { color: var(--accent); }

/* ===== Plate staging area (multi-aliments) ===== */
.capture-plate {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 10px 12px;
  margin: -2px 0 8px;
  background: color-mix(in srgb, var(--accent) 4%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 25%, var(--hairline));
  border-radius: 10px;
}
.plate-items {
  display: flex;
  flex-direction: column;
}
.plate-item {
  display: grid;
  grid-template-columns: 1fr 70px 50px 24px;
  align-items: center;
  gap: 8px;
  padding: 8px 0;
  border-bottom: 1px solid color-mix(in srgb, var(--accent) 18%, var(--hairline-soft));
}
.plate-item:last-child { border-bottom: none; }
.plate-item-name {
  font-family: var(--sans);
  font-size: 13px;
  color: var(--text);
  line-height: 1.2;
  text-overflow: ellipsis;
  overflow: hidden;
  white-space: nowrap;
}
.plate-item-grams {
  display: inline-flex;
  align-items: baseline;
  gap: 3px;
  justify-self: end;
}
.plate-grams-input {
  width: 50px;
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--hairline);
  font-family: var(--mono);
  font-size: 13px;
  color: var(--text);
  text-align: right;
  padding: 2px 2px;
  outline: none;
  -moz-appearance: textfield;
}
.plate-grams-input::-webkit-outer-spin-button,
.plate-grams-input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.plate-grams-input:focus { border-bottom-color: var(--accent); color: var(--accent); }
.plate-g-unit {
  font-family: var(--mono);
  font-size: 10px;
  color: var(--text-4);
}
.plate-item-kcal {
  font-family: var(--mono);
  font-size: 13px;
  color: var(--text);
  text-align: right;
}
.plate-item-remove {
  background: transparent;
  border: 0;
  padding: 2px;
  color: var(--text-3);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 28px;
  min-height: 28px;
  border-radius: 50%;
  transition: color 0.12s var(--ease);
}
.plate-item-remove:hover { color: var(--rust); }
.plate-item-remove svg { width: 12px; height: 12px; }
.plate-totals {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  padding: 6px 0 0;
  border-top: 1px solid color-mix(in srgb, var(--accent) 30%, var(--hairline));
}
.plate-totals-label {
  font-family: var(--mono);
  font-size: 10px;
  color: var(--text-3);
  letter-spacing: 0.18em;
  text-transform: uppercase;
}
.plate-totals-value {
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
}
.plate-totals-value .num {
  font-family: var(--mono);
  font-size: 18px;
  color: var(--text);
  font-weight: 500;
}
.plate-unit {
  font-family: var(--mono);
  font-size: 10px;
  color: var(--text-3);
  letter-spacing: 0.06em;
}
.plate-macros {
  font-family: var(--mono);
  font-size: 11px;
  color: var(--text-3);
  margin-left: 8px;
}

/* ===== Barcode scanner ===== */
.capture-tools {
  display: flex;
  gap: 8px;
  margin: 0 0 8px;
}
.capture-tool-btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  background: transparent;
  border: 1px solid var(--hairline);
  border-radius: 8px;
  font-family: var(--mono);
  font-size: 10px;
  color: var(--text-3);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  cursor: pointer;
  min-height: 36px;
  transition: border-color 0.15s var(--ease), color 0.15s var(--ease);
}
.capture-tool-btn:hover { border-color: var(--accent); color: var(--text); }
.capture-tool-btn svg { width: 14px; height: 14px; }
.capture-tool-btn.recording {
  border-color: var(--rust);
  color: var(--rust);
  background: color-mix(in srgb, var(--rust) 8%, transparent);
  animation: pulse-tool 1.6s ease-in-out infinite;
}
@keyframes pulse-tool {
  0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--rust) 30%, transparent); }
  50%      { box-shadow: 0 0 0 6px color-mix(in srgb, var(--rust) 0%, transparent); }
}

.dialog.barcode-dialog .dialog-inner { max-width: 380px; }
.barcode-video-wrap {
  position: relative;
  aspect-ratio: 4 / 3;
  background: #000;
  border-radius: 10px;
  overflow: hidden;
  margin: 8px 0 10px;
}
.barcode-video-wrap video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.barcode-frame {
  position: absolute;
  inset: 18% 12%;
  border: 2px solid var(--accent);
  border-radius: 6px;
  box-shadow: 0 0 0 9999px rgba(0, 0, 0, 0.35);
  pointer-events: none;
}
.barcode-hint {
  font-family: var(--mono);
  font-size: 11px;
  color: var(--text-3);
  letter-spacing: 0.04em;
  margin: 0 0 8px;
  text-align: center;
}
.barcode-manual {
  display: flex;
  align-items: center;
  gap: 8px;
  padding-top: 6px;
  border-top: 1px solid var(--hairline-soft);
}
.barcode-manual input {
  flex: 1;
  background: var(--bg);
  border: 1px solid var(--hairline);
  border-radius: 6px;
  padding: 8px 10px;
  font-family: var(--mono);
  font-size: 13px;
  color: var(--text);
  outline: none;
}
.barcode-manual input:focus { border-color: var(--accent); }
.primary-btn.primary-btn-mini {
  padding: 8px 14px;
  min-height: 36px;
  font-size: 10px;
}

/* ===== Section label dans le dropdown (Fréquents / Recherche) ===== */
.sugg-section-label {
  font-family: var(--mono);
  font-size: 9.5px;
  color: var(--text-3);
  letter-spacing: 0.22em;
  text-transform: uppercase;
  padding: 4px 8px;
  margin-top: 4px;
}
.sugg-frequent .sugg-freq {
  font-family: var(--mono);
  font-size: 10px;
  color: var(--text-4);
  margin-left: 6px;
  letter-spacing: 0.04em;
}

/* ===== Autocomplete dropdown CIQUAL ===== */
.capture-suggestions {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin: -4px 0 6px;
  max-height: 240px;
  overflow-y: auto;
  scrollbar-width: thin;
  border-top: 1px solid var(--hairline-soft);
  padding-top: 6px;
}
.capture-suggestion {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  width: 100%;
  padding: 9px 8px;
  background: transparent;
  border: 0;
  border-radius: 6px;
  cursor: pointer;
  text-align: left;
  transition: background 0.12s var(--ease);
  min-height: 40px;
}
.capture-suggestion:hover,
.capture-suggestion:focus {
  background: color-mix(in srgb, var(--accent) 7%, transparent);
  outline: none;
}
.capture-suggestion .sugg-name {
  font-family: var(--sans);
  font-size: 14px;
  color: var(--text);
  line-height: 1.3;
  flex: 1;
  min-width: 0;
  text-overflow: ellipsis;
  white-space: nowrap;
  overflow: hidden;
}
.capture-suggestion .sugg-macros {
  font-family: var(--mono);
  font-size: 11px;
  color: var(--text-3);
  letter-spacing: 0.02em;
  display: inline-flex;
  align-items: baseline;
  gap: 2px;
  flex-shrink: 0;
}
.capture-suggestion .sugg-kcal { color: var(--text-2); font-weight: 500; }
.capture-suggestion .sugg-per { color: var(--text-4); font-size: 9.5px; }

/* Ligne meta (heure custom) sous le textarea */
.capture-meta {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: -2px 0 2px;
}
.capture-meta-label {
  font-family: var(--mono);
  font-size: 10px;
  color: var(--text-4);
  letter-spacing: 0.16em;
  text-transform: uppercase;
}
.capture-meta input {
  flex: 0 0 auto;
  width: 80px;
  background: var(--bg);
  border: 1px solid var(--hairline);
  border-radius: 6px;
  padding: 6px 10px;
  font-family: var(--mono);
  font-size: 13px;
  color: var(--text);
  text-align: center;
  outline: none;
  transition: border-color 0.15s var(--ease);
}
.capture-meta input:focus { border-color: var(--accent); }
.capture-meta input::placeholder { color: var(--text-4); }

/* Bouton submit avec spinner inline pour loading state */
.primary-btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
}
.primary-btn .btn-spinner {
  display: none;
  width: 12px;
  height: 12px;
  border: 1.5px solid currentColor;
  border-top-color: transparent;
  border-radius: 50%;
  animation: spin 0.7s linear infinite;
}
.primary-btn.loading .btn-label { opacity: 0.35; }
.primary-btn.loading .btn-spinner { display: inline-block; }
.primary-btn:disabled { cursor: wait; }
@keyframes spin {
  to { transform: rotate(360deg); }
}

@media (max-width: 480px) {
  .capture-chip { min-width: 72px; padding: 7px 8px; }
  .capture-chip .chip-label { font-size: 11px; }
  .capture-chip .chip-time { font-size: 8.5px; }
}

@media (min-width: 768px) {
  .recording-sheet { bottom: 130px; }
}

/* ============== TOAST (success/error feedback inline) ============== */
.toast {
  position: fixed;
  left: 50%;
  bottom: calc(116px + env(safe-area-inset-bottom));
  transform: translate(-50%, 12px);
  background: var(--bg);
  color: var(--text);
  border: 1px solid var(--hairline);
  border-radius: 8px;
  padding: 10px 16px;
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.06em;
  white-space: nowrap;
  max-width: calc(100% - 32px);
  opacity: 0;
  pointer-events: none;
  z-index: var(--z-toast);
  transition: transform 0.22s var(--ease), opacity 0.22s var(--ease);
  box-shadow: 0 6px 22px rgba(0, 0, 0, 0.32);
}
.toast.active {
  opacity: 1;
  transform: translate(-50%, 0);
}
.toast.toast-success {
  border-color: color-mix(in srgb, var(--accent) 60%, transparent);
}
.toast.toast-error {
  border-color: color-mix(in srgb, var(--rust) 60%, transparent);
  color: color-mix(in srgb, var(--rust) 50%, var(--text));
}
@media (prefers-reduced-motion: reduce) {
  .toast { transition: opacity 0.15s linear; transform: translate(-50%, 0); }
}

/* ============== WEIGHT QUICK-LOG DIALOG ============== */
.dialog.weight-log .weight-input-row {
  display: flex;
  align-items: baseline;
  gap: 10px;
  padding: 18px 0 8px;
  border-bottom: 1px solid var(--hairline-soft);
  margin-bottom: 8px;
}
.dialog.weight-log #weight-input {
  flex: 1;
  background: transparent;
  border: 0;
  outline: none;
  font-family: var(--mono);
  font-size: 38px;
  font-weight: 500;
  color: var(--text);
  letter-spacing: -0.01em;
  text-align: left;
  -moz-appearance: textfield;
}
.dialog.weight-log #weight-input::-webkit-outer-spin-button,
.dialog.weight-log #weight-input::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
.dialog.weight-log #weight-input::placeholder {
  color: var(--text-4);
}
.dialog.weight-log .weight-unit {
  font-family: var(--mono);
  font-size: 14px;
  color: var(--text-3);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

/* ===== Contextual quick-log chips (sprint 18, friction zéro) =====
   Sous le hero, strip horizontal scroll. Un tap = log direct via hx-post.
   Charge silencieuse : si chips vide, le bloc disparaît (display:none auto).
   Sprint 32 : .card-chips padding overriden par la nouvelle règle tuile. */
.card-chips .chips-head {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin-bottom: 8px;
}
.card-chips .chips-head .label {
  font-family: var(--mono);
  font-size: var(--fs-3xs);
  color: var(--text-3);
  letter-spacing: 0.14em;
  text-transform: uppercase;
}
.card-chips .chips-head .ctx {
  font-family: var(--sans);
  font-size: var(--fs-xs);
  color: var(--text-4);
  letter-spacing: 0;
}
.chips-row {
  display: flex;
  gap: 8px;
  overflow-x: auto;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
  scroll-snap-type: x proximity;
  /* Sprint 32 : ajusté pour le nouveau padding card-chips 14px 16px */
  margin: 0 -16px;
  padding: 2px 16px;
}
.chips-row::-webkit-scrollbar { display: none; }
.chip-quick {
  flex: 0 0 auto;
  display: inline-flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
  padding: 9px 12px 8px;
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: var(--r-md);
  cursor: pointer;
  scroll-snap-align: start;
  transition: border-color 0.15s var(--ease),
              background 0.15s var(--ease),
              transform 0.08s var(--ease);
  text-align: left;
  max-width: 200px;
  position: relative;
}
.chip-quick:hover { border-color: var(--text-3); background: var(--surface-2); }
.chip-quick:active { transform: scale(0.97); }
.chip-quick:disabled { opacity: 0.5; cursor: progress; }
.chip-quick .chip-dish {
  font-family: var(--sans);
  font-size: var(--fs-sm);
  font-weight: 500;
  color: var(--text);
  letter-spacing: -0.005em;
  line-height: 1.15;
  max-width: 175px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.chip-quick .chip-meta {
  font-family: var(--mono);
  font-size: var(--fs-3xs);
  color: var(--text-3);
  letter-spacing: 0.08em;
}
.chip-quick .chip-meta .kcal { color: var(--text-2); }
.chip-quick .chip-meta .sep { opacity: 0.45; padding: 0 3px; }
/* État loading après tap, le temps que le POST revienne */
.chip-quick.is-loading {
  background: color-mix(in srgb, var(--accent) 12%, var(--surface));
  border-color: color-mix(in srgb, var(--accent) 40%, var(--hairline));
}
.chip-quick.is-loading .chip-dish { color: color-mix(in srgb, var(--accent) 80%, var(--text)); }

/* ===== Hero diagnostic one-liner (sprint 18, intelligence) =====
   Sous le delta macros du hero, ligne plate qui interprète l'état du jour.
   Couleur driven by .is-{tone} : ok / tight / over / ahead / early.
   Pas de carte séparée, c'est une extension visuelle du hero. */
.hero-diag {
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
  margin-top: 10px;
  padding: 4px 10px 4px 8px;
  border-radius: var(--r-pill);
  font-family: var(--sans);
  font-size: var(--fs-xs);
  letter-spacing: -0.005em;
  line-height: 1;
  border: 1px solid var(--hairline);
  background: color-mix(in srgb, var(--surface) 60%, transparent);
  max-width: 100%;
}
.hero-diag .diag-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--text-3);
  flex-shrink: 0;
}
.hero-diag .diag-label {
  color: var(--text);
  font-weight: 500;
}
.hero-diag .diag-sep {
  color: var(--text-4);
  font-family: var(--mono);
  padding: 0 1px;
}
.hero-diag .diag-hint {
  color: var(--text-3);
  font-family: var(--mono);
  font-size: var(--fs-2xs);
  letter-spacing: 0.04em;
}
.hero-diag.is-ok .diag-dot { background: var(--accent); }
.hero-diag.is-ok { border-color: color-mix(in srgb, var(--accent) 30%, var(--hairline)); }
.hero-diag.is-tight .diag-dot { background: var(--ochre); }
.hero-diag.is-tight { border-color: color-mix(in srgb, var(--ochre) 35%, var(--hairline)); }
.hero-diag.is-over .diag-dot { background: var(--rust); }
.hero-diag.is-over { border-color: color-mix(in srgb, var(--rust) 35%, var(--hairline)); }
.hero-diag.is-ahead .diag-dot { background: var(--marine); }
.hero-diag.is-ahead { border-color: color-mix(in srgb, var(--marine) 35%, var(--hairline)); }
.hero-diag.is-early .diag-dot { background: var(--text-3); }
/* Sprint 19 : diag-pulse retiré (slop), le tone is-early peut afficher
   un dot statique. Si rien à dire le matin, on retournera None côté Python. */

/* ===== Hero dynamic color (sprint 18, polish signature) =====
   Lorsque hero-diag est tight/over, on teinte aussi le hero-value pour que
   le glance soit immédiat même sans lire le label. */
.card-hero:has(.hero-diag.is-over) .hero-num .value { color: var(--rust); }
.card-hero:has(.hero-diag.is-over) .hero-num .unit { color: color-mix(in srgb, var(--rust) 70%, var(--text-3)); }
.card-hero:has(.hero-diag.is-tight) .hero-num .value { color: var(--ochre); }
.card-hero:has(.hero-diag.is-tight) .hero-num .unit { color: color-mix(in srgb, var(--ochre) 70%, var(--text-3)); }

/* Fallback browsers sans :has support : on garde la couleur default. */

/* Sprint 19 : watermark .spark-watermark supprimé (audit) — redondant avec
   "moy XXXX" déjà dans section-head, et bruit slop sans valeur ajoutée.
   Le focal point devient la signature visuelle : today dot + segment accent. */
.sparkline .spark-past { color: var(--text-3); }
.sparkline .spark-today-label {
  fill: var(--accent);
  font-weight: 500;
  letter-spacing: 0.16em;
}

/* Sprint 19 : wordmark heartbeat pulse 5x supprimé (audit anti-slop).
   Le dot reste statique. Si on veut le "signal vivant" plus tard, on peut
   le brancher sur un événement réel (premier log du jour, etc.) plutôt que
   sur un pulse au load. */

/* ===== Entry wrap + swipe-to-delete (sprint 19, mobile-first) =====
   Pattern iOS native : swipe gauche révèle un fond rouge "Supprimer",
   tap dessus = delete. Tap normal = ouvre l'édition. Pas de hx-confirm
   natif (bug iOS PWA), confirmation via le geste lui-même.

   Structure :
   .entry-wrap (overflow hidden, position relative)
   ├── .entry-swipe-action (absolute right, full height, visible quand .entry est translaté)
   └── .entry (translation négative en X via JS) */

.entry-wrap {
  position: relative;
  overflow: hidden;
  /* Anim fade-out à la suppression */
  transition: opacity 0.18s var(--ease), max-height 0.22s var(--ease), margin 0.22s var(--ease);
  max-height: 80px;
}
.entry-wrap.is-removing {
  opacity: 0;
  max-height: 0;
  margin: 0;
  pointer-events: none;
}
.entry-swipe-action {
  position: absolute;
  inset: 0 0 0 auto;
  width: 110px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  background: var(--rust);
  color: #fff;
  border: 0;
  cursor: pointer;
  font-family: var(--sans);
  font-size: var(--fs-xs);
  font-weight: 500;
  letter-spacing: 0.02em;
  padding: 0;
  opacity: 0;
  transition: opacity 0.12s var(--ease);
  z-index: 0;
}
.entry-swipe-action svg { stroke-width: 1.6; }
.entry-swipe-action span { line-height: 1; }
.entry-wrap.is-swiping .entry-swipe-action,
.entry-wrap.is-swiped .entry-swipe-action {
  opacity: 1;
}
.entry-wrap .entry {
  position: relative;
  z-index: 1;
  background: var(--bg);
  /* Translation pilotée par JS via .style.transform pendant le drag, puis CSS pour la transition snap. */
  transition: transform 0.22s var(--ease);
  /* user-select: none pendant le swipe pour éviter le text-select intempestif */
  touch-action: pan-y;
}
.entry-wrap.is-swiping .entry { transition: none; }
.entry-wrap.is-swiped .entry { transform: translateX(-110px); }

/* Sur desktop (hover possible), on n'expose pas le swipe — les boutons inline gèrent. */
@media (hover: hover) and (pointer: fine) {
  .entry-wrap .entry-swipe-action { display: none; }
}

/* Sur mobile, on enlève les boutons inline (.entry-actions) parce que le swipe fait le job.
   Le bouton dupliquer reste accessible via long-press → menu (futur), pour l'instant on
   garde dupliquer visible sur tap. */
@media (hover: none) and (pointer: coarse) {
  .entry-wrap .entry-actions .entry-action-btn.destructive { display: none; }
  .entry-wrap .entry-actions { opacity: 0.55; }
}

/* ===== Duplicate picker dialog (sprint 19) =====
   3 chips Hier / Aujourd'hui / Demain en row + un date input pour autre jour.
   Pattern Apple Reminders / Things, mais cleaner pour Kale operator. */
.dialog.duplicate-dialog .dialog-inner { max-width: 360px; }
.dialog.duplicate-dialog .dialog-sub {
  font-family: var(--mono);
  font-size: var(--fs-xs);
  color: var(--text-3);
  letter-spacing: 0.04em;
  text-overflow: ellipsis;
  overflow: hidden;
  white-space: nowrap;
}
.dup-day-row {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 8px;
  margin: 18px 0 16px;
}
.dup-day-btn {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  padding: 14px 8px;
  border-radius: var(--r-md);
  border: 1px solid var(--hairline);
  background: var(--surface);
  color: var(--text);
  cursor: pointer;
  font-family: var(--sans);
  transition: border-color 0.15s var(--ease), background 0.15s var(--ease), transform 0.08s var(--ease);
}
.dup-day-btn:hover { border-color: var(--text-3); background: var(--surface-2); }
.dup-day-btn:active { transform: scale(0.97); }
.dup-day-btn.is-default {
  border-color: color-mix(in srgb, var(--accent) 35%, var(--hairline));
  background: color-mix(in srgb, var(--accent) 6%, var(--surface));
}
.dup-day-btn .dup-day-label {
  font-size: var(--fs-sm);
  font-weight: 500;
  line-height: 1;
}
.dup-day-btn .dup-day-iso {
  font-family: var(--mono);
  font-size: var(--fs-2xs);
  color: var(--text-3);
  letter-spacing: 0.04em;
  line-height: 1;
}
.dup-date-custom {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 14px;
  border-radius: var(--r-md);
  border: 1px solid var(--hairline);
  background: var(--surface);
  margin-bottom: 14px;
}
.dup-custom-label {
  font-family: var(--sans);
  font-size: var(--fs-sm);
  color: var(--text-2);
}
.dup-custom-input {
  background: transparent;
  border: 0;
  outline: none;
  color: var(--text);
  font-family: var(--mono);
  font-size: var(--fs-sm);
  text-align: right;
  width: 130px;
}

/* ===== Pull-to-refresh indicator (sprint 20) =====
   Barre fine accent en haut de la viewport qui grandit au pull.
   Pas un spinner rond classique (slop), juste une ligne signature. */
.ptr-indicator {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: 3px;
  background: var(--accent);
  transform-origin: top;
  transform: scaleY(0);
  transition: transform 0.18s var(--ease), opacity 0.18s var(--ease);
  z-index: var(--z-ptr);
  pointer-events: none;
  opacity: 0.55;
}
.ptr-indicator.is-ready { opacity: 1; }
.ptr-indicator.is-loading {
  transform: scaleY(1) !important;
  /* Pendant le reload, ligne pleine accent qui pulse une fois.
     Bounded par la durée du reload (250ms + roundtrip), pas d'infinite. */
  opacity: 1;
  animation: ptr-load 0.6s ease-out infinite;
}
@keyframes ptr-load {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.55; }
}

/* ===== Settings danger zone (sprint 20) =====
   Section destructive séparée en bas du dialog settings, hairline en haut
   pour signaler la limite. Pas dans le form (évite submit accidentel). */
.dialog-danger-zone {
  border-top: 1px solid var(--hairline);
  padding: 16px 22px 20px;
  margin: 0 -22px -20px;
  background: color-mix(in srgb, var(--rust) 4%, transparent);
}
.danger-zone-label {
  font-family: var(--mono);
  font-size: var(--fs-3xs);
  color: var(--rust);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  margin-bottom: 10px;
}
.danger-btn {
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
  padding: 12px 14px;
  background: transparent;
  border: 1px solid color-mix(in srgb, var(--rust) 40%, var(--hairline));
  border-radius: var(--r-md);
  color: var(--text);
  cursor: pointer;
  text-align: left;
  font-family: var(--sans);
  transition: border-color 0.15s var(--ease), background 0.15s var(--ease);
}
.danger-btn:hover {
  border-color: var(--rust);
  background: color-mix(in srgb, var(--rust) 8%, transparent);
}
.danger-btn:active { transform: scale(0.98); }
.danger-btn .danger-btn-label {
  font-size: var(--fs-base);
  font-weight: 500;
  color: var(--rust);
  line-height: 1.2;
}
.danger-btn .danger-btn-sub {
  font-size: var(--fs-xs);
  color: var(--text-3);
  letter-spacing: -0.005em;
}
/* Bouton solide rouge pour confirm destruction (deuxième tap, opt-in clair) */
.danger-btn-solid {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 10px 20px;
  background: var(--rust);
  border: 1px solid var(--rust);
  border-radius: var(--r-md);
  color: #fff;
  cursor: pointer;
  font-family: var(--sans);
  font-size: var(--fs-base);
  font-weight: 500;
  letter-spacing: -0.005em;
  transition: background 0.15s var(--ease), transform 0.08s var(--ease);
}
.danger-btn-solid:hover {
  background: color-mix(in srgb, var(--rust) 88%, #000);
}
.danger-btn-solid:active { transform: scale(0.97); }
.danger-btn-solid:disabled {
  opacity: 0.6;
  cursor: progress;
}
.dialog.reset-confirm .dialog-inner { max-width: 360px; }

/* ===== Touch-action global (sprint 21, audit) =====
   Élimine les 300ms de tap delay sur iOS Safari < 16 et certains Android.
   `manipulation` permet le pan/zoom natifs mais coupe le double-tap-to-zoom
   et le tap-delay sur les éléments interactifs. */
button,
a,
[role="button"],
.fab,
.day-nav-btn,
.meal-add-btn,
.entry-action-btn,
.chip-quick,
.dup-day-btn,
.danger-btn,
.danger-btn-solid,
.primary-btn,
.ghost-btn,
.action-sheet-item {
  touch-action: manipulation;
}

/* =================================================================
   PHOTO CAMERA FULLSCREEN (sprint 26, impeccable craft photo-first)
   =================================================================
   Pattern : un <dialog> fullscreen avec 4 layers (capture / analyzing /
   confirm / empty). Les layers sont absolument positionnés, on switch
   leur visibilité via data-state sur le parent.

   Color strategy : Restrained. Caméra preview prend tout, l'UI overlay
   est minimaliste, accent vert uniquement sur shutter ring + CTA commit.

   Theme scene : PE au déjeuner à 13h, plateau devant lui, iPhone d'une
   main. La photo doit se prendre comme un Snapchat, pas comme une
   procédure administrative. Dark mode pour cohérence app.
*/

.photo-camera {
  /* Override dialog defaults : fullscreen sans border ni padding */
  position: fixed;
  inset: 0;
  width: 100vw;
  height: 100dvh;
  max-width: 100vw;
  max-height: 100dvh;
  margin: 0;
  padding: 0;
  border: 0;
  background: var(--bg);
  color: var(--text);
  z-index: var(--z-plate-overlay);
  overflow: hidden;
}
.photo-camera::backdrop {
  background: var(--bg);
}
.photo-camera:not([open]) { display: none; }

/* Layers : tous absolutely positioned, montrés selon data-state.
   Sprint 29 polish : fade-in 180ms quand un layer devient actif. Pas de slide
   horizontal (=trop bling), juste opacity. Pas de fade-out (un seul layer
   actif à la fois, le switch est instant côté hide). */
.pc-layer {
  position: absolute;
  inset: 0;
  display: none;
  flex-direction: column;
  justify-content: space-between;
}
.photo-camera[data-state="capture"]   .pc-layer-capture,
.photo-camera[data-state="analyzing"] .pc-layer-analyzing,
.photo-camera[data-state="confirm"]   .pc-layer-confirm,
.photo-camera[data-state="empty"]     .pc-layer-empty {
  display: flex;
  animation: pc-fade-in 0.18s var(--ease) both;
}
@keyframes pc-fade-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .pc-layer { animation: none !important; }
}

/* ===== Layer 1 : Capture caméra ===== */

.pc-video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  background: var(--bg);
}
/* Voile très léger pour rendre le UI overlay lisible sans masquer la photo */
.pc-veil {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    linear-gradient(to bottom, rgba(10, 11, 14, 0.55) 0%, rgba(10, 11, 14, 0) 18%, rgba(10, 11, 14, 0) 60%, rgba(10, 11, 14, 0.62) 100%);
}
.pc-veil-dim {
  background: rgba(10, 11, 14, 0.72);
}

.pc-head {
  position: relative;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: max(20px, env(safe-area-inset-top)) 20px 0;
  gap: 12px;
}
.pc-icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  width: 40px;
  height: 40px;
  border-radius: 999px;
  background: rgba(10, 11, 14, 0.55);
  border: 1px solid rgba(242, 243, 245, 0.16);
  color: var(--text);
  cursor: pointer;
  transition: background 0.15s var(--ease), transform 0.08s var(--ease);
  padding: 0;
}
.pc-icon-btn:hover { background: rgba(10, 11, 14, 0.75); }
.pc-icon-btn:active { transform: scale(0.94); }
.pc-icon-btn.pc-gallery {
  width: auto;
  padding: 0 14px 0 10px;
}
.pc-icon-btn-label {
  font-family: var(--mono);
  font-size: var(--fs-3xs);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text-2);
}

.pc-foot {
  position: relative;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  padding: 0 20px max(36px, calc(env(safe-area-inset-bottom) + 24px));
}
.pc-shutter {
  width: 78px;
  height: 78px;
  border-radius: 50%;
  border: 4px solid var(--accent);
  background: transparent;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: transform 0.1s var(--ease);
  padding: 0;
}
.pc-shutter:active { transform: scale(0.92); }
.pc-shutter-inner {
  display: block;
  width: 60px;
  height: 60px;
  border-radius: 50%;
  background: var(--accent);
  transition: background 0.12s var(--ease), transform 0.12s var(--ease);
}
.pc-shutter:active .pc-shutter-inner {
  background: color-mix(in srgb, var(--accent) 75%, #000);
  transform: scale(0.92);
}
.pc-shutter:disabled { opacity: 0.4; cursor: progress; }
.pc-hint {
  font-family: var(--mono);
  font-size: var(--fs-3xs);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgba(242, 243, 245, 0.7);
  margin: 0;
  text-align: center;
}

/* ===== Layer 2 : Analyzing ===== */

.pc-still {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.pc-analyze {
  position: relative;
  z-index: 2;
  margin: auto;
  width: 100%;
  max-width: 320px;
  padding: 0 28px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 18px;
}
.pc-progress {
  width: 100%;
  height: 2px;
  background: rgba(242, 243, 245, 0.14);
  border-radius: 2px;
  overflow: hidden;
}
.pc-progress-bar {
  display: block;
  width: 22%;
  height: 100%;
  background: var(--accent);
  border-radius: 2px;
  transform-origin: left center;
  animation: pc-progress-slide 1.4s cubic-bezier(0.4, 0, 0.2, 1) infinite;
}
@keyframes pc-progress-slide {
  0%   { transform: translateX(-100%); width: 22%; }
  50%  { width: 35%; }
  100% { transform: translateX(450%); width: 22%; }
}
@media (prefers-reduced-motion: reduce) {
  .pc-progress-bar { animation: none; width: 60%; }
}
.pc-analyze-label {
  font-family: var(--mono);
  font-size: var(--fs-xs);
  color: var(--text-2);
  letter-spacing: 0.08em;
  text-align: center;
  margin: 0;
}
.pc-cancel-analyze { margin-top: 4px; }

/* ===== Layer 3 : Confirm ===== */

.pc-layer-confirm {
  background: var(--bg);
  overflow-y: auto;
  padding: 0;
}
.pc-confirm-head {
  display: grid;
  grid-template-columns: 56px 1fr 40px;
  gap: 14px;
  align-items: center;
  padding: max(18px, env(safe-area-inset-top)) 20px 18px;
  border-bottom: 1px solid var(--hairline);
  background: var(--bg);
  position: sticky;
  top: 0;
  z-index: 3;
}
.pc-thumb {
  width: 56px;
  height: 56px;
  border-radius: var(--r-md);
  object-fit: cover;
  background: var(--surface);
}
.pc-confirm-meta { min-width: 0; }
.pc-confirm-title {
  font-family: var(--sans);
  font-size: var(--fs-md);
  font-weight: 500;
  color: var(--text);
  letter-spacing: -0.01em;
  margin: 0 0 2px;
}
.pc-confirm-sub {
  font-family: var(--mono);
  font-size: var(--fs-3xs);
  color: var(--text-3);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  margin: 0;
}

.pc-plate {
  flex: 1;
  display: flex;
  flex-direction: column;
  padding: 12px 20px 12px;
}
.pc-plate-item {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: baseline;
  gap: 8px 16px;
  padding: 14px 0;
  border-bottom: 1px solid var(--hairline-soft);
  transition: opacity 0.18s var(--ease), max-height 0.22s var(--ease);
  max-height: 100px;
}
.pc-plate-item:last-child { border-bottom: none; }
.pc-plate-item.is-removing {
  opacity: 0;
  max-height: 0;
  padding: 0;
  pointer-events: none;
}
.pc-plate-item-name {
  font-family: var(--sans);
  font-size: var(--fs-base);
  color: var(--text);
  letter-spacing: -0.005em;
  line-height: 1.25;
}
.pc-plate-item-kcal {
  font-family: var(--mono);
  font-size: var(--fs-sm);
  color: var(--text);
  letter-spacing: -0.01em;
}
.pc-plate-item-meta {
  grid-column: 1 / -1;
  display: flex;
  align-items: center;
  gap: 10px;
  font-family: var(--mono);
  font-size: var(--fs-xs);
  color: var(--text-3);
  letter-spacing: 0.04em;
  margin-top: 2px;
}
.pc-plate-item-grams {
  display: inline-flex;
  align-items: baseline;
  gap: 4px;
}
.pc-plate-item-grams input {
  background: transparent;
  border: 0;
  border-bottom: 1px dashed var(--text-4);
  color: var(--text);
  font-family: var(--mono);
  font-size: var(--fs-sm);
  width: 52px;
  text-align: right;
  padding: 2px 0;
  outline: none;
  caret-color: var(--accent);
}
.pc-plate-item-grams input:focus { border-bottom-color: var(--accent); }
.pc-plate-item-grams .unit { color: var(--text-3); }
.pc-plate-item-macros {
  color: var(--text-4);
  letter-spacing: 0.02em;
}
.pc-plate-item-remove {
  margin-left: auto;
  background: transparent;
  border: 0;
  padding: 6px;
  color: var(--text-4);
  cursor: pointer;
  transition: color 0.15s var(--ease);
}
.pc-plate-item-remove:hover { color: var(--rust); }
.pc-plate-item-remove svg { width: 16px; height: 16px; }

.pc-confirm-time {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 20px;
  border-top: 1px solid var(--hairline-soft);
}
.pc-confirm-time-label {
  font-family: var(--mono);
  font-size: var(--fs-3xs);
  color: var(--text-3);
  letter-spacing: 0.16em;
  text-transform: uppercase;
}
#pc-time-input {
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--hairline);
  color: var(--text);
  font-family: var(--mono);
  font-size: var(--fs-sm);
  text-align: right;
  width: 72px;
  padding: 4px 0;
  outline: none;
  caret-color: var(--accent);
}
#pc-time-input:focus { border-bottom-color: var(--accent); }

.pc-confirm-foot {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 10px;
  padding: 14px 20px max(20px, calc(env(safe-area-inset-bottom) + 14px));
  border-top: 1px solid var(--hairline);
  background: var(--bg);
  position: sticky;
  bottom: 0;
  z-index: 3;
}
.pc-commit {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  padding: 14px 20px;
}
.pc-commit-kcal { opacity: 0.85; font-size: var(--fs-sm); }
.pc-commit:disabled { opacity: 0.5; cursor: not-allowed; }
.pc-commit.is-loading { opacity: 0.72; cursor: progress; }

/* ===== Layer 4 : Empty / no items detected ===== */

.pc-layer-empty {
  align-items: center;
  justify-content: center;
  padding: 32px;
}
.pc-empty {
  max-width: 320px;
  text-align: center;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.pc-empty-title {
  font-family: var(--sans);
  font-size: var(--fs-lg);
  color: var(--text);
  letter-spacing: -0.01em;
  margin: 0;
  font-weight: 500;
}
.pc-empty-sub {
  font-family: var(--mono);
  font-size: var(--fs-sm);
  color: var(--text-3);
  letter-spacing: 0.02em;
  line-height: 1.6;
  margin: 0;
}
.pc-empty-actions {
  display: flex;
  gap: 10px;
  justify-content: center;
  margin-top: 12px;
}

/* =================================================================
   HEALTH CARD (sprint 27, Apple Health webhook)
   =================================================================
   Card minimaliste qui affiche pas / sommeil / actif / FC repos quand
   les données sont synced via Health Auto Export. Pas de chart, juste
   les valeurs glanceable, deltas vs moy 7j.
*/

.card-health {
  /* Sprint 32 : hérite du .card (tuile surface). Pas de border-top ni padding
     custom, la tuile gère. */
}
.health-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 14px 20px;
}
.health-metric {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 2px 0;
}
.health-metric-label {
  font-family: var(--mono);
  font-size: var(--fs-3xs);
  color: var(--text-3);
  letter-spacing: 0.16em;
  text-transform: uppercase;
}
.health-metric-value {
  font-family: var(--mono);
  font-size: 26px;
  font-weight: 500;
  color: var(--text);
  letter-spacing: -0.02em;
  line-height: 1.1;
}
.health-metric-delta {
  font-family: var(--mono);
  font-size: var(--fs-2xs);
  color: var(--text-3);
  letter-spacing: 0.04em;
}
.health-metric-delta.up { color: var(--accent); }
.health-metric-delta.down { color: var(--ochre); }

/* Diagnostic pill tone "sleep" : marine, signal nuit courte (sprint 27) */
.hero-diag.is-sleep .diag-dot { background: var(--marine); }
.hero-diag.is-sleep {
  border-color: color-mix(in srgb, var(--marine) 40%, var(--hairline));
}

/* Sprint 28 : streak silencieux dans la sparkline */
.sparkline .spark-streak {
  fill: var(--accent);
  font-weight: 500;
  letter-spacing: 0.06em;
  opacity: 0.78;
}

/* Sprint 29 audit responsive : iPhone SE (320px) et autres petits écrans.
   Le shutter 78px + safe-area-inset peut être tight, on dégrade gracieusement. */
@media (max-width: 360px) {
  .pc-shutter { width: 68px; height: 68px; border-width: 3px; }
  .pc-shutter-inner { width: 54px; height: 54px; }
  .pc-foot { padding-bottom: max(24px, calc(env(safe-area-inset-bottom) + 16px)); }
  .pc-head { padding: max(14px, env(safe-area-inset-top)) 14px 0; gap: 8px; }
  .pc-icon-btn { width: 36px; height: 36px; }
  .pc-icon-btn.pc-gallery { padding: 0 10px 0 8px; }
  .pc-hint { font-size: 8.5px; letter-spacing: 0.14em; }
  /* Confirm head : reduce thumb si très petit */
  .pc-confirm-head { grid-template-columns: 44px 1fr 36px; gap: 10px; padding: 14px 14px 14px; }
  .pc-thumb { width: 44px; height: 44px; }
  .pc-plate { padding: 10px 14px; }
  /* Health card : auto-fit minmax 120 au lieu de 140 */
  .health-row { grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 12px 14px; }
  .health-metric-value { font-size: 22px; }
}

/* Sprint 29 audit : tabular-nums sur les valeurs numériques pour éviter le
   "jitter" quand un chiffre change (1, 9 sont plus larges que 8 en proportional). */
.health-metric-value,
.hero-num .value,
.pc-commit-kcal,
.pc-plate-item-kcal,
.macro-row .stat .num {
  font-variant-numeric: tabular-nums;
}

/* =================================================================
   INTEGRATIONS SECTION + APPLE HEALTH INFO DIALOG (sprint 30)
   =================================================================
   Section "Intégrations" dans le settings dialog, au-dessus de la zone
   destructive. Pour V1 contient juste Apple Health setup. Extensible
   plus tard (Strava, Garmin, etc).
*/

.dialog-integrations {
  border-top: 1px solid var(--hairline-soft);
  padding: 14px 22px 12px;
  margin: 0 -22px;
}
.integrations-label {
  font-family: var(--mono);
  font-size: var(--fs-3xs);
  color: var(--text-3);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  margin-bottom: 8px;
}
.integration-btn {
  width: 100%;
  display: grid;
  grid-template-columns: 32px 1fr 18px;
  gap: 12px;
  align-items: center;
  padding: 10px 12px;
  background: transparent;
  border: 1px solid var(--hairline);
  border-radius: var(--r-md);
  color: var(--text);
  cursor: pointer;
  text-align: left;
  font-family: var(--sans);
  transition: border-color 0.15s var(--ease), background 0.15s var(--ease);
}
.integration-btn:hover { border-color: var(--text-3); background: var(--surface); }
.integration-btn:active { transform: scale(0.98); }
.integration-btn-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: var(--r-sm);
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  color: var(--accent);
}
.integration-btn-body {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.integration-btn-label {
  font-size: var(--fs-base);
  font-weight: 500;
  color: var(--text);
  line-height: 1.2;
}
.integration-btn-sub {
  font-size: var(--fs-xs);
  color: var(--text-3);
  letter-spacing: -0.005em;
}
.integration-btn-arrow {
  color: var(--text-4);
}

/* Apple Health info dialog : compact, instructionnel */
.dialog.ah-info .dialog-inner { max-width: 420px; }
.dialog.ah-info .dialog-sub {
  font-family: var(--mono);
  font-size: var(--fs-sm);
  color: var(--text-3);
  letter-spacing: 0.01em;
  line-height: 1.6;
}
.ah-step {
  display: grid;
  grid-template-columns: 24px 1fr;
  gap: 12px;
  align-items: flex-start;
  padding: 14px 0;
  border-top: 1px solid var(--hairline-soft);
}
.ah-step:first-of-type { border-top: none; }
.ah-step-num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--accent) 18%, transparent);
  color: var(--accent);
  font-family: var(--mono);
  font-size: var(--fs-xs);
  font-weight: 500;
}
.ah-step-body { min-width: 0; }
.ah-step-title {
  font-family: var(--sans);
  font-size: var(--fs-sm);
  font-weight: 500;
  color: var(--text);
  margin: 0 0 6px;
  line-height: 1.3;
}
.ah-step-detail {
  font-family: var(--mono);
  font-size: var(--fs-xs);
  color: var(--text-3);
  letter-spacing: 0.01em;
  line-height: 1.5;
  margin: 4px 0 0;
  word-break: break-word;
}
.ah-code,
.ah-code-block {
  font-family: var(--mono);
  font-size: var(--fs-xs);
  background: var(--surface);
  border: 1px solid var(--hairline-soft);
  padding: 1px 6px;
  border-radius: var(--r-sm);
  color: var(--text);
  letter-spacing: 0;
}
.ah-code-block {
  display: inline-block;
  margin-top: 6px;
  padding: 4px 8px;
  word-break: break-all;
}

/* Sprint 34 : footer + version badge visible pour debug cache iOS.
   Position discrète en bas, juste avant le FAB safe-area. */
.app-footer {
  display: flex;
  justify-content: center;
  padding: 18px 0 8px;
  opacity: 0.4;
}
.version-badge {
  font-family: var(--mono);
  font-size: var(--fs-2xs);
  color: var(--text-4);
  letter-spacing: 0.14em;
  text-transform: uppercase;
}
