/* ==========================================================================
   Design system « Cadran »
   L'interface emprunte au combiné d'instruments : graduations, aiguilles, rétroéclairage ambre.
   Mode jour par défaut, mode nuit via prefers-color-scheme ou [data-theme="dark"].
   Toutes les classes sont préfixées « o- » : cohabitation possible avec l'ancien app.css pendant la migration.
   Polices IBM Plex Sans, IBM Plex Mono et Michroma auto-hébergées (CSP font-src 'self').
   ========================================================================== */

/* ---------- Polices auto-hébergées (licence SIL OFL 1.1, fichiers LICENSE-*.txt dans fonts/) ---------- */
@font-face { font-family: "IBM Plex Sans"; font-style: normal; font-weight: 400; font-display: swap; src: url("../fonts/ibm-plex-sans-latin-400-normal.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+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: "IBM Plex Sans"; font-style: normal; font-weight: 400; font-display: swap; src: url("../fonts/ibm-plex-sans-latin-ext-400-normal.woff2") format("woff2"); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: "IBM Plex Sans"; font-style: normal; font-weight: 500; font-display: swap; src: url("../fonts/ibm-plex-sans-latin-500-normal.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+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: "IBM Plex Sans"; font-style: normal; font-weight: 500; font-display: swap; src: url("../fonts/ibm-plex-sans-latin-ext-500-normal.woff2") format("woff2"); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: "IBM Plex Sans"; font-style: normal; font-weight: 600; font-display: swap; src: url("../fonts/ibm-plex-sans-latin-600-normal.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+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: "IBM Plex Sans"; font-style: normal; font-weight: 600; font-display: swap; src: url("../fonts/ibm-plex-sans-latin-ext-600-normal.woff2") format("woff2"); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: "IBM Plex Mono"; font-style: normal; font-weight: 400; font-display: swap; src: url("../fonts/ibm-plex-mono-latin-400-normal.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+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: "IBM Plex Mono"; font-style: normal; font-weight: 500; font-display: swap; src: url("../fonts/ibm-plex-mono-latin-500-normal.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+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: "Michroma"; font-style: normal; font-weight: 400; font-display: swap; src: url("../fonts/michroma-latin-400-normal.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+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }


:root {
  /* Surfaces et encre : neutres froids, légèrement bleutés */
  --o-bg: #e8ecf1;
  --o-surface: #f7f9fb;
  --o-surface-2: #eef2f6;
  --o-sunken: #dfe5ec;
  --o-ink: #10161f;
  --o-ink-2: #46536a;
  --o-ink-3: #66738a;
  --o-line: #c7d0db;
  --o-line-soft: #dbe1e9;
  /* Rétroéclairage : l'unique accent. Sert à ce qui est « allumé » (sélection, aiguille, valeur active). */
  --o-glow: #a65400;
  --o-glow-fill: #c96a00;
  --o-glow-soft: color-mix(in srgb, var(--o-glow-fill) 14%, transparent);
  --o-on-glow: #ffffff;
  /* Sémantique (zones du cadran) — distincte de l'accent */
  --o-go: #217a52;
  --o-info: #1d6894;
  --o-caution: #9a5b00;
  --o-stop: #b3261e;
  --o-go-soft: color-mix(in srgb, var(--o-go) 13%, transparent);
  --o-info-soft: color-mix(in srgb, var(--o-info) 13%, transparent);
  --o-caution-soft: color-mix(in srgb, var(--o-caution) 15%, transparent);
  --o-stop-soft: color-mix(in srgb, var(--o-stop) 12%, transparent);
  --o-scrim: rgba(16, 22, 31, .32);
  --o-shadow: 0 1px 0 rgba(255, 255, 255, .7) inset, 0 10px 30px -18px rgba(16, 22, 31, .35);

  /* Typographie */
  --o-font: "IBM Plex Sans", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --o-font-num: "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, monospace;
  --o-font-label: "Michroma", "Eurostile", "Arial Narrow", sans-serif;
  --o-t-xs: 12px; --o-t-sm: 13.5px; --o-t-md: 15px; --o-t-lg: 17px; --o-t-xl: 20px; --o-t-2xl: 26px; --o-t-3xl: 34px; --o-t-4xl: 44px;

  /* Géométrie */
  --o-s1: 4px; --o-s2: 8px; --o-s3: 12px; --o-s4: 16px; --o-s5: 20px; --o-s6: 24px; --o-s8: 32px; --o-s10: 40px;
  --o-r-ctl: 8px;   /* commandes */
  --o-r-card: 14px; /* cartes */
  --o-r-dial: 20px; /* instruments */
  --o-sidebar: 248px;
  --o-tap: 44px;    /* cible tactile minimale (iPhone) */

  /* Mouvement : l'aiguille dépasse légèrement puis se pose ; le reste est bref */
  --o-ease: cubic-bezier(.2, .8, .2, 1);
  --o-ease-needle: cubic-bezier(.2, .9, .25, 1.15);
  --o-dur: 180ms;
  --o-dur-needle: 800ms;
  color-scheme: light;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --o-bg: #0a111e; --o-surface: #101a2b; --o-surface-2: #142035; --o-sunken: #080e19;
    --o-ink: #e6edf7; --o-ink-2: #a3b2c8; --o-ink-3: #7d8da6; --o-line: #24344e; --o-line-soft: #1a2840;
    --o-glow: #ffb547; --o-glow-fill: #ffb547; --o-on-glow: #1a1206;
    --o-go: #4fd18f; --o-info: #7cc8ff; --o-caution: #ffb547; --o-stop: #ff6b5e;
    --o-scrim: rgba(3, 6, 12, .6);
    --o-shadow: 0 1px 0 rgba(255, 255, 255, .03) inset, 0 16px 40px -20px rgba(0, 0, 0, .8);
    color-scheme: dark;
  }
}
:root[data-theme="dark"] {
  --o-bg: #0a111e; --o-surface: #101a2b; --o-surface-2: #142035; --o-sunken: #080e19;
  --o-ink: #e6edf7; --o-ink-2: #a3b2c8; --o-ink-3: #7d8da6; --o-line: #24344e; --o-line-soft: #1a2840;
  --o-glow: #ffb547; --o-glow-fill: #ffb547; --o-on-glow: #1a1206;
  --o-go: #4fd18f; --o-info: #7cc8ff; --o-caution: #ffb547; --o-stop: #ff6b5e;
  --o-scrim: rgba(3, 6, 12, .6);
  --o-shadow: 0 1px 0 rgba(255, 255, 255, .03) inset, 0 16px 40px -20px rgba(0, 0, 0, .8);
  color-scheme: dark;
}

/* ---------- Base ---------- */
.o-root [hidden], .o-root[hidden] { display: none !important; }
.o-root, .o-root * { box-sizing: border-box; }
.o-root { background: var(--o-bg); color: var(--o-ink); font: 400 var(--o-t-md)/1.55 var(--o-font); -webkit-font-smoothing: antialiased; }
.o-root :focus-visible { outline: 2px solid var(--o-glow-fill); outline-offset: 2px; }
.o-root a { color: inherit; }
.o-num { font-family: var(--o-font-num); font-variant-numeric: tabular-nums; letter-spacing: -.01em; }
.o-label { font: 400 10.5px/1.3 var(--o-font-label); letter-spacing: .12em; text-transform: uppercase; color: var(--o-ink-2); }
.o-h1 { font: 600 var(--o-t-3xl)/1.1 var(--o-font); letter-spacing: -.015em; margin: 0; text-wrap: balance; }
.o-h2 { font: 600 var(--o-t-xl)/1.25 var(--o-font); margin: 0; text-wrap: balance; }
.o-h3 { font: 600 var(--o-t-lg)/1.3 var(--o-font); margin: 0; }
.o-muted { color: var(--o-ink-2); }
.o-small { font-size: var(--o-t-sm); }
.o-stack { display: grid; gap: var(--o-s4); align-content: start; }
.o-row { display: flex; flex-wrap: wrap; gap: var(--o-s2); align-items: center; }
.o-between { justify-content: space-between; }

/* ---------- Coquille : barre latérale (ordinateur), barre d'onglets (iPhone) ---------- */
.o-shell { display: grid; grid-template-columns: var(--o-sidebar) minmax(0, 1fr); min-height: 100%; }
.o-side { background: var(--o-surface); border-right: 1px solid var(--o-line); padding: var(--o-s5) var(--o-s3); display: grid; gap: var(--o-s5); align-content: start; position: sticky; top: 0; height: 100dvh; overflow-y: auto; }
.o-brand { font: 400 13px var(--o-font-label); letter-spacing: .16em; padding: 0 var(--o-s2); }
.o-brand b { color: var(--o-glow); font-weight: 400; }
.o-spaces { display: grid; grid-template-columns: 1fr 1fr; background: var(--o-sunken); border-radius: var(--o-r-ctl); padding: 3px; gap: 3px; }
.o-spaces a { text-align: center; text-decoration: none; padding: 7px 4px; border-radius: 6px; font: 600 var(--o-t-xs) var(--o-font); color: var(--o-ink-2); }
.o-spaces a[aria-current="true"] { background: var(--o-surface); color: var(--o-ink); box-shadow: var(--o-shadow); }
.o-nav { display: grid; gap: 1px; }
.o-nav .o-label { padding: var(--o-s3) var(--o-s2) var(--o-s1); }
.o-nav a { display: flex; align-items: center; gap: var(--o-s3); padding: 8px var(--o-s2); border-radius: var(--o-r-ctl); text-decoration: none; color: var(--o-ink-2); font-size: var(--o-t-sm); font-weight: 500; position: relative; }
.o-nav a:hover { background: var(--o-surface-2); color: var(--o-ink); }
.o-nav a[aria-current="page"] { color: var(--o-ink); background: var(--o-surface-2); }
.o-nav a[aria-current="page"]::before { content: ""; position: absolute; left: -12px; top: 9px; bottom: 9px; width: 3px; border-radius: 0 3px 3px 0; background: var(--o-glow-fill); }
.o-nav .o-count { margin-left: auto; font: 500 11px var(--o-font-num); color: var(--o-ink-3); }
.o-main { min-width: 0; padding: var(--o-s6) var(--o-s8) var(--o-s10); display: grid; gap: var(--o-s6); align-content: start; }
.o-topbar { display: flex; flex-wrap: wrap; gap: var(--o-s3); align-items: center; justify-content: space-between; }
.o-tabbar { display: none; }

@media (max-width: 860px) {
  .o-shell { grid-template-columns: minmax(0, 1fr); }
  .o-side { display: none; }
  .o-main { padding: var(--o-s4) var(--o-s4) calc(var(--o-s10) + 64px + env(safe-area-inset-bottom, 0px)); gap: var(--o-s5); }
  .o-tabbar { display: grid; grid-template-columns: repeat(5, 1fr); position: fixed; left: 0; right: 0; bottom: 0; z-index: 20; background: color-mix(in srgb, var(--o-surface) 92%, transparent); backdrop-filter: blur(12px); border-top: 1px solid var(--o-line); padding: 6px 4px calc(6px + env(safe-area-inset-bottom, 0px)); }
  .o-tabbar a { display: grid; justify-items: center; gap: 2px; min-height: var(--o-tap); padding-top: 4px; text-decoration: none; font: 500 10.5px var(--o-font); color: var(--o-ink-3); }
  .o-tabbar a[aria-current="page"] { color: var(--o-glow); }
  .o-tabbar svg { width: 22px; height: 22px; }
}

/* ---------- Recherche universelle ---------- */
.o-search { display: flex; align-items: center; gap: var(--o-s2); min-width: min(360px, 100%); flex: 1 1 260px; max-width: 520px; background: var(--o-surface); border: 1px solid var(--o-line); border-radius: var(--o-r-ctl); padding: 0 var(--o-s3); min-height: 40px; color: var(--o-ink-3); }
.o-search input { flex: 1; min-width: 0; border: 0; background: none; color: var(--o-ink); font: inherit; font-size: var(--o-t-sm); padding: 9px 0; outline: none; }
.o-kbd { font: 500 11px var(--o-font-num); border: 1px solid var(--o-line); border-bottom-width: 2px; border-radius: 5px; padding: 1px 6px; color: var(--o-ink-2); }

/* ---------- Boutons et commandes ---------- */
.o-btn { display: inline-flex; align-items: center; justify-content: center; gap: var(--o-s2); min-height: 38px; padding: 0 var(--o-s4); border-radius: var(--o-r-ctl); border: 1px solid transparent; font: 600 var(--o-t-sm) var(--o-font); cursor: pointer; text-decoration: none; transition: background var(--o-dur) var(--o-ease), border-color var(--o-dur) var(--o-ease), transform var(--o-dur) var(--o-ease); white-space: nowrap; }
.o-btn:active { transform: translateY(1px); }
.o-btn--primary { background: var(--o-ink); color: var(--o-bg); }
.o-btn--primary:hover { background: color-mix(in srgb, var(--o-ink) 85%, var(--o-glow-fill)); }
.o-btn--glow { background: var(--o-glow-fill); color: var(--o-on-glow); }
.o-btn--ghost { background: transparent; color: var(--o-ink); border-color: var(--o-line); }
.o-btn--ghost:hover { background: var(--o-surface-2); }
.o-btn--danger { background: transparent; color: var(--o-stop); border-color: color-mix(in srgb, var(--o-stop) 40%, transparent); }
.o-btn--sm { min-height: 30px; padding: 0 var(--o-s3); font-size: var(--o-t-xs); }
.o-btn[disabled] { opacity: .45; cursor: not-allowed; }
@media (pointer: coarse) { .o-btn { min-height: var(--o-tap); } }

.o-seg { display: inline-flex; border: 1px solid var(--o-line); border-radius: 999px; padding: 3px; gap: 2px; background: var(--o-surface); }
.o-seg button { font: 500 var(--o-t-xs) var(--o-font-num); border: 0; background: none; color: var(--o-ink-2); padding: 6px 12px; border-radius: 999px; cursor: pointer; }
.o-seg button[aria-pressed="true"] { background: var(--o-ink); color: var(--o-bg); }

/* ---------- Formulaires ---------- */
.o-form { display: grid; gap: var(--o-s4); }
.o-grid-2 { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--o-s4); }
.o-field { display: grid; gap: 6px; min-width: 0; }
.o-field > label { font-size: var(--o-t-sm); font-weight: 600; }
.o-field .o-opt { font-weight: 400; color: var(--o-ink-3); }
.o-input, .o-select, .o-textarea { width: 100%; min-height: 40px; border: 1px solid var(--o-line); border-radius: var(--o-r-ctl); background: var(--o-surface); color: var(--o-ink); font: inherit; font-size: var(--o-t-md); padding: 8px 12px; transition: border-color var(--o-dur) var(--o-ease), box-shadow var(--o-dur) var(--o-ease); }
.o-input:hover, .o-select:hover { border-color: var(--o-ink-3); }
.o-input:focus, .o-select:focus, .o-textarea:focus { outline: none; border-color: var(--o-glow-fill); box-shadow: 0 0 0 3px var(--o-glow-soft); }
.o-input[aria-invalid="true"] { border-color: var(--o-stop); }
.o-affix { position: relative; }
/* Unité centrée sur toute la hauteur du champ, place réservée pour les unités longues (« mois ») : lot L18d. */
.o-affix .o-input { display: block; width: 100%; padding-right: 3.6em; font-family: var(--o-font-num); text-align: right; font-variant-numeric: tabular-nums; }
.o-affix span { position: absolute; right: 12px; top: 0; bottom: 0; display: flex; align-items: center; margin: 0; line-height: 1; color: var(--o-ink-3); font-size: var(--o-t-sm); pointer-events: none; }
.o-help { font-size: var(--o-t-xs); color: var(--o-ink-3); }
.o-error { font-size: var(--o-t-xs); color: var(--o-stop); font-weight: 600; }
.o-source { font: 500 10.5px var(--o-font-num); color: var(--o-info); background: var(--o-info-soft); border-radius: 4px; padding: 1px 6px; justify-self: start; }
.o-range { width: 100%; accent-color: var(--o-glow-fill); min-height: 28px; }
@media (max-width: 560px) { .o-grid-2 { grid-template-columns: minmax(0, 1fr); } }

/* Plaque d'immatriculation française : saisie et affichage */
.o-plate { display: inline-flex; align-items: stretch; border: 1.5px solid var(--o-ink); border-radius: 5px; overflow: hidden; background: #fff; color: #10161f; font: 600 var(--o-t-lg) var(--o-font-num); letter-spacing: .08em; }
.o-plate::before { content: "F"; display: grid; place-items: end center; background: #1d3fa6; color: #fff; font: 600 10px var(--o-font); padding: 3px 5px; letter-spacing: 0; }
.o-plate input, .o-plate span { border: 0; background: none; color: inherit; font: inherit; letter-spacing: inherit; text-transform: uppercase; width: 11ch; padding: 4px 10px; outline: none; }
/* Plaque affichée (pas saisie) : jamais coupée sur deux lignes ; plus petite dans un texte ou un tableau (recette v12). */
.o-plate span { width: auto; white-space: nowrap; }
.kv .o-plate, td .o-plate { font-size: var(--o-t-sm); vertical-align: middle; }
.kv .o-plate span, td .o-plate span { padding: 1px 8px; }

/* ---------- Cartes et instruments ---------- */
.o-card { background: var(--o-surface); border: 1px solid var(--o-line); border-radius: var(--o-r-card); padding: var(--o-s5); display: grid; gap: var(--o-s3); align-content: start; min-width: 0; box-shadow: var(--o-shadow); }
.o-card__head { display: flex; justify-content: space-between; align-items: baseline; gap: var(--o-s3); flex-wrap: wrap; }
.o-instrument { border-radius: var(--o-r-dial); }

/* Indicateur : toujours un lien ou un bouton vers sa liste filtrée */
.o-gauges { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: var(--o-s3); }
.o-gauge { display: grid; gap: 8px; text-align: left; text-decoration: none; color: inherit; font: inherit; background: var(--o-surface); border: 1px solid var(--o-line); border-radius: var(--o-r-card); padding: var(--o-s4); cursor: pointer; box-shadow: var(--o-shadow); transition: border-color var(--o-dur) var(--o-ease), transform var(--o-dur) var(--o-ease); }
.o-gauge:hover { border-color: var(--o-glow-fill); transform: translateY(-1px); }
.o-gauge__value { font: 500 var(--o-t-2xl)/1.1 var(--o-font-num); font-variant-numeric: tabular-nums; letter-spacing: -.02em; }
.o-gauge__foot { font-size: var(--o-t-xs); color: var(--o-ink-2); }
.o-gauge__foot b { color: var(--o-caution); font-weight: 600; }
.o-ticks { height: 8px; position: relative; overflow: hidden; border-radius: 2px; background: repeating-linear-gradient(90deg, var(--o-line) 0 2px, transparent 2px 7px); }
.o-ticks > i { position: absolute; inset: 0 auto 0 0; background: repeating-linear-gradient(90deg, var(--o-glow-fill) 0 2px, transparent 2px 7px); transition: width var(--o-dur-needle) var(--o-ease); }
.o-gauge--estimate .o-gauge__value { color: var(--o-ink-2); }
.o-gauge--estimate .o-gauge__value::after { content: " prév."; font: 400 var(--o-t-xs) var(--o-font); color: var(--o-ink-3); }

/* Cadran (SVG produit par dial.js) */
.o-dial { display: grid; justify-items: center; gap: 4px; }
.o-dial svg { width: 100%; max-width: 440px; height: auto; color: var(--o-ink); overflow: visible; }
.o-dial .o-needle { transition: transform var(--o-dur-needle) var(--o-ease-needle); }
.o-dial__read { font: 500 var(--o-t-3xl)/1 var(--o-font-num); font-variant-numeric: tabular-nums; letter-spacing: -.02em; }
.o-dial__zone { font: 400 11px var(--o-font-label); letter-spacing: .12em; text-transform: uppercase; }
.o-dial text { fill: var(--o-ink-2); font: 500 11px var(--o-font-num); }

/* Registre de montants : calculateurs, finances */
.o-ledger { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, max-content); gap: 0 var(--o-s4); font-size: var(--o-t-sm); }
.o-ledger > * { padding: 7px 0; border-bottom: 1px dashed var(--o-line-soft); }
.o-ledger > :nth-child(even) { font-family: var(--o-font-num); font-variant-numeric: tabular-nums; text-align: right; }
.o-ledger .o-total { border-bottom: 0; border-top: 1.5px solid var(--o-ink); font-weight: 600; padding-top: 9px; }
.o-ledger .o-internal { color: var(--o-ink-3); }
.o-tag-internal { font: 400 9.5px var(--o-font-label); letter-spacing: .1em; text-transform: uppercase; color: var(--o-stop); border: 1px solid currentColor; border-radius: 4px; padding: 2px 5px; }

/* ---------- Bandeaux, statuts ---------- */
.o-banner { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: var(--o-s3); align-items: start; padding: var(--o-s3) var(--o-s4); border-radius: var(--o-r-ctl); font-size: var(--o-t-sm); background: var(--o-caution-soft); border: 1px solid color-mix(in srgb, var(--o-caution) 35%, transparent); }
.o-banner--info { background: var(--o-info-soft); border-color: color-mix(in srgb, var(--o-info) 35%, transparent); }
.o-banner--stop { background: var(--o-stop-soft); border-color: color-mix(in srgb, var(--o-stop) 35%, transparent); }
.o-banner::before { content: ""; width: 8px; height: 8px; margin-top: 6px; border-radius: 50%; background: var(--o-caution); }
.o-banner--info::before { background: var(--o-info); }
.o-banner--stop::before { background: var(--o-stop); }

/* Statut : forme + couleur + libellé (jamais la couleur seule) */
.o-status { display: inline-flex; align-items: center; gap: 6px; font: 600 var(--o-t-xs) var(--o-font); white-space: nowrap; padding: 3px 9px 3px 7px; border-radius: 999px; background: var(--o-surface-2); color: var(--o-ink-2); }
.o-status::before { content: ""; width: 8px; height: 8px; border-radius: 50%; border: 1.5px solid currentColor; }
.o-status--draft::before { border-style: dashed; }
.o-status--pending { color: var(--o-info); background: var(--o-info-soft); }
.o-status--active { color: var(--o-go); background: var(--o-go-soft); }
.o-status--active::before { background: currentColor; }
.o-status--expiring { color: var(--o-caution); background: var(--o-caution-soft); }
.o-status--expiring::before { background: currentColor; border-radius: 1px; transform: rotate(45deg); width: 7px; height: 7px; }
.o-status--expired, .o-status--cancelled { color: var(--o-stop); background: var(--o-stop-soft); }
.o-status--expired::before { background: currentColor; border-radius: 1px; }
.o-status--cancelled::before { background: linear-gradient(45deg, transparent 42%, currentColor 42% 58%, transparent 58%); }
.o-status--done { color: var(--o-ink); }
.o-status--done::before { background: currentColor; box-shadow: inset 0 0 0 1.5px var(--o-surface-2); }

/* ---------- Tables ---------- */
.o-table-wrap { overflow-x: auto; border: 1px solid var(--o-line); border-radius: var(--o-r-card); background: var(--o-surface); }
.o-table { width: 100%; border-collapse: collapse; font-size: var(--o-t-sm); }
.o-table th { position: sticky; top: 0; text-align: left; font: 400 10px var(--o-font-label); letter-spacing: .12em; text-transform: uppercase; color: var(--o-ink-3); background: var(--o-surface-2); padding: 11px 14px; border-bottom: 1px solid var(--o-line); white-space: nowrap; }
.o-table td { padding: 11px 14px; border-bottom: 1px solid var(--o-line-soft); vertical-align: middle; }
.o-table tr:last-child td { border-bottom: 0; }
.o-table tbody tr { transition: background var(--o-dur) var(--o-ease); }
.o-table tbody tr:hover { background: var(--o-surface-2); }
.o-table .o-amount { text-align: right; font-family: var(--o-font-num); font-variant-numeric: tabular-nums; white-space: nowrap; }
.o-table a.o-rowlink { text-decoration: none; font-weight: 600; }
.o-table a.o-rowlink:hover { text-decoration: underline; text-decoration-color: var(--o-glow-fill); text-underline-offset: 3px; }
.o-filters { display: flex; flex-wrap: wrap; gap: var(--o-s2); align-items: center; font-size: var(--o-t-xs); }
.o-filter { display: inline-flex; align-items: center; gap: 6px; background: var(--o-glow-soft); color: var(--o-ink); border-radius: 999px; padding: 4px 6px 4px 10px; font-weight: 600; }
.o-filter button { border: 0; background: none; color: var(--o-ink-2); cursor: pointer; font: inherit; padding: 0 4px; }

/* Tableau en cartes sur iPhone */
@media (max-width: 560px) {
  .o-table--stack thead { display: none; }
  .o-table--stack tr { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 4px var(--o-s3); padding: var(--o-s3) var(--o-s4); border-bottom: 1px solid var(--o-line-soft); }
  .o-table--stack td { padding: 0; border: 0; }
  .o-table--stack td[data-hide-sm] { display: none; }
}

/* ---------- Tiroir de détail (feuille plein écran sur iPhone) ---------- */
.o-scrim { position: fixed; inset: 0; background: var(--o-scrim); z-index: 40; }
.o-drawer { position: fixed; z-index: 41; top: 0; right: 0; bottom: 0; width: min(460px, 100%); background: var(--o-surface); border-left: 1px solid var(--o-line); padding: calc(var(--o-s5) + env(safe-area-inset-top, 0px)) var(--o-s5) calc(var(--o-s5) + env(safe-area-inset-bottom, 0px)); display: grid; grid-template-rows: auto minmax(0, 1fr) auto; gap: var(--o-s4); box-shadow: -20px 0 60px -30px rgba(0, 0, 0, .4); animation: o-slide var(--o-dur) var(--o-ease); }
.o-drawer__body { overflow-y: auto; min-height: 0; }
@keyframes o-slide { from { transform: translateX(24px); opacity: 0; } }
@media (max-width: 560px) { .o-drawer { top: auto; width: 100%; max-height: 88dvh; border-left: 0; border-top: 1px solid var(--o-line); border-radius: var(--o-r-card) var(--o-r-card) 0 0; animation-name: o-rise; } }
@keyframes o-rise { from { transform: translateY(32px); opacity: 0; } }

/* ---------- Historique ---------- */
.o-timeline { list-style: none; margin: 0; padding: 0; display: grid; gap: 0; }
.o-timeline li { display: grid; grid-template-columns: 74px 14px minmax(0, 1fr); gap: var(--o-s3); font-size: var(--o-t-sm); }
.o-timeline time { font: 500 var(--o-t-xs) var(--o-font-num); color: var(--o-ink-3); padding-top: 2px; text-align: right; }
.o-timeline i { position: relative; }
.o-timeline i::before { content: ""; position: absolute; left: 3px; top: 6px; width: 8px; height: 8px; border-radius: 50%; background: var(--o-surface); border: 2px solid var(--o-ink-3); }
.o-timeline i::after { content: ""; position: absolute; left: 7px; top: 18px; bottom: -6px; width: 1px; background: var(--o-line); }
.o-timeline li:last-child i::after { display: none; }
.o-timeline span { padding-bottom: var(--o-s4); }
.o-timeline .o-locked i::before { border-color: var(--o-go); background: var(--o-go); }

.o-empty { text-align: center; padding: var(--o-s8) var(--o-s4); display: grid; gap: var(--o-s2); justify-items: center; color: var(--o-ink-2); }

@media (prefers-reduced-motion: reduce) {
  .o-root *, .o-root *::before, .o-root *::after { transition-duration: 0ms !important; animation-duration: 0ms !important; }
}

/* ==========================================================================
   Pont avec app.css (lot L2) : les écrans existants passent aux jetons Cadran sans changer leur balisage.
   Les jetons d'app.css sont redéfinis à partir de ceux de Cadran ; Cadran gère lui-même le jour et la nuit.
   Spécificité :root:root (0,2,0) : l'emporte sur :root et [data-theme="light"] d'app.css.
   La refonte écran par écran viendra au lot L9.
   ========================================================================== */
:root:root {
  --o-font: "IBM Plex Sans", "Inter var", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --bg: var(--o-bg);
  --bg-elev: color-mix(in srgb, var(--o-bg) 50%, var(--o-surface));
  --surface: var(--o-surface);
  --surface-2: var(--o-surface-2);
  --surface-3: var(--o-sunken);
  --overlay: var(--o-scrim);
  --border: var(--o-line-soft);
  --border-strong: var(--o-line);
  --text: var(--o-ink);
  --text-2: var(--o-ink-2);
  --muted: var(--o-ink-3);
  --faint: color-mix(in srgb, var(--o-ink-3) 65%, var(--o-surface));
  /* Rétroéclairage ambre : l'unique accent. Remplacé par la couleur de marque si l'espace en a choisi une. */
  --accent: var(--o-glow);
  --on-accent: var(--o-on-glow);
  --success: var(--o-go);
  --warning: var(--o-caution);
  --danger: var(--o-stop);
  --info: var(--o-info);
  --shadow-sm: var(--o-shadow);
  --font: var(--o-font);
  --mono: var(--o-font-num);
  --r-sm: var(--o-r-ctl);
  --r-md: var(--o-r-card);
  --r-lg: var(--o-r-dial);
}

/* Chiffres : alignés et lisibles d'un coup d'œil, comme sur un combiné d'instruments. */
.stat-value, .kpi-value, td.num, .num, .price { font-family: var(--o-font-num); font-variant-numeric: tabular-nums; letter-spacing: -.01em; }
/* Libellés techniques : capitales espacées. */
.nav-group-label, .menu-label, .stat-label { font-family: var(--o-font-label); font-weight: 400; letter-spacing: .12em; text-transform: uppercase; font-size: 10px; }
.brand-label { font-family: var(--o-font-label); font-weight: 400; letter-spacing: .16em; text-transform: uppercase; font-size: 13px; }

/* Sélecteur d'espace (D2) : Business | Intelligence. */
.space-switch { display: grid; grid-template-columns: 1fr 1fr; gap: 3px; padding: 3px; margin: 0 var(--s-3) var(--s-3); background: var(--o-sunken); border-radius: var(--o-r-ctl); }
.space-switch a { display: flex; align-items: center; justify-content: center; gap: 6px; min-height: 34px; padding: 6px 4px; border-radius: 6px; color: var(--o-ink-2); font-size: var(--o-t-xs); font-weight: 600; text-decoration: none; }
.space-switch a:hover { color: var(--o-ink); }
.space-switch a[aria-current="true"] { background: var(--o-surface); color: var(--o-ink); box-shadow: var(--o-shadow); }
.space-switch a[aria-current="true"] .icon { color: var(--o-glow); }
.app.is-collapsed .space-switch { grid-template-columns: 1fr; margin-inline: var(--s-2); }
/* Entrée courante : repère ambre à gauche, comme une aiguille. */
.nav-item[aria-current="page"] { position: relative; }
.nav-item[aria-current="page"]::before { content: ""; position: absolute; left: 0; top: 9px; bottom: 9px; width: 3px; border-radius: 0 3px 3px 0; background: var(--o-glow-fill); }
@media (max-width: 860px) {
  .app.is-collapsed .space-switch { grid-template-columns: 1fr 1fr; margin-inline: var(--s-3); }
  .bottom-nav .space-tab { color: var(--o-ink-2); }
}

/* ---------- Tableau d'opportunités (lot L3) ---------- */
.o-board { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(250px, 1fr); gap: var(--o-s3); overflow-x: auto; padding-bottom: var(--o-s2); scroll-snap-type: x proximity; }
.o-col { display: grid; align-content: start; gap: var(--o-s2); background: var(--o-surface-2); border: 1px solid var(--o-line-soft); border-radius: var(--o-r-card); padding: var(--o-s3); min-height: 120px; scroll-snap-align: start; }
.o-col__head { display: grid; gap: 2px; padding: 0 2px var(--o-s2); border-bottom: 1px solid var(--o-line-soft); }
.o-col__sum { font: 500 var(--o-t-xs) var(--o-font-num); color: var(--o-ink-2); }
.o-col--won .o-col__head .o-label { color: var(--o-go); }
.o-col--lost { opacity: .78; }
.o-deal { display: grid; gap: 6px; background: var(--o-surface); border: 1px solid var(--o-line); border-radius: var(--o-r-ctl); padding: var(--o-s3); font-size: var(--o-t-sm); }
.o-deal:hover { border-color: var(--o-glow-fill); }
.o-deal a { font-weight: 600; color: var(--o-ink); text-decoration: none; }
.o-deal a:hover { text-decoration: underline; text-decoration-color: var(--o-glow-fill); text-underline-offset: 3px; }
.o-deal__meta { display: flex; flex-wrap: wrap; gap: 4px 10px; color: var(--o-ink-3); font-size: var(--o-t-xs); }
.o-deal__amounts { display: flex; justify-content: space-between; gap: var(--o-s2); font: 500 var(--o-t-xs) var(--o-font-num); }
.o-deal__move { display: flex; gap: 4px; }
.o-deal__move select { flex: 1; min-width: 0; min-height: 30px; font-size: var(--o-t-xs); border: 1px solid var(--o-line); border-radius: 6px; background: var(--o-surface); color: var(--o-ink); }
.o-badge-src { font: 400 9.5px var(--o-font-label); letter-spacing: .1em; text-transform: uppercase; color: var(--o-info); }
.o-tabs { display: flex; flex-wrap: wrap; gap: 4px; }
.o-tabs a { display: inline-flex; align-items: center; gap: 6px; padding: 7px 12px; border-radius: 999px; border: 1px solid var(--o-line); text-decoration: none; color: var(--o-ink-2); font-size: var(--o-t-sm); font-weight: 600; }
.o-tabs a[aria-current="page"] { background: var(--o-ink); color: var(--o-bg); border-color: var(--o-ink); }
.o-tabs .o-count { font: 500 11px var(--o-font-num); opacity: .8; }

/* Barre d'onglets iPhone : cinq libellés sur une ligne, jamais coupés au milieu d'un mot. */
@media (max-width: 860px) {
  .bottom-nav a span, .bottom-nav button span { display: block; max-width: 100%; padding: 0 2px; font-size: 10px; letter-spacing: -.01em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
}

/* Lignes de facture (lot L7) : trois colonnes sur ordinateur, empilées sur iPhone (désignation, puis quantité et prix). */
.o-table--lines .o-col-qty { width: 90px; }
.o-table--lines .o-col-price { width: 150px; }
.o-num-input { text-align: right; font-family: var(--o-font-num); font-variant-numeric: tabular-nums; }
@media (max-width: 560px) {
  .o-table--lines thead { display: none; }
  .o-table--lines tr { display: grid; grid-template-columns: 1fr 1.4fr; gap: 6px; padding: 10px 12px; border-bottom: 1px solid var(--o-line-soft); }
  .o-table--lines td { padding: 0; border: 0; }
  .o-table--lines td:first-child { grid-column: 1 / -1; }
}

/* Pastille de filtre (lot L8) : le × est un lien vers la liste sans ce filtre. */
.o-filter a { color: var(--o-ink-2); text-decoration: none; padding: 0 4px; font-weight: 700; }
.o-filter a:hover { color: var(--o-stop); }
/* Indicateur du cockpit : valeur, écart avec la période précédente. */
.o-delta { font: 500 var(--o-t-xs) var(--o-font-num); }
.o-delta--up { color: var(--o-go); }
.o-delta--down { color: var(--o-stop); }
.o-section-title { margin: var(--o-s6) 0 var(--o-s3); }

/* ---------- Intelligence (lot L9) ---------- */
/* Note d'opportunité : valeur sur 100, classe en clair, jauge graduée. */
.o-score { display: grid; gap: 4px; min-width: 0; }
.o-score__read { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 8px; font: 500 var(--o-t-xs) var(--o-font-num); color: var(--o-ink-3); }
.o-score__read b { font-size: var(--o-t-lg); font-weight: 600; color: var(--o-ink); font-variant-numeric: tabular-nums; }
.o-score__class { font: 400 10px var(--o-font-label); letter-spacing: .12em; text-transform: uppercase; color: var(--o-ink-3); }
.o-score--strong .o-score__class { color: var(--o-go); }
.o-score--medium .o-score__class { color: var(--o-caution); }
.o-score--strong .o-ticks > i { background: repeating-linear-gradient(90deg, var(--o-go) 0 2px, transparent 2px 7px); }
.o-score__conf { font: 600 11px var(--o-font); color: var(--o-caution); }
.o-score--sm .o-score__read b { font-size: var(--o-t-sm); }
.o-score--sm .o-ticks { height: 6px; max-width: 120px; }
.ad-card .ad-price, .ad-card .ad-meta { font-family: var(--o-font-num); font-variant-numeric: tabular-nums; }
.ad-card .ad-body { gap: var(--o-s2); }

/* Filtres rapides : deux groupes nommés ; un filtre actif est « allumé ». */
.o-quick { display: grid; gap: var(--o-s2); }
.o-quick > div { display: flex; flex-wrap: wrap; align-items: center; gap: var(--o-s2); }
.o-quick .o-label { min-width: 92px; }
.o-tabs a[aria-pressed="true"] { background: var(--o-ink); color: var(--o-bg); border-color: var(--o-ink); }

/* Divulgation progressive : un bloc replié se lit à son titre et à son résumé chiffré. */
.o-disclose { background: var(--o-surface); border: 1px solid var(--o-line); border-radius: var(--o-r-card); box-shadow: var(--o-shadow); min-width: 0; }
.o-disclose > summary { list-style: none; cursor: pointer; display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--o-s2) var(--o-s3); padding: var(--o-s4) var(--o-s5); min-height: 44px; }
.o-disclose > summary::-webkit-details-marker { display: none; }
.o-disclose > summary::after { content: "+"; margin-left: auto; font: 500 var(--o-t-lg)/1 var(--o-font-num); color: var(--o-ink-3); }
.o-disclose[open] > summary::after { content: "−"; }
.o-disclose > summary:focus-visible { outline: 2px solid var(--o-glow-fill); outline-offset: -2px; border-radius: var(--o-r-card); }
.o-disclose__body { padding: 0 var(--o-s5) var(--o-s5); display: grid; gap: var(--o-s3); min-width: 0; }
.o-disclose__body > .table-wrap, .o-disclose__body > .o-table-wrap { margin: 0 calc(-1 * var(--o-s5)); }

/* Instrument de lecture seule (pas de liste derrière) : même dessin, sans effet de survol. */
.o-gauge--static { cursor: default; }
.o-gauge--static:hover { border-color: var(--o-line); transform: none; }

/* Zones du cadran de position de prix (mêmes couleurs que dial.js). */
.o-zone-0 { color: var(--o-info); }
.o-zone-1 { color: var(--o-go); }
.o-zone-2 { color: var(--o-caution); }
.o-zone-3 { color: var(--o-stop); }
.o-dial--price { padding-top: var(--o-s2); }
.o-dial--price .o-ledger { width: 100%; max-width: 420px; }
.o-dial--price .o-help { text-align: center; max-width: 44ch; margin: 0; }
.o-quick .o-tabs a { white-space: nowrap; }
@media (max-width: 560px) {
  .o-quick > div { display: grid; gap: 6px; }
  .o-quick .o-tabs { flex-wrap: nowrap; overflow-x: auto; margin: 0 calc(-1 * var(--o-s4)); padding: 0 var(--o-s4) 2px; scrollbar-width: none; }
  .o-quick .o-tabs::-webkit-scrollbar { display: none; }
}
.o-dial--price .o-ledger { grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr); }

/* Indicateur cliquable (« Aujourd'hui » : affaires en cours, D15). */
a.stat { color: inherit; text-decoration: none; }
a.stat:hover { border-color: var(--o-line-strong, var(--o-line)); }

/* Fiabilité de la chance de mandat (lot L16) : à côté de la note, jamais dans la note. */
.o-rel { font: 600 11px var(--o-font); padding: 1px 6px; border-radius: 999px; border: 1px solid currentColor; }
.o-rel--A { color: var(--o-go); }
.o-rel--B { color: var(--o-caution); }
.o-rel--C { color: var(--o-ink-3, var(--o-ink-2)); }
