/* ── Fontes auto-hebergees ──
   Reprises telles quelles du back-office minier : Roboto en 400/500/700 et le
   sous-ensemble Material Symbols.

   AUTO-HEBERGEES, donc aucune requete sortante : le hub tourne sans internet,
   et une requete vers Google Fonts n'y repondrait jamais. C'est le fichier qui
   est local, pas l'idee qui etait mauvaise — j'avais confondu les deux.

   Material Symbols est sous-ensemble a ~7 Ko. UNE ICONE ABSENTE DU
   SOUS-ENSEMBLE NE S'AFFICHE PAS DU TOUT — ni carre vide, ni repli. Ajouter
   une icone veut donc dire regenerer la fonte :

     https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined
       :opsz,wght,FILL,GRAD@24,400,0,0&icon_names=<liste separee par des virgules>

   Les noms disponibles dans le fichier actuel, herites du back-office minier :
     account_balance_wallet, add, admin_panel_settings, archive, arrow_back,
     badge, bedtime, category, check_circle, chevron_left, chevron_right,
     close, dark_mode, delete, directions_bus, donut_large, edit, engineering,
     error, fact_check, group, handyman, help, history, image, info, inventory,
     light_mode, list_alt, local_gas_station, lock_reset, logout, menu,
     payments, pending_actions, photo_camera, picture_as_pdf, price_check,
     print, query_stats, receipt_long, request_quote, rule, save, settings,
     shelves, space_dashboard, store, task_alt, translate, tune, unarchive,
     warning, workspaces
*/
@font-face {
    font-family: "Roboto";
    font-style: normal; font-weight: 400; font-display: swap;
    src: url("../fonts/roboto-400.woff2") format("woff2");
}
@font-face {
    font-family: "Roboto";
    font-style: normal; font-weight: 500; font-display: swap;
    src: url("../fonts/roboto-500.woff2") format("woff2");
}
@font-face {
    font-family: "Roboto";
    font-style: normal; font-weight: 700; font-display: swap;
    src: url("../fonts/roboto-700.woff2") format("woff2");
}
@font-face {
    /* Le wordmark « NK Lounge » seulement. 9 Ko, sous-ensemble latin. */
    font-family: "Marcellus";
    font-style: normal; font-weight: 400; font-display: swap;
    src: url("../fonts/marcellus-400.woff2") format("woff2");
}
@font-face {
    font-family: "Material Symbols Outlined";
    font-style: normal; font-weight: 400; font-display: block;
    src: url("../fonts/material-symbols.woff2?v=1") format("woff2");
}

.ico {
    font-family: "Material Symbols Outlined";
    font-weight: normal; font-style: normal;
    line-height: 1;
    letter-spacing: normal;
    text-transform: none;
    white-space: nowrap;
    word-wrap: normal;
    direction: ltr;
    -webkit-font-feature-settings: "liga";
    font-feature-settings: "liga";
    -webkit-font-smoothing: antialiased;
    font-size: 22px;
    flex: 0 0 auto;
}

/* NK Lounge — feuille unique, sans build ni framework.

   Le systeme est celui de Material Design 3 : roles de couleur tonaux,
   hierarchie de surfaces, echelle de formes, elevation. Ce qui change par
   rapport a un back-office ordinaire tient en trois points, et chacun vient
   d'une contrainte physique :

   1. LE SOMBRE EST LE DEFAUT SUR LE FRONT DE NUIT. Un lounge est une piece
      noire, et l'ecran y est l'objet le plus lumineux : il eclaire le visage
      de la serveuse, gene le client et detruit sa vision nocturne a chaque
      consultation. Le contraste vient donc de la SATURATION et de la FORME,
      pas de la luminosite. Le bouton d'envoi tire son poids d'etre sature,
      pas d'etre blanc.

   2. LA DENSITE EST INVERSEE. Un back-office serre les lignes pour en tenir
      plus a l'ecran. Ici c'est une main, sur cinq pouces, dans le bruit, avec
      des gens qui bousculent : 56 a 64 px de cible la ou MD3 dit 48.

   3. PAS DE POLICE DISTANTE. Le hub tourne sans internet. Une requete vers
      Google Fonts ne repondrait jamais et la page attendrait pour rien. Pile
      systeme, point.
*/

:root {
    /* Roles tonaux — graine ambre (le gingembre), sur un neutre prune.
       Le neutre penche vers l'accent : un gris pur aurait l'air non choisi. */
    --primary:            #E29A4C;
    --on-primary:         #2A1704;
    --primary-container:  #4A3218;
    --on-primary-container: #FBDCB8;

    --secondary:          #C8B8A0;
    --secondary-container:#3A332A;

    --error:              #E5678C;
    --error-container:    #3E1826;
    --on-error-container:  #FFD9E2;

    --success:            #6FB98C;
    --success-container:  #1B3327;
    --on-success-container: #C7EBD5;

    --warning:            #E0B04A;
    --warning-container:  #3A2E12;

    /* Surfaces : la profondeur vient des surfaces, pas de bordures partout. */
    --background:          #121014;
    --surface:             #191519;
    --surface-container:   #221D23;
    --surface-container-hi:#2C262D;
    --surface-bright:      #373038;

    --on-surface:          #ECE3E6;
    --on-surface-variant:  #B4A8AD;
    --outline:             #6E6268;
    --outline-variant:     #3A3238;
    --inverse-surface:     #ECE3E6;
    --inverse-on-surface:  #201B24;

    /* Formes */
    --r-xs: 6px;
    --r-sm: 10px;
    --r-md: 14px;
    --r-lg: 20px;
    --r-full: 999px;

    /* Cibles tactiles. Ce ne sont pas des valeurs de confort : c'est ce qui
       fait la difference entre la bonne ligne et la ligne d'a cote. */
    --tap:    56px;
    --tap-lg: 64px;

    /* LA MESURE : jusqu'ou une colonne de contenu s'etale avant de se centrer.
       Deux valeurs, parce que les deux coques se lisent a des distances
       differentes — un tableau de chiffres a un bureau, des tuiles tenues a
       bout de bras. Au-dela, on centre : une ligne de 2 000 px ne se lit pas,
       et une rangee de quinze tuiles n'est plus une grille, c'est un mur. */
    --mesure-jour: 1500px;
    --mesure-nuit: 1100px;
    --gouttiere: 14px;

    --elev-1: 0 1px 2px rgba(0,0,0,.5), 0 1px 3px 1px rgba(0,0,0,.3);
    --elev-2: 0 2px 6px rgba(0,0,0,.5), 0 1px 2px rgba(0,0,0,.4);

    --font: "Roboto", system-ui, -apple-system, "Segoe UI", "Helvetica Neue",
            Arial, sans-serif;
    --mono: ui-monospace, "Cascadia Mono", "SF Mono", Menlo, Consolas, monospace;
    --marque: "Marcellus", Georgia, "Times New Roman", serif;
}

/* Le back-office est lu de jour, assis, par quelqu'un qui compare des chiffres.
   Meme systeme, autre calibration. */
[data-mode="jour"] {
    --primary:            #A05F14;
    --on-primary:         #FFFFFF;
    --primary-container:  #FBE6CD;
    --on-primary-container: #341E02;

    --secondary:          #6B5D4C;
    --secondary-container:#EFE6DA;

    --error:              #A31B4B;
    --error-container:    #FCE0E8;
    --on-error-container:  #3F0018;

    --success:            #2F6B47;
    --success-container:  #D6EEE0;
    --on-success-container: #062514;

    --warning:            #8A6A11;
    --warning-container:  #FBEBC4;

    --background:          #FBF8F6;
    --surface:             #FFFFFF;
    --surface-container:   #F3EDEA;
    --surface-container-hi:#EBE4E0;
    --surface-bright:      #FFFFFF;

    --on-surface:          #241E22;
    --on-surface-variant:  #5A5057;
    --outline:             #8B7F86;
    --outline-variant:     #DDD3D8;
    --inverse-surface:     #322B33;
    --inverse-on-surface:  #F4EEF2;

    --elev-1: 0 1px 2px rgba(0,0,0,.14), 0 1px 3px 1px rgba(0,0,0,.06);
    --elev-2: 0 2px 6px rgba(0,0,0,.14), 0 1px 2px rgba(0,0,0,.08);
}

* { box-sizing: border-box; }

html, body {
    margin: 0;
    padding: 0;
    height: 100%;
}

body {
    background: var(--background);
    color: var(--on-surface);
    font-family: var(--font);
    font-size: 16px;
    line-height: 1.45;
    -webkit-font-smoothing: antialiased;
    -webkit-tap-highlight-color: transparent;
    overscroll-behavior: none;
}

/* Une main qui glisse ne doit pas selectionner du texte par accident. */
button, .tap { -webkit-user-select: none; user-select: none; }

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

.mono { font-family: var(--mono); font-variant-numeric: tabular-nums; }
/* LES MONTANTS EN MONO, partout — nuit comme jour. Un chiffre a chasse fixe
   s'aligne tout seul en colonne et se compare d'un coup d'oeil. */
.gnf  { font-family: var(--mono); font-variant-numeric: tabular-nums; white-space: nowrap; }


/* ── Ossature ─────────────────────────────────────────────────────────────── */

.app {
    min-height: 100%;
    display: flex;
    flex-direction: column;
}

.topbar {
    position: sticky;
    top: 0;
    z-index: 20;
    display: flex;
    align-items: center;
    gap: 12px;
    padding-block: 10px;
    background: var(--surface-container);
    border-bottom: 1px solid var(--outline-variant);
    min-height: 54px;
}

.topbar .titre {
    font-size: 17px;
    font-weight: 600;
    letter-spacing: -.01em;
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.topbar .retour {
    display: grid;
    place-items: center;
    width: 40px;
    height: 40px;
    margin-left: -6px;
    border-radius: var(--r-full);
    color: var(--on-surface);
    font-size: 22px;
}

.qui {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 8px 6px 6px;
    border-radius: var(--r-full);
    background: var(--surface-container-hi);
    color: var(--on-surface-variant);
    font-size: 12.5px;
    white-space: nowrap;
}
.qui .pastille {
    display: grid;
    place-items: center;
    width: 28px; height: 28px;
    border-radius: var(--r-full);
    background: var(--primary);
    color: var(--on-primary);
    font-size: 11.5px;
    font-weight: 700;
    letter-spacing: .02em;
}

.contenu { flex: 1; padding-block: 14px; display: flex; flex-direction: column; gap: 12px; }
.contenu.serre { padding: 0; }

.barre-bas {
    position: sticky;
    bottom: 0;
    z-index: 20;
    background: var(--surface-container);
    border-top: 1px solid var(--outline-variant);
    padding-block: 12px calc(12px + env(safe-area-inset-bottom));
    display: flex;
    flex-direction: column;
    gap: 10px;
}


/* ── Boutons ──────────────────────────────────────────────────────────────── */

.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    min-height: var(--tap);
    padding: 0 20px;
    border: none;
    border-radius: var(--r-full);
    background: var(--surface-container-hi);
    color: var(--on-surface);
    font-family: inherit;
    font-size: 16px;
    font-weight: 600;
    cursor: pointer;
    transition: filter .12s ease, transform .06s ease;
}
.btn:active { transform: scale(.97); }
.btn:focus-visible { outline: 3px solid var(--primary); outline-offset: 2px; }

.btn--primaire { background: var(--primary); color: var(--on-primary); }
.btn--danger   { background: var(--error-container); color: var(--on-error-container); }
.btn--ok       { background: var(--success-container); color: var(--on-success-container); }
.btn--fantome  { background: transparent; box-shadow: inset 0 0 0 1px var(--outline); }
.btn--bloc     { width: 100%; }
.btn--grand    { min-height: var(--tap-lg); font-size: 18px; }
.btn:disabled  { opacity: .38; cursor: default; }

form.inline { display: contents; }


/* ── Pave PIN ─────────────────────────────────────────────────────────────── */

.pin-ecran {
    min-height: 100%;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    gap: 22px;
    padding: 28px 20px calc(28px + env(safe-area-inset-bottom));
}

.pin-marque { text-align: center; display: flex; flex-direction: column; gap: 16px; }
.pin-marque .nom {
    font-size: 26px;
    font-weight: 700;
    letter-spacing: -.02em;
}
.pin-marque .sous {
    font-size: 13px;
    color: var(--on-surface-variant);
    letter-spacing: .06em;
    text-transform: uppercase;
}

.pin-points { display: flex; gap: 14px; height: 18px; align-items: center; }
.pin-points i {
    width: 14px; height: 14px;
    border-radius: var(--r-full);
    background: transparent;
    box-shadow: inset 0 0 0 2px var(--outline);
    transition: background .12s ease, box-shadow .12s ease;
}
.pin-points i.plein {
    background: var(--primary);
    box-shadow: inset 0 0 0 2px var(--primary);
}

.pin-grille {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 14px;
    width: min(320px, 100%);
}
.pin-touche {
    height: 74px;
    border: none;
    border-radius: var(--r-full);
    background: var(--surface-container);
    color: var(--on-surface);
    font-family: var(--mono);
    font-size: 27px;
    font-weight: 500;
    cursor: pointer;
    transition: background .1s ease, transform .06s ease;
}
.pin-touche:active { transform: scale(.94); background: var(--surface-container-hi); }
.pin-touche.vide { background: transparent; cursor: default; }
.pin-touche.action { font-size: 20px; color: var(--on-surface-variant); }

.pin-erreur {
    min-height: 22px;
    color: var(--error);
    font-size: 14.5px;
    font-weight: 500;
}

.pin-aide {
    font-size: 12px;
    color: var(--on-surface-variant);
    text-align: center;
    line-height: 1.7;
    max-width: 320px;
}
.pin-aide b { color: var(--on-surface); font-weight: 600; }


/* ── Compteur « a recuperer » ─────────────────────────────────────────────── */

/* Le canal fiable. Elle ratera la moitie des vibrations — le POS sera dans sa
   poche, ou elle sera en train d'encaisser. Ce chiffre-la reste juste sans
   qu'elle ait rien eu a attraper. */
.recup {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 14px 18px;
    border-radius: var(--r-md);
    background: var(--success-container);
    color: var(--on-success-container);
}
.recup .n {
    font-family: var(--mono);
    font-size: 32px;
    font-weight: 700;
    line-height: 1;
}
.recup .quoi { display: flex; flex-direction: column; gap: 2px; }
.recup .quoi .t {
    font-size: 11.5px;
    letter-spacing: .11em;
    text-transform: uppercase;
    opacity: .8;
}
.recup .quoi .d { font-size: 15px; font-weight: 600; }
.recup.vide {
    background: var(--surface-container);
    color: var(--on-surface-variant);
}
.recup.vide .n { color: var(--outline); }


/* ── Liste des additions ──────────────────────────────────────────────────── */

.additions { display: flex; flex-direction: column; gap: 8px; }

.addition {
    display: grid;
    grid-template-columns: auto 1fr auto;
    gap: 4px 14px;
    align-items: center;
    padding: 14px 16px;
    min-height: var(--tap-lg);
    border-radius: var(--r-md);
    background: var(--surface-container);
    color: inherit;
    border-left: 3px solid transparent;
}
.addition:active { background: var(--surface-container-hi); }
.addition.pret { border-left-color: var(--success); }

.addition .num {
    font-family: var(--mono);
    font-size: 17px;
    font-weight: 600;
    color: var(--primary);
    letter-spacing: -.02em;
}
.addition .ou {
    grid-column: 1;
    font-size: 11px;
    color: var(--on-surface-variant);
    letter-spacing: .04em;
}
/* Ce qui la fait reconnaitre un client : ce qu'il a commande. Elle ne se
   souvient pas du « 1042 », elle se souvient du nectar mangue. */
.addition .quoi {
    grid-column: 2;
    grid-row: 1 / span 2;
    font-size: 15.5px;
    line-height: 1.35;
    overflow: hidden;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
}
.addition .droite {
    grid-column: 3;
    grid-row: 1 / span 2;
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 5px;
}
.addition .montant { font-size: 15.5px; font-weight: 600; }

.etats { display: flex; gap: 5px; flex-wrap: wrap; justify-content: flex-end; }

.puce {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 2px 8px;
    border-radius: var(--r-full);
    font-size: 11px;
    font-weight: 600;
    letter-spacing: .02em;
    white-space: nowrap;
    background: var(--surface-container-hi);
    color: var(--on-surface-variant);
}
.puce--pret    { background: var(--success-container); color: var(--on-success-container); }
.puce--attente { background: var(--warning-container);  color: var(--warning); }
.puce--retard  { background: var(--error-container);    color: var(--on-error-container); }
.puce--solde   { background: var(--success-container);  color: var(--on-success-container); }
.puce--du      { background: var(--surface-container-hi); color: var(--on-surface-variant); }
.puce--alerte  { background: var(--error-container);    color: var(--on-error-container); }


/* ── Tables (ouverture d'addition) ────────────────────────────────────────── */

.zone-titre {
    font-size: 11.5px;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: var(--on-surface-variant);
    margin: 4px 0 0;
}

.tables {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(76px, 100%), 1fr));
    gap: 8px;
}
.table-case {
    /* UN <button> NE S'ETIRE PAS dans une grille : `justify-self: normal`
       vaut `start` pour un controle de formulaire, qui garde sa largeur de
       contenu. Mesure : 71 px dans une colonne de 108. Le pave prend donc sa
       colonne explicitement. */
    width: 100%;
    justify-self: stretch;
    min-height: var(--tap-lg);
    display: grid;
    place-items: center;
    border: none;
    border-radius: var(--r-sm);
    background: var(--surface-container);
    color: var(--on-surface);
    font-family: var(--mono);
    font-size: 18px;
    font-weight: 600;
    cursor: pointer;
}
.table-case:active { background: var(--surface-container-hi); }
.table-case .n { font-size: 10px; color: var(--primary); font-weight: 700; }


/* ── Grille de produits ───────────────────────────────────────────────────── */

.onglets {
    display: flex;
    gap: 8px;
    overflow-x: auto;
    padding: 2px 0 6px;
    scrollbar-width: none;
}
.onglets::-webkit-scrollbar { display: none; }
.onglet {
    flex: 0 0 auto;
    min-height: 42px;
    padding: 0 18px;
    display: inline-flex;
    align-items: center;
    border-radius: var(--r-full);
    background: var(--surface-container);
    color: var(--on-surface-variant);
    font-size: 14.5px;
    font-weight: 600;
    cursor: pointer;
    border: none;
}
.onglet.actif { background: var(--primary-container); color: var(--on-primary-container); }

.produits {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(146px, 100%), 1fr));
    gap: 8px;
}
.produit {
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    gap: 8px;
    min-height: 92px;
    padding: 12px 13px;
    border: none;
    border-radius: var(--r-md);
    background: var(--surface-container);
    color: var(--on-surface);
    text-align: left;
    font-family: inherit;
    cursor: pointer;
}
.produit:active { background: var(--surface-container-hi); }
.produit .nom { font-size: 14.5px; font-weight: 600; line-height: 1.25; }
.produit .prix { font-size: 13px; color: var(--primary); font-weight: 600; }

/* Rupture declaree par le poste : grise, et on ne peut pas la taper. Un solde
   a zero, lui, avertit mais laisse vendre. */
.produit.rupture { opacity: .4; cursor: default; }
.produit.rupture .nom { text-decoration: line-through; }


/* ── Panier ───────────────────────────────────────────────────────────────── */

.panier { display: flex; flex-direction: column; gap: 6px; }

.ligne {
    display: grid;
    grid-template-columns: 34px 1fr auto auto;
    align-items: center;
    gap: 10px;
    padding: 11px 13px;
    border-radius: var(--r-sm);
    background: var(--surface-container);
    min-height: 52px;
}
.ligne .q {
    font-family: var(--mono);
    font-size: 15px;
    font-weight: 700;
    color: var(--primary);
}
.ligne .n { font-size: 15px; min-width: 0; }
.ligne .n small {
    display: block;
    font-size: 11.5px;
    color: var(--on-surface-variant);
}
.ligne .m { font-size: 14.5px; font-weight: 600; }
.ligne .x {
    width: 38px; height: 38px;
    display: grid; place-items: center;
    border: none;
    border-radius: var(--r-full);
    background: transparent;
    color: var(--on-surface-variant);
    font-size: 19px;
    cursor: pointer;
}
.ligne .x:active { background: var(--surface-container-hi); }
.ligne.figee { background: var(--surface); }

.total-bar {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    font-size: 15px;
}
.total-bar .somme { font-size: 22px; font-weight: 700; }
.total-bar .lbl { color: var(--on-surface-variant); font-size: 13px; }


/* ── File de poste ────────────────────────────────────────────────────────── */

/* Ni prix ni total ici : le bar n'a pas a connaitre l'addition du VIP. */
.commande {
    display: grid;
    grid-template-columns: 1fr auto;
    gap: 10px 14px;
    padding: 15px 16px;
    border-radius: var(--r-md);
    background: var(--surface-container);
    border-left: 3px solid var(--outline-variant);
}
.commande.retard { border-left-color: var(--error); }

.commande .entete {
    display: flex;
    align-items: baseline;
    gap: 10px;
    flex-wrap: wrap;
}
.commande .num {
    font-family: var(--mono);
    font-size: 18px;
    font-weight: 700;
    color: var(--primary);
}
.commande .place { font-size: 13px; color: var(--on-surface-variant); }
.commande .quoi {
    grid-column: 1;
    font-size: 20px;
    font-weight: 600;
    line-height: 1.25;
}
.commande .quoi .q {
    font-family: var(--mono);
    color: var(--primary);
    margin-right: 6px;
}
.commande .agir { grid-column: 2; grid-row: 1 / span 2; display: grid; place-items: center; }
.commande .par { font-size: 12px; color: var(--on-surface-variant); }


/* ── Cartes de chiffres (mode service du gerant) ──────────────────────────── */

.chiffres {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(140px, 100%), 1fr));
    gap: 8px;
}
.chiffre {
    padding: 14px 16px;
    border-radius: var(--r-md);
    background: var(--surface-container);
    display: flex;
    flex-direction: column;
    gap: 4px;
}
.chiffre .t {
    font-size: 11px;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--on-surface-variant);
}
.chiffre .v { font-size: 25px; font-weight: 700; letter-spacing: -.02em; }
.chiffre .v small { font-size: 13px; font-weight: 500; color: var(--on-surface-variant); }


/* ── Divers ───────────────────────────────────────────────────────────────── */

.vide-etat {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    padding: 44px 20px;
    text-align: center;
    color: var(--on-surface-variant);
}
.vide-etat .gros { font-size: 34px; opacity: .5; }
.vide-etat p { margin: 0; font-size: 15px; max-width: 30ch; }

.section-titre {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    font-size: 11.5px;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: var(--on-surface-variant);
}

.chantier {
    display: flex;
    flex-direction: column;
    gap: 14px;
    padding: 22px;
    border-radius: var(--r-md);
    background: var(--surface-container);
}
.chantier h2 { margin: 0; font-size: 21px; }
.chantier .etape {
    font-family: var(--mono);
    font-size: 11.5px;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--primary);
}
.chantier ul { margin: 0; padding-left: 20px; display: flex; flex-direction: column; gap: 7px; }
.chantier li { color: var(--on-surface-variant); font-size: 15px; }

.saisie {
    width: 100%;
    min-height: var(--tap);
    padding: 0 16px;
    border: none;
    border-radius: var(--r-sm);
    background: var(--surface-container-hi);
    color: var(--on-surface);
    font-family: var(--mono);
    font-size: 19px;
    font-variant-numeric: tabular-nums;
}
.saisie:focus { outline: 2px solid var(--primary); }

@media (prefers-reduced-motion: reduce) {
    * { transition: none !important; animation: none !important; }
}


/* ── Ecrans fixes : un travail par ecran, aucun defilement pour trouver ──────

   Sur cinq pouces, une page qui defile est une page ou l'action la plus
   frequente finit sous le pli. La grille de produits doit prendre l'ecran :
   c'est le geste des 400 fois par nuit. Donc la page elle-meme ne defile pas —
   seule une zone defile, et l'en-tete comme le pied restent en place.
*/

.app.fixe {
    height: 100dvh;
    overflow: hidden;
}

.zone-defile {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    padding-block: 12px calc(12px + env(safe-area-inset-bottom));
    display: flex;
    flex-direction: column;
    gap: 12px;
}
/* ── LA GOUTTIERE QUI CENTRE ──────────────────────────────────────────────

   Un fond doit courir d'un bord a l'autre — une barre qui s'arrete au milieu
   d'un ecran large ressemble a une fenetre mal dimensionnee. Mais son CONTENU
   doit s'aligner sur la colonne centrale, sinon le titre d'une page part a
   gauche pendant que les cartes en dessous sont au milieu.

   Un seul bourrage regle les deux : la gouttiere ordinaire tant que l'ecran
   est plus etroit que la mesure, puis la moitie du debordement des qu'il la
   depasse. Aucun conteneur supplementaire dans le HTML, et les barres restent
   pleine largeur.

   Un ecran de poste au mur fait souvent 24 pouces : sans ca, la file du barman
   s'etalait sur quinze colonnes de tuiles et il fallait balayer la salle des
   yeux pour lire une commande. */
.zone-defile, .contenu, .topbar, .entete-cmd, .onglets-fixes, .barre-bas {
    padding-inline: max(var(--gouttiere), (100% - var(--mesure-nuit)) / 2);
}
.zone-defile.serre { gap: 8px; }

/* En-tete de commande : le numero, la place, le total. Rien d'autre — tout ce
   qui est ajoute ici est pris sur la grille. */
.entete-cmd {
    display: flex;
    align-items: center;
    gap: 12px;
    padding-block: 9px;
    background: var(--surface-container);
    border-bottom: 1px solid var(--outline-variant);
}
.entete-cmd .retour {
    display: grid; place-items: center;
    width: 42px; height: 42px; margin-left: -8px;
    border-radius: var(--r-full);
    color: var(--on-surface);
    font-size: 23px;
}
.entete-cmd .ident { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.entete-cmd .ident .n {
    font-family: var(--mono);
    font-size: 17px; font-weight: 700;
    color: var(--primary);
    letter-spacing: -.02em;
}
.entete-cmd .ident .ou { font-size: 11.5px; color: var(--on-surface-variant); }
.entete-cmd .somme { font-size: 17px; font-weight: 700; }

/* Les onglets de categorie ne defilent jamais avec les produits. */
.onglets-fixes {
    display: flex;
    gap: 7px;
    overflow-x: auto;
    padding-block: 9px;
    background: var(--surface);
    border-bottom: 1px solid var(--outline-variant);
    scrollbar-width: none;
}
.onglets-fixes::-webkit-scrollbar { display: none; }

/* Bandeau d'alerte sous l'en-tete : court, et seulement quand il y a lieu. */
.rappel {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 14px;
    background: var(--success-container);
    color: var(--on-success-container);
}
.rappel .txt { flex: 1; min-width: 0; font-size: 14px; font-weight: 600; }
.rappel .btn { min-height: 42px; padding: 0 16px; font-size: 14.5px; }


/* ── Panier en feuille : il ne vole pas la place aux produits ────────────── */

.pied-cmd {
    background: var(--surface-container);
    border-top: 1px solid var(--outline-variant);
    padding: 10px 14px calc(10px + env(safe-area-inset-bottom));
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.poignee {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    width: 100%;
    min-height: 48px;
    padding: 0 4px;
    border: none;
    background: transparent;
    color: var(--on-surface);
    font-family: inherit;
    font-size: 15px;
    font-weight: 600;
    cursor: pointer;
}
.poignee .compte { color: var(--on-surface-variant); font-weight: 500; font-size: 14px; }
.poignee .fleche { color: var(--on-surface-variant); font-size: 13px; }

.scrim {
    position: fixed;
    inset: 0;
    z-index: 40;
    background: rgba(0, 0, 0, .62);
    opacity: 0;
    pointer-events: none;
    transition: opacity .18s ease;
}
.scrim.on { opacity: 1; pointer-events: auto; }

.feuille {
    position: fixed;
    left: 0; right: 0; bottom: 0;
    z-index: 50;
    max-height: 84dvh;
    display: flex;
    flex-direction: column;
    background: var(--surface-container);
    border-radius: var(--r-lg) var(--r-lg) 0 0;
    border-top: 1px solid var(--outline);
    transform: translateY(101%);
    transition: transform .2s cubic-bezier(.2, .8, .3, 1);
}
.feuille.on { transform: none; }

.feuille .prise {
    flex: 0 0 auto;
    display: grid;
    place-items: center;
    padding: 10px 0 4px;
    cursor: pointer;
}
.feuille .prise i {
    width: 38px; height: 4px;
    border-radius: var(--r-full);
    background: var(--outline);
}
/* Le panneau est fixe et pleine largeur — son ombre doit courir d'un bord a
   l'autre — mais sa liste de lignes suit la meme mesure que la grille au
   dessus, sinon les articles s'alignent au centre et le panier a gauche. */
.feuille .dedans {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    padding-block: 8px 4px;
    padding-inline: max(var(--gouttiere), (100% - var(--mesure-nuit)) / 2);
    display: flex;
    flex-direction: column;
    gap: 10px;
}
.feuille .sous {
    flex: 0 0 auto;
    padding-block: 12px calc(14px + env(safe-area-inset-bottom));
    padding-inline: max(var(--gouttiere), (100% - var(--mesure-nuit)) / 2);
    border-top: 1px solid var(--outline-variant);
    display: flex;
    flex-direction: column;
    gap: 9px;
}


/* ── Ecran de choix de table ─────────────────────────────────────────────── */

.tables-plein {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(84px, 100%), 1fr));
    gap: 9px;
}
.tables-plein .table-case { min-height: 78px; gap: 3px; flex-direction: column; }


/* Dans un ecran fixe, la grille remplit la zone qui defile : les tuiles
   s'alignent en haut et le reste est du vide, jamais une tuile etiree. */
.zone-defile .produits { align-content: start; }
.zone-defile .produits[hidden] { display: none; }


/* ── Vignettes de produit ────────────────────────────────────────────────────

   Une photo se reconnait plus vite qu'un libelle, et beaucoup plus vite a 3 h
   du matin. C'est une des cinq contraintes du brief — personnel qui tourne,
   litteratie variable, ecran presque sans mots — pas de la decoration.

   Tant qu'un article n'a pas de photo, il porte ses initiales sur la couleur
   de sa categorie. Un carre vide serait pire que rien : il ferait croire que
   le chargement a echoue.
*/

.vignette {
    position: relative;
    display: grid;
    place-items: center;
    overflow: hidden;
    border-radius: var(--r-sm);
    background: color-mix(in srgb, var(--c, var(--outline)) 22%, var(--surface-container));
    flex: 0 0 auto;
}
.vignette img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}
.vignette .lettre {
    font-family: var(--mono);
    font-weight: 700;
    color: var(--c, var(--on-surface-variant));
    letter-spacing: .02em;
}

/* Sur la tuile de commande. Une photo est lumineuse dans une salle noire :
   elle reste petite et on la couche legerement, pour qu'elle serve la
   reconnaissance sans transformer l'ecran en lampe. */
.produit .vignette {
    width: 100%;
    aspect-ratio: 3 / 2;
    filter: brightness(.94) saturate(1.05);
}
.produit .vignette .lettre { font-size: 22px; }

.produit {
    gap: 7px;
    padding: 8px 8px 11px;
    min-height: 0;
}
.produit .nom { font-size: 13.5px; line-height: 1.22; }
.produit .prix { font-size: 12.5px; }

/* Au catalogue, en liste : la meme vignette, en petit. */
.vignette--sm { width: 46px; height: 46px; }
.vignette--sm .lettre { font-size: 15px; }

.ligne-cat {
    display: grid;
    grid-template-columns: auto 1fr auto auto;
    align-items: center;
    gap: 12px;
    padding: 10px 13px;
    border-radius: var(--r-sm);
    background: var(--surface-container);
    min-height: 66px;
}
.ligne-cat .n { font-size: 15px; min-width: 0; }
.ligne-cat .n small {
    display: block;
    font-size: 11.5px;
    color: var(--on-surface-variant);
}
.ligne-cat .btn { min-height: 42px; padding: 0 15px; font-size: 14px; }
.ligne-cat .pose label { cursor: pointer; }
.ligne-cat .x {
    width: 38px; height: 38px;
    display: grid; place-items: center;
    border: none; border-radius: var(--r-full);
    background: transparent; color: var(--on-surface-variant);
    font-size: 19px; cursor: pointer;
}





/* Deux boutons cote a cote : l'action secondaire garde sa largeur propre pour
   qu'on ne la confonde jamais avec l'envoi, qui prend tout le reste. */
.paire { display: flex; gap: 9px; }
.paire > form:last-child { flex: 1; }

.lien-action {
    border: none;
    background: transparent;
    color: var(--primary);
    font-family: inherit;
    font-size: 11.5px;
    font-weight: 700;
    letter-spacing: .1em;
    text-transform: uppercase;
    padding: 6px 2px;
    cursor: pointer;
}


/* ── Le brouillon, visible pendant la saisie ─────────────────────────────────

   Un article ajoute doit apparaitre tout de suite. Sans ca elle ne sait pas si
   son tap a pris, et elle retape — c'est comme ca qu'on sert deux chichas au
   lieu d'une.

   La bande est plafonnee a trois lignes et defile au-dela : elle ne doit
   jamais manger la grille, qui reste le geste des 400 fois par nuit.
*/
.brouillon {
    flex: 0 0 auto;
    max-height: 138px;
    overflow-y: auto;
    background: var(--surface);
    border-top: 1px solid var(--outline-variant);
    padding: 7px 14px;
    display: flex;
    flex-direction: column;
    gap: 4px;
}
.brouillon .bl {
    display: grid;
    grid-template-columns: 26px 1fr auto 38px;
    align-items: center;
    gap: 10px;
    min-height: 40px;
}
.brouillon .bl .q {
    font-family: var(--mono);
    font-size: 16px;
    font-weight: 700;
    color: var(--primary);
    text-align: right;
}
.brouillon .bl .n {
    font-size: 14.5px;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.brouillon .bl .m { font-size: 13.5px; color: var(--on-surface-variant); }
.brouillon .bl .x {
    width: 38px; height: 38px;
    display: grid; place-items: center;
    border: none; border-radius: var(--r-full);
    background: var(--surface-container-hi);
    color: var(--on-surface-variant);
    font-size: 20px; cursor: pointer;
}
.brouillon .bl .x:active { background: var(--surface-bright); }


/* Une tournee, pas un article : le barman pose trois verres sur un plateau et
   declare le tout pret d'un geste. Les articles s'empilent dans la carte. */
.commande .quoi { display: flex; flex-direction: column; gap: 3px; }
.commande .quoi .art { display: flex; align-items: baseline; gap: 8px; }
.commande .quoi .art .q {
    font-family: var(--mono);
    color: var(--primary);
    min-width: 20px;
}


/* ── Replis ──────────────────────────────────────────────────────────────────

   `<details>` natif : pas de JavaScript, donc il survit au remplacement d'une
   zone vivante et il reste ouvert si on l'avait ouvert. C'est le meme reflexe
   que partout ailleurs — l'etat dans le HTML, pas dans un script.
*/
.plier { grid-column: 1 / -1; margin-top: 4px; }

/* La cible fait TOUTE la largeur et 52 px de haut.

   Un repli discret n'est pas un repli petit : il est moins visible, pas plus
   dur a toucher. Une cible de la largeur du mot « Details », a 3 h du matin,
   dans le bruit, avec des gens qui bousculent, c'est un tap sur deux qui rate. */
.plier > summary {
    list-style: none;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    width: 100%;
    min-height: 52px;
    padding: 0 14px;
    border-radius: var(--r-sm);
    background: var(--surface);
    color: var(--on-surface-variant);
    font-size: 14.5px;
    font-weight: 600;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    transition: background .1s ease;
}
.plier > summary:active { background: var(--surface-container-hi); }
.plier > summary:focus-visible { outline: 3px solid var(--primary); outline-offset: 2px; }
.plier > summary::-webkit-details-marker { display: none; }
.plier > summary::after {
    content: "BE";   /* un vrai chevron : l ancien caractere se rendait en lettres */
    font-size: 13px;
    color: var(--outline);
    transition: transform .15s ease;
}
.plier[open] > summary { border-radius: var(--r-sm) var(--r-sm) 0 0; }
.plier[open] > summary::after { transform: rotate(180deg); }

.plier dl {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: 7px 16px;
    margin: 0 0 4px;
    padding: 13px 14px;
    border-radius: 0 0 var(--r-sm) var(--r-sm);
    background: var(--surface);
    box-shadow: inset 0 1px 0 var(--outline-variant);
    font-size: 14px;
}
.plier dt {
    color: var(--on-surface-variant);
    font-size: 11px;
    letter-spacing: .08em;
    text-transform: uppercase;
    padding-top: 2px;
}
.plier dd { margin: 0; }


/* Le repli d'une addition vit sous la ligne, pas dedans : la ligne reste un
   lien plein — ouvrir l'addition est le geste des 400 fois par nuit et ne doit
   pas couter un tap de plus. */
.add-bloc {
    border-radius: var(--r-md);
    background: var(--surface-container);
    overflow: hidden;
}
.add-bloc .addition { background: transparent; border-radius: 0; }
.add-bloc .plier { padding: 0 10px 8px; margin-top: 0; }
.add-bloc .plier > summary { background: var(--background); }
.add-bloc .plier > summary:active { background: var(--surface-container-hi); }
.add-bloc .plier dl { background: var(--background); }
.add-bloc .plier dd { display: flex; align-items: baseline; gap: 7px; flex-wrap: wrap; }
.add-bloc .plier dd small { color: var(--on-surface-variant); font-size: 11.5px; }
.add-bloc .plier dt.mono { text-transform: none; letter-spacing: 0; font-size: 13px; color: var(--primary); font-weight: 700; }


/* ── LE BACK-OFFICE ──────────────────────────────────────────────────────────

   L'autre moitie de l'application. Ici on est assis, de jour, et on compare
   des chiffres : navigation complete, calibration claire, densite de lecture.
   C'est l'exact oppose du front de nuit — debout, salle noire, un pouce.

   Le tiroir s'ouvre sans une ligne de JavaScript : une case a cocher cachee et
   le selecteur `:checked`. Meme reflexe que partout ailleurs, l'etat dans le
   HTML.
*/

.bureau { display: flex; min-height: 100vh; }

.lateral {
    position: fixed;
    top: 0; bottom: 0; left: 0;
    z-index: 40;
    /* 232 px : le haut de la fourchette du handoff (200-232). Seize pixels
       rendus au contenu — sur un portable de 1280, ils comptent. */
    width: 200px;
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: 16px 12px;
    background: var(--surface-container);
    border-right: 1px solid var(--outline-variant);
    overflow-y: auto;
    transform: translateX(-100%);
    transition: transform .2s cubic-bezier(.2, .8, .3, 1);
}
.tiroir-bascule:checked ~ .bureau .lateral { transform: none; }

.lateral-marque {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 6px 10px 14px;
    font-size: 15px;
    font-weight: 700;
    letter-spacing: -.01em;
}
.lateral-marque .pastille {
    display: grid; place-items: center;
    width: 32px; height: 32px;
    border-radius: var(--r-sm);
    background: var(--primary);
    color: var(--on-primary);
    font-family: var(--mono);
    font-size: 12px;
    font-weight: 700;
}

/* Le mode SERVICE est une entree a part, pas un element de menu : c'est un
   autre etat d'esprit, pas une rubrique de plus. */
.lateral-service {
    display: flex;
    align-items: center;
    min-height: 46px;
    padding: 0 14px;
    margin-bottom: 8px;
    border-radius: var(--r-full);
    background: var(--primary-container);
    color: var(--on-primary-container);
    font-size: 14.5px;
    font-weight: 600;
}

.lateral-nav { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; }
.lateral-titre {
    padding: 16px 14px 6px;
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: var(--on-surface-variant);
}
.lateral-nav a {
    display: flex;
    align-items: center;
    min-height: 44px;
    padding: 0 14px;
    border-radius: var(--r-full);
    color: var(--on-surface);
    font-size: 14.5px;
}
.lateral-nav a:hover { background: var(--surface-container-hi); }
.lateral-nav a.actif {
    background: var(--primary-container);
    color: var(--on-primary-container);
    font-weight: 600;
}

.lateral-sortie {
    margin-top: auto;
    display: flex;
    align-items: center;
    min-height: 44px;
    padding: 0 14px;
    color: var(--on-surface-variant);
    font-size: 13.5px;
}

.voile {
    position: fixed;
    inset: 0;
    z-index: 30;
    background: rgba(0, 0, 0, .4);
    opacity: 0;
    pointer-events: none;
    transition: opacity .18s ease;
}
.tiroir-bascule:checked ~ .bureau .voile { opacity: 1; pointer-events: auto; }

.page { flex: 1; min-width: 0; display: flex; flex-direction: column; }

.page-barre {
    position: sticky;
    top: 0;
    z-index: 20;
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 12px 20px;
    background: var(--surface);
    border-bottom: 1px solid var(--outline-variant);
}
.page-barre h1 {
    flex: 1;
    min-width: 0;
    margin: 0;
    font-size: 19px;
    font-weight: 700;
    letter-spacing: -.015em;
    /* Coupe plutot que de passer a la ligne : la barre a une hauteur, et un
       titre sur deux lignes la ferait deborder au lieu de la grandir. */
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.burger {
    display: grid; place-items: center;
    width: 42px; height: 42px;
    margin-left: -8px;
    border-radius: var(--r-full);
    font-size: 21px;
    cursor: pointer;
    color: var(--on-surface);
}
.burger:hover { background: var(--surface-container); }

/* Le plafond etait a 1100 px SANS centrage : sur un ecran large, tout le
   contenu se tassait a gauche et la moitie droite restait vide. Le plafond
   monte, et surtout la colonne se centre — c'est ce qui manquait. */
.page-corps {
    flex: 1;
    padding: var(--gouttiere) max(var(--gouttiere), (100% - var(--mesure-jour)) / 2);
    display: flex;
    flex-direction: column;
    gap: 12px;
}

/* Ecran large : le tiroir devient un panneau fixe, le voile et le burger
   disparaissent. Le gerant qui s'assied a un ordinateur voit tout d'un coup. */
@media (min-width: 900px) {
    .lateral { transform: none; }
    .bureau { padding-left: 200px; }
    .burger, .voile { display: none; }
}


/* Carte de back-office : lue assise, de jour. Densite de lecture, pas de
   densite tactile. */
.carte {
    padding: 22px 24px;
    border-radius: var(--r-md);
    background: var(--surface);
    border: 1px solid var(--outline-variant);
    display: flex;
    flex-direction: column;
    gap: 12px;
}
.carte .etape {
    font-family: var(--mono);
    font-size: 11px;
    font-weight: 600;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--primary);
}
.carte h2 { margin: 0; font-size: 20px; letter-spacing: -.015em; }
.carte p { margin: 0; color: var(--on-surface-variant); }
.carte ul { margin: 0; padding-left: 20px; display: flex; flex-direction: column; gap: 7px; }
.carte li { color: var(--on-surface-variant); }


/* Un choix d'actes : deux boutons pleins, empiles, avec leur consequence
   ecrite dessous. On ne fait pas deviner ce qu'un bouton va faire quand il
   met deux noms sur un acte. */
.choix { display: flex; flex-direction: column; gap: 8px; }
.choix .btn {
    flex-direction: column;
    align-items: flex-start;
    justify-content: center;
    gap: 2px;
    padding: 12px 18px;
    text-align: left;
}
.choix .btn small { font-size: 12.5px; font-weight: 400; opacity: .75; }

.carte-nuit {
    display: grid;
    grid-template-columns: 34px 1fr;
    align-items: center;
    gap: 12px;
    padding: 14px 16px;
    border-radius: var(--r-md);
    background: var(--surface-container);
}
.carte-nuit .q {
    font-family: var(--mono);
    font-size: 18px;
    font-weight: 700;
    color: var(--primary);
}
.carte-nuit .n { font-size: 16px; font-weight: 600; }
.carte-nuit .n small {
    display: block;
    font-size: 12.5px;
    font-weight: 400;
    color: var(--on-surface-variant);
}


/* Une porte vers un autre monde n'est pas un bouton d'action : elle dit ou
   elle mene. Un bouton nomme « Gestion » tout seul ne se distingue pas d'un
   bouton mort. */
/* DEUX BOUTONS COTE A COTE dans la barre du bas : commander la nuit, et
   passer au jour. Ils gardent leur hauteur — on est au pouce, dans le noir —
   mais se partagent la largeur. La porte vers le back-office prend un peu
   moins de place que l'action de la nuit : c'est celle-la qu'on cherche a
   l'ouverture et a la fermeture, l'autre se consulte. */
.barre-bas--duo { flex-direction: row; align-items: stretch; gap: 10px; }
.barre-bas--duo > form { flex: 3 1 0; min-width: 0; display: flex; }
.barre-bas--duo > form > .btn { flex: 1; }
.barre-bas--duo > .btn { flex: 2 1 0; min-width: 0; }
/* L'action de la nuit garde le plus de place : c'est celle qu'on cherche a
   l'ouverture et a la fermeture. La depense et la porte du back-office se
   partagent le reste. */
.barre-bas--duo > form:first-child { flex: 3 1 0; }
.barre-bas--duo > .porte { flex: 2 1 0; }
.barre-bas--duo .lib { min-width: 0; overflow: hidden; text-overflow: ellipsis; }

.porte { gap: 8px; padding: 0 14px; min-width: 0; }
.porte .lib { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.porte .ico { font-size: 20px; opacity: .85; }
.porte .fleche { font-size: 18px; opacity: .7; }

/* Sur un telephone tenu droit, deux boutons a 64 px de haut cote a cote ne
   laissent plus de place aux mots : ils repassent l'un sous l'autre. */
/* Trois boutons a 64 px de haut cote a cote ne laissent plus de place aux
   mots sur un telephone tenu droit : ils repassent l'un sous l'autre. */
@media (max-width: 560px) {
    .barre-bas--duo { flex-direction: column; }
}


/* ── Tableau de soldes ───────────────────────────────────────────────────────

   Un emplacement par colonne. Le zero est grise et le negatif est rouge : un
   negatif n'est pas une erreur d'affichage, c'est le signal qu'une sortie n'a
   pas ete saisie ou qu'il manque physiquement de la marchandise.
*/
.tableau { display: flex; flex-direction: column; gap: 2px; }
.tableau .tr {
    display: grid;
    grid-template-columns: 1fr repeat(3, 62px);
    align-items: center;
    gap: 8px;
    padding: 10px 13px;
    border-radius: var(--r-sm);
    background: var(--surface-container);
    min-height: 52px;
}
.tableau .th {
    background: transparent;
    min-height: 0;
    padding-bottom: 2px;
}
.tableau .th span {
    font-size: 10.5px;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--on-surface-variant);
}
.tableau .td-nom { font-size: 14.5px; min-width: 0; }
.tableau .td-nom small {
    display: block;
    font-size: 11.5px;
    color: var(--on-surface-variant);
}
.tableau .td-n {
    text-align: right;
    font-size: 16px;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}
.tableau .td-n.vide { color: var(--outline); font-weight: 400; }
.tableau .td-n.negatif { color: var(--error); }

.ligne .q.sortie { color: var(--error); }


/* ── Saisie de reception ────────────────────────────────────────────────────
   Deux champs par ligne : combien de casiers, a quel prix le casier. Jamais
   d'unites — il compte des casiers sur un quai a 18 h. */
.ligne-recep {
    display: grid;
    grid-template-columns: 1fr 76px 110px;
    align-items: center;
    gap: 9px;
    padding: 9px 12px;
    border-radius: var(--r-sm);
    background: var(--surface-container);
    min-height: 60px;
}
.ligne-recep .n { font-size: 14.5px; min-width: 0; }
.ligne-recep .n small {
    display: block;
    font-size: 11.5px;
    color: var(--on-surface-variant);
}
.saisie.mini {
    min-height: 46px;
    padding: 0 10px;
    font-size: 16px;
    text-align: right;
}
select.saisie { font-family: var(--font); }

.bascule {
    display: flex;
    align-items: center;
    gap: 12px;
    min-height: 56px;
    padding: 0 16px;
    border-radius: var(--r-sm);
    background: var(--surface-container);
    font-size: 14px;
    cursor: pointer;
}
.bascule input { width: 22px; height: 22px; accent-color: var(--primary); flex: 0 0 auto; }


/* Une pile d'elements dans une page de back-office : elle defile avec la page,
   pas dans une zone fixe. On est assis, on lit — on ne tient pas l'ecran. */
.pile { display: flex; flex-direction: column; gap: 12px; }
.actions {
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding-top: 4px;
    max-width: 420px;
}


/* Le tableau des soldes s'adapte au nombre d'emplacements : un seul au pilote,
   plusieurs le jour ou les transferts a deux signatures arriveront. */
.tableau .tr {
    grid-template-columns: 1fr repeat(var(--cols, 1), 78px) 110px;
}
/* Un tableau plus large que l'ecran defile DANS SON CADRE. `contain` empeche
   le balayage horizontal de remonter au navigateur, qui l'interpreterait comme
   « page precedente » — on perdrait la saisie en cours pour avoir voulu lire
   une colonne de droite. */
.scroll-h { overflow-x: auto; overscroll-behavior-x: contain; -webkit-overflow-scrolling: touch; }


/* ══ LE LANGAGE DU BACK-OFFICE ═══════════════════════════════════════════════

   Repris de zone_web, composant par composant. Ce n'est pas de la copie : la
   moitie jour des deux logiciels resout exactement le meme probleme visuel —
   un adulte assis qui lit des chiffres — et il n'y avait aucune raison de
   reinventer une deuxieme reponse.

   Ce qui change reste la graine de couleur, deja re-teintee dans les jetons.
*/

/* ── Carte ─────────────────────────────────────────────────────────────────
   Une bordure fine plutot qu'une ombre : sur un ecran de bureau, la separation
   suffit et l'ombre ferait flotter chaque bloc. */
.card {
    background: var(--surface);
    padding: 22px 24px;
    border-radius: var(--r-lg);
    border: 1px solid var(--outline-variant);
}
/* AUCUNE OMBRE, nulle part : c'est la regle du handoff, et elle tient
   toute la hierarchie par le fond et une bordure de 1 px. Une carte qui
   voulait se distinguer le fait par une bordure plus franche. */
.card--elevee { border-color: var(--outline); }
.card-entete {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin-bottom: 16px;
    flex-wrap: wrap;
}
.card-entete h2 { font-size: 1.12rem; font-weight: 600; margin: 0; letter-spacing: -.01em; }
.discret { color: var(--on-surface-variant); font-size: .82rem; }

/* ── Cartes de chiffres ────────────────────────────────────────────────────
   Le carre de couleur porte le sens, pas la decoration : vert ce qui va, rouge
   ce qui manque, ambre ce qui attend. Pas de fonte d'icones — le hub tourne
   sans internet, et un glyphe systeme suffit. */
.stat-grille {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(210px, 100%), 1fr));
    gap: 12px;
}
.stat-carte {
    display: flex;
    align-items: center;
    gap: 16px;
    padding: 18px 20px;
    border-radius: var(--r-lg);
    background: var(--surface);
    border: 1px solid var(--outline-variant);
    color: inherit;
    transition: box-shadow .15s ease, transform .15s ease;
}
a.stat-carte:hover { border-color: var(--outline); }
.stat-marque {
    display: grid;
    place-items: center;
    width: 52px; height: 52px;
    flex: 0 0 auto;
    border-radius: var(--r-md);
    font-size: 22px;
    line-height: 1;
    background: var(--surface-container);
    color: var(--on-surface-variant);
}
.stat-marque--accent  { background: var(--primary-container); color: var(--primary); }
.stat-marque--ok      { background: var(--success-container);  color: var(--success); }
.stat-marque--attente { background: var(--warning-container);  color: var(--warning); }
.stat-marque--alerte  { background: var(--error-container);    color: var(--error); }
.stat-valeur {
    font-family: var(--mono);
    font-size: 1.6rem;
    font-weight: 700;
    line-height: 1.1;
    letter-spacing: -.02em;
    font-variant-numeric: tabular-nums;
}
.stat-unite { font-size: .82rem; font-weight: 600; color: var(--on-surface-variant); }
.stat-libelle { font-size: .8rem; color: var(--on-surface-variant); margin-top: 3px; }

/* ── Tableau de donnees ────────────────────────────────────────────────────
   L'en-tete en capitales espacees, les lignes separees par un filet, la ligne
   survolee qui s'eclaire. Rien d'autre : ce qu'on lit, ce sont les chiffres. */
.data-table { width: 100%; border-collapse: collapse; font-size: .9rem; }
.data-table th {
    text-align: left;
    padding: 11px 16px;
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 1.2px;
    color: var(--outline);
    border-bottom: 1px solid var(--outline-variant);
    white-space: nowrap;
}
.data-table td {
    padding: 13px 16px;
    border-bottom: 1px solid var(--outline-variant);
    vertical-align: middle;
}
.data-table tbody tr { transition: background .12s ease; }
.data-table tbody tr:hover { background: var(--surface-container); }
.data-table tr:last-child td { border-bottom: none; }
.data-table .num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }

/* ── LA CELLULE D'ACTIONS ────────────────────────────────────────────────────

   Les actes d'une ligne forment UNE RANGEE, jamais un empilement. C'etait le
   defaut : des ancres de niveau bloc, des formulaires en `inline-flex` et de
   l'espace blanc entre les deux, dans une cellule qui n'avait pour toute mise
   en page qu'un `text-align: right`. Selon ce qu'on y mettait, ca s'alignait
   ou ca ne s'alignait pas.

   Le `<td>` ne devient PAS lui-meme une boite flex : une cellule de tableau
   qui cesse d'etre une cellule perd son alignement vertical avec ses voisines.
   C'est son contenu qui est une rangee, d'ou le `.rang` a l'interieur.

   `width: 1%` demande a la colonne de ne prendre que ce qu'il lui faut : sans
   ca, la colonne des actions s'etire et pousse le nom a gauche de l'ecran. */
.data-table th.actes,
.data-table td.actes { width: 1%; white-space: nowrap; text-align: right; }
.data-table td.actes .rang {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 6px;
}
/* Un <form> est un bloc : sans ca, chaque bouton enveloppe d'un formulaire
   casse la rangee a lui tout seul. */
.data-table td.actes .rang > form { display: flex; align-items: center; gap: 6px; margin: 0; }

/* UNE SEULE HAUTEUR dans la rangee, quoi qu'on y mette. Un champ de saisie a
   34 px a cote d'un bouton a 30 laisse un decalage de deux pixels en haut et
   en bas — invisible sur une ligne, evident sur douze. */
.data-table td.actes .rang .btn,
.data-table td.actes .rang .acte,
.data-table td.actes .rang .saisie {
    height: 30px;
    min-height: 30px;
    flex: 0 0 auto;
}
.data-table .sous { display: block; font-size: .78rem; color: var(--on-surface-variant); }
.data-table .manque { color: var(--error); font-weight: 600; }
.data-table .zero { color: var(--outline); }

/* ── Pastille d'etat ───────────────────────────────────────────────────────*/
.badge {
    display: inline-flex;
    align-items: center;
    height: 24px;
    padding: 0 10px;
    border-radius: var(--r-full);
    font-size: .74rem;
    font-weight: 600;
    white-space: nowrap;
    background: var(--surface-container-hi);
    color: var(--on-surface-variant);
}
.badge--ok     { background: var(--success-container); color: var(--success); }
.badge--alerte { background: var(--error-container);   color: var(--error); }
.badge--attente{ background: var(--warning-container); color: var(--warning); }

/* ── Grille de definitions ────────────────────────────────────────────────*/
.detail-grille {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(200px, 100%), 1fr));
    gap: 18px;
}
.detail-grille dt {
    font-size: .72rem;
    text-transform: uppercase;
    letter-spacing: .05em;
    color: var(--on-surface-variant);
    font-weight: 600;
    margin-bottom: 4px;
}
.detail-grille dd { margin: 0; font-size: 1rem; }

/* ── Rien a montrer ───────────────────────────────────────────────────────
   Ne vaut pas la moitie d'un ecran. */
.vide { text-align: center; padding: 30px 16px; color: var(--on-surface-variant); }
.vide .signe { font-size: 34px; color: var(--outline); display: block; margin-bottom: 8px; }

/* ── Le bloc « qui est connecte », en bas du tiroir ───────────────────────*/
.lateral-qui {
    margin-top: auto;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 12px 14px 4px;
    border-top: 1px solid var(--outline-variant);
}
.lateral-qui .infos { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.lateral-qui .nom { font-size: .88rem; font-weight: 600; }
.lateral-qui .role { font-size: .74rem; color: var(--on-surface-variant); }
.lateral-qui .sortir {
    display: grid; place-items: center;
    width: 38px; height: 38px;
    border-radius: var(--r-full);
    color: var(--on-surface-variant);
    font-size: 17px;
}
.lateral-qui .sortir:hover { background: var(--surface-container-hi); }

/* Hauteurs de navigation reprises telles quelles : elles sont eprouvees. */
.lateral-nav a { min-height: 46px; }

.lateral-qui .pastille {
    display: grid; place-items: center;
    width: 34px; height: 34px; flex: 0 0 auto;
    border-radius: var(--r-full);
    background: var(--primary-container);
    color: var(--primary);
    font-family: var(--mono);
    font-size: 12px;
    font-weight: 700;
}


[data-mode="jour"] .saisie {
    font-family: var(--font);
    font-size: 15px;
    min-height: 46px;
    background: var(--surface-container);
}
[data-mode="jour"] .saisie.mini { width: 84px; min-height: 40px; font-size: 15px; }
[data-mode="jour"] .saisie.mini.large { width: 122px; }

/* Bandeaux de message, repris du back-office minier. */
.alerte {
    padding: 12px 16px;
    border-radius: var(--r-sm);
    font-size: .9rem;
    background: var(--surface-container);
    color: var(--on-surface);
}
.alerte--erreur  { background: var(--error-container);   color: var(--on-error-container); }
.alerte--succes  { background: var(--success-container); color: var(--on-success-container); }
.alerte--attente { background: var(--warning-container); color: var(--warning); }

.liste-a-venir { margin: 0; padding-left: 20px; display: flex; flex-direction: column; gap: 8px; }
.liste-a-venir li { color: var(--on-surface-variant); }
/* Une rangee de commandes hors tableau — dans le front de nuit, ou les
   cibles restent au pouce. Le back-office a `.rang` dans ses cellules. */
.en-ligne { display: inline-flex; gap: 8px; align-items: center; justify-content: flex-end; }
.en-ligne .btn { min-height: 40px; padding: 0 14px; font-size: 14px; }
.office .en-ligne .btn { min-height: 30px; padding: 0 13px; font-size: .78rem; }
.page-barre .btn { min-height: 42px; padding: 0 18px; font-size: 14.5px; }


/* Les icones dans la navigation et les cartes de chiffres. */
.lateral-nav a .ico { font-size: 20px; margin-right: 12px; color: var(--on-surface-variant); }
.lateral-nav a.actif .ico { color: var(--on-primary-container); }
.lateral-service .ico { font-size: 20px; margin-right: 10px; }
.stat-marque .ico { font-size: 26px; }
.btn .ico { font-size: 19px; }
.burger .ico { font-size: 22px; }
.lateral-qui .sortir .ico { font-size: 20px; }
.vide .ico { font-size: 38px; color: var(--outline); display: block; margin-bottom: 8px; }

.bascule-mode {
    display: grid; place-items: center;
    width: 40px; height: 40px; flex: 0 0 auto;
    border-radius: var(--r-full);
    color: var(--on-surface-variant);
}
.bascule-mode:hover { background: var(--surface-container); }


/* ── Catalogue en grille ─────────────────────────────────────────────────────

   Repris de la vue « cartes » des vehicules du back-office minier : photo en
   16/10, badge d'etat en surimpression, titre + chip, meta, actions en pied.

   Ce qui change, ce sont les champs. Le chiffre pour lequel on ouvre cette
   page, c'est le PRIX — il a donc la taille d'un chiffre qu'on lit.
*/
.grille-cartes {
    display: grid;
    gap: 12px;
    grid-template-columns: repeat(auto-fill, minmax(min(158px, 100%), 1fr));
}

.carte-produit {
    position: relative;
    display: flex;
    flex-direction: column;
    background: var(--surface);
    border: 1px solid var(--outline-variant);
    border-radius: var(--r-md);
    overflow: hidden;
    transition: box-shadow .15s ease, transform .15s ease;
}
.carte-produit:hover { border-color: var(--outline); }
.carte-produit--rupture { opacity: .72; }

.carte-produit__media {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    aspect-ratio: 4 / 3;
    background: color-mix(in srgb, var(--c, var(--outline)) 20%, var(--surface-container-hi));
    overflow: hidden;
}
.carte-produit__media img { width: 100%; height: 100%; object-fit: cover; display: block; }
.carte-produit__media .lettre {
    font-family: var(--mono);
    font-size: 26px;
    font-weight: 700;
    color: var(--c, var(--on-surface-variant));
    letter-spacing: .02em;
}
.carte-produit__etat { position: absolute; top: 6px; left: 6px; }
.carte-produit__etat.badge { height: 20px; padding: 0 8px; font-size: .68rem; }

.carte-produit__corps {
    padding: 9px 11px 11px;
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    gap: 3px;
}
.carte-produit__nom {
    font-size: .84rem;
    font-weight: 600;
    line-height: 1.3;
    color: var(--on-surface);
}
.carte-produit__nom:hover { color: var(--primary); }
.carte-produit__prix {
    font-size: 1.05rem;
    font-weight: 700;
    letter-spacing: -.02em;
    line-height: 1.15;
    font-variant-numeric: tabular-nums;
    margin-top: auto;
}
/* La devise en petit et en gris : le chiffre est ce qu'on lit, l'unite ce
   qu'on verifie. Elle ne doit pas peser autant que lui. */
.carte-produit__prix .unite {
    font-size: .68rem;
    font-weight: 600;
    color: var(--on-surface-variant);
    margin-left: 4px;
}

/* Les actes servent une fois par mois ; le nom et le prix se lisent tous les
   jours. Ils restent donc caches jusqu'au survol — et toujours visibles la ou
   il n'y a pas de survol, c'est-a-dire au doigt. */
.carte-produit__actions {
    position: absolute;
    top: 6px; right: 6px;
    display: flex;
    gap: 4px;
    opacity: 0;
    transition: opacity .15s ease;
}
.carte-produit:hover .carte-produit__actions,
.carte-produit:focus-within .carte-produit__actions { opacity: 1; }
@media (hover: none) { .carte-produit__actions { opacity: 1; } }

.acte {
    /* INLINE-grid, et c'est la correction qui compte : en `grid` tout court,
       le bouton est de niveau BLOC — deux actes dans une meme cellule se
       posaient l'un SOUS l'autre au lieu de s'aligner. */
    display: inline-grid;
    place-items: center;
    width: 28px; height: 28px;
    border: none;
    border-radius: var(--r-full);
    background: color-mix(in srgb, var(--surface) 84%, transparent);
    backdrop-filter: blur(6px);
    color: var(--on-surface-variant);
    cursor: pointer;
    padding: 0;
}
.acte:hover { background: var(--surface); color: var(--on-surface); }
.acte .ico { font-size: 16px; }

.btn--sm { min-height: 32px; padding: 0 10px; font-size: .78rem; gap: 5px; }
.btn--sm .ico { font-size: 16px; }
.btn--icone { width: 32px; min-width: 32px; padding: 0; }
.btn--icone .ico { font-size: 16px; }

/* Le chip de station, repris tel quel. */
.chip {
    display: inline-flex;
    align-items: center;
    height: 20px;
    padding: 0 8px;
    border-radius: var(--r-full);
    background: var(--surface-container-hi);
    color: var(--on-surface-variant);
    font-size: .68rem;
    font-weight: 600;
}


/* ── Formulaires et filtres ──────────────────────────────────────────────────

   Repris tels quels du back-office minier : le champ contourne, l'etiquette en
   capitales espacees AU-DESSUS plutot qu'un libelle flottant dans une boite
   remplie. Plus leger a lire quand un formulaire en aligne huit.
*/
.form-pile { display: flex; flex-direction: column; gap: 16px; }

.field { display: flex; flex-direction: column; gap: 6px; }
.field > span,
.field > label {
    font-size: .75rem;
    font-weight: 600;
    color: var(--on-surface-variant);
    text-transform: uppercase;
    letter-spacing: .04em;
}
.field input,
.field textarea,
.field select {
    width: 100%;
    padding: 10px 14px;
    border: 1px solid var(--outline-variant);
    border-radius: var(--r-sm);
    background: var(--surface);
    color: var(--on-surface);
    font-family: inherit;
    font-size: .92rem;
    outline: none;
    transition: border-color .15s ease;
}
.field select { cursor: pointer; }
.field input:focus, .field textarea:focus, .field select:focus { border-color: var(--primary); }
.field input::placeholder { color: var(--outline); }
.field-aide {
    font-size: .72rem;
    font-weight: 600;
    color: var(--on-surface-variant);
    text-transform: none;
    letter-spacing: 0;
}

.form-row {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(190px, 100%), 1fr));
    gap: 16px;
}
.form-actions { display: flex; gap: 10px; margin-top: 4px; flex-wrap: wrap; }

/* ── Barre de filtres ───────────────────────────────────────────────────────
   L'etat est dans l'URL, pas dans un script : un filtre se partage, se met en
   favori, et survit au rechargement. */
.filter-bar {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    align-items: flex-end;
}
.filter-field { flex: 1 1 160px; min-width: 0; max-width: 240px; }
.filter-chips { display: flex; flex-wrap: wrap; gap: 8px; }
.filter-chip {
    height: 34px;
    padding: 0 16px;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    border-radius: var(--r-full);
    border: 1px solid var(--outline-variant);
    color: var(--on-surface-variant);
    font-size: .82rem;
    font-weight: 500;
    transition: background .15s ease, color .15s ease, border-color .15s ease;
}
.filter-chip:hover { background: var(--surface-container); }
.filter-chip.actif {
    background: var(--primary);
    color: var(--on-primary);
    border-color: transparent;
    font-weight: 600;
}


/* ── La modale ───────────────────────────────────────────────────────────────
   Reprise du back-office minier. Elle s'ouvre en haut plutot qu'au centre : un
   formulaire long doit pouvoir grandir vers le bas sans sauter a l'ecran. */
.modal-couche {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, .5);
    display: flex;
    align-items: flex-start;
    justify-content: center;
    padding: 6vh 16px;
    z-index: 200;
    opacity: 0;
    transition: opacity .2s ease;
    overflow-y: auto;
}
.modal-couche.ouverte { opacity: 1; }
.modal {
    background: var(--surface);
    border-radius: var(--r-lg);
    border: 1px solid var(--outline-variant);
    width: min(720px, 100%);
    max-height: 88vh;
    display: flex;
    flex-direction: column;
    transform: translateY(-10px) scale(.98);
    transition: transform .2s ease;
}
.modal-couche.ouverte .modal { transform: none; }
.modal__entete {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 16px 22px;
    border-bottom: 1px solid var(--outline-variant);
}
.modal__entete h2 { font-size: 1.1rem; font-weight: 600; margin: 0; }
.modal__fermer {
    background: none; border: none; cursor: pointer;
    color: var(--on-surface-variant);
    width: 36px; height: 36px; flex: 0 0 auto;
    border-radius: var(--r-full);
    display: inline-flex; align-items: center; justify-content: center;
}
.modal__fermer:hover { background: var(--surface-container-hi); }
.modal__corps { padding: 22px; overflow-y: auto; }
.modal__corps .card { border: none; padding: 0; background: transparent; }
.modal__corps .card + .card { margin-top: 20px; padding-top: 20px; border-top: 1px solid var(--outline-variant); }
.modal__attente { padding: 48px; text-align: center; color: var(--on-surface-variant); }

/* La confirmation : centree, courte, et le bouton dangereux en rouge. */
.modal-couche--confirm { align-items: center; }
.modal--confirm { width: min(420px, 100%); }
.confirm__corps { padding: 24px 24px 8px; }
.confirm__titre { font-size: 1.15rem; font-weight: 600; margin: 0 0 8px; }
.confirm__msg { color: var(--on-surface-variant); font-size: .95rem; line-height: 1.5; margin: 0; }
.confirm__actions {
    display: flex;
    justify-content: flex-end;
    gap: 10px;
    padding: 16px 24px 20px;
}
.confirm__actions .btn { min-height: 42px; padding: 0 18px; font-size: .9rem; }

.chip-groupe { display: inline-flex; align-items: center; gap: 2px; }
.chip-modifier {
    display: grid; place-items: center;
    width: 30px; height: 30px;
    border-radius: var(--r-full);
    color: var(--outline);
    opacity: 0;
    transition: opacity .15s ease;
}
.chip-groupe:hover .chip-modifier { opacity: 1; }
.chip-modifier:hover { background: var(--surface-container-hi); color: var(--on-surface); }
.chip-modifier .ico { font-size: 16px; }


/* ── L'aide en infobulle ─────────────────────────────────────────────────────

   Les phrases d'explication sous chaque champ alourdissent un formulaire qui
   en aligne huit : on les lit une fois, puis elles ne sont plus que du bruit
   entre les champs. Elles passent donc derriere un « ? ».

   C'est un BOUTON, pas un `title=""` : le survol n'existe pas sur une tablette,
   et le gerant est sur une tablette. Taper le bouton lui donne le focus, donc
   affiche l'infobulle ; taper ailleurs la referme.
*/
.aide {
    position: relative;
    display: inline-grid;
    place-items: center;
    width: 17px; height: 17px;
    margin-left: 5px;
    vertical-align: middle;
    border: none;
    border-radius: var(--r-full);
    background: var(--surface-container-hi);
    color: var(--on-surface-variant);
    font-family: var(--font);
    font-size: 11px;
    font-weight: 700;
    line-height: 1;
    cursor: pointer;
    padding: 0;
}
/* Le survol change la PASTILLE, pas la bulle : il signale qu'on peut cliquer,
   il ne repond pas a la place de l'utilisateur. */
.aide:hover { background: var(--surface-container); color: var(--on-surface); }
.aide:focus { background: var(--primary); color: var(--on-primary); outline: none; }

.aide::after {
    content: attr(data-aide);
    /* `* { box-sizing: border-box }` NE TOUCHE PAS les pseudo-elements : sans
       cette ligne, la bulle faisait 272 px — 250 de contenu plus deux fois 11
       de marge interieure — et le script qui la cale lisait 250. Trois pixels
       de debordement, exactement ceux qu'on cherchait. */
    box-sizing: border-box;
    position: absolute;
    left: 50%;
    bottom: calc(100% + 8px);
    /* LA BULLE GLISSE POUR RESTER DANS L'ECRAN. Centree sur un « ? » colle au
       bord droit, ses 250 px depassaient le viewport tant qu'on la lisait. Le
       script mesure a l'ouverture et pose `--aide-decalage` sur la pastille ;
       la pointe, elle, reste centree sur le bouton — c'est lui qu'elle vise. */
    transform: translateX(calc(-50% + var(--aide-decalage, 0px)));
    width: max-content;
    max-width: 250px;
    padding: 8px 11px;
    border-radius: var(--r-sm);
    background: var(--inverse-surface);
    color: var(--inverse-on-surface);
    font-size: .78rem;
    font-weight: 400;
    line-height: 1.45;
    text-transform: none;
    letter-spacing: 0;
    text-align: left;
    white-space: normal;
    border: 1px solid var(--outline-variant);   /* pas d'ombre : fond + bordure */
    /* FERMEE, LA BULLE N'EXISTE PAS. Elle etait en `opacity: 0` : invisible,
       mais toujours posee dans la page — 250 px de large, centree sous un « ? »
       colle au bord droit, elle depassait le viewport et la page entiere se
       mettait a defiler lateralement. Une opacite nulle ne retire rien de la
       zone de defilement ; seul `display: none` le fait. */
    display: none;
    pointer-events: none;
    z-index: 30;
}
/* La petite pointe vers le champ. */
.aide::before {
    content: "";
    position: absolute;
    left: 50%;
    bottom: calc(100% + 3px);
    transform: translateX(-50%);
    border: 5px solid transparent;
    border-top-color: var(--inverse-surface);
    display: none;
    pointer-events: none;
    z-index: 30;
}
/* ELLE S'OUVRE AU CLIC, PAS AU SURVOL.
   Au survol, traverser un formulaire faisait s'allumer une bulle par champ :
   du texte qui apparait sous le curseur pendant qu'on vise autre chose, et qui
   recouvre le champ suivant. Une aide se demande, elle ne s'impose pas.

   `:focus` seul suffit, sans une ligne de JavaScript : cliquer une pastille la
   met au focus — la bulle s'ouvre ; cliquer ailleurs le lui retire — elle se
   ferme. Au clavier, Tab l'ouvre de la meme facon, ce qui est exactement ce
   qu'il faut. Et ca marche dans les deux coques, alors que le script du
   back-office n'est pas charge sur les ecrans de nuit. */
/* A l'ouverture, une ANIMATION et non une transition : une transition ne se
   joue pas sur un passage de `display: none` a `block`, une animation si. */
.aide:focus::after, .aide:focus::before,
.aide.ouverte::after, .aide.ouverte::before {
    display: block;
    animation: aide-entre .12s ease both;
}
@keyframes aide-entre { from { opacity: 0; } to { opacity: 1; } }
.aide.ouverte { background: var(--primary); color: var(--on-primary); }

/* Pres du bord gauche, l'infobulle se recale pour ne pas sortir de la carte. */
.field:first-child .aide::after { left: 0; transform: none; }
.field:first-child .aide::before { left: 8px; transform: none; }


/* Le « ? » dans le front de nuit : plus gros, parce qu'on y vise avec un pouce
   et pas avec une souris. Meme composant, autre calibration — comme partout. */
[data-mode="nuit"] .aide { width: 22px; height: 22px; font-size: 13px; margin-left: 8px; }
[data-mode="nuit"] .aide::after { font-size: .82rem; max-width: 260px; }

/* Dans un titre de section en capitales, l'infobulle reprend une casse
   normale : c'est une phrase, pas une etiquette. */
.section-titre .aide::after,
.card-entete h2 .aide::after { text-transform: none; letter-spacing: 0; }
.card-entete h2 .aide { vertical-align: 3px; }

/* La pastille de stock d'une carte mene au stock : c'est le meme article, vu
   sous l'autre question. */
.carte-produit__vers-stock {
    position: absolute;
    top: 6px; left: 6px;
    width: 90px; height: 22px;
    z-index: 2;
}
.acte--table { background: var(--surface-container); backdrop-filter: none; }

/* Le rappel de l'article qu'on met en vente : son nom vient du stock et ne se
   modifie pas ici. */
.entete-article {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 12px 14px;
    border-radius: var(--r-sm);
    background: var(--surface-container);
}
.entete-article .nom { font-size: 1rem; font-weight: 600; }
.entete-article .sous { font-size: .8rem; color: var(--on-surface-variant); }

/* Le champ photo : l'aperçu à côté du bouton, pour qu'on voie ce qu'on change. */
.photo-champ { display: flex; align-items: center; gap: 14px; }
.photo-apercu {
    display: grid;
    place-items: center;
    width: 72px; height: 54px;
    flex: 0 0 auto;
    border-radius: var(--r-sm);
    overflow: hidden;
    background: color-mix(in srgb, var(--c, var(--outline)) 20%, var(--surface-container-hi));
}
.photo-apercu img { width: 100%; height: 100%; object-fit: cover; display: block; }
.photo-apercu .lettre {
    font-family: var(--mono);
    font-size: 18px;
    font-weight: 700;
    color: var(--c, var(--on-surface-variant));
}
.photo-actions { display: flex; flex-direction: column; gap: 6px; align-items: flex-start; }
.bascule--mince {
    min-height: 32px;
    padding: 0 10px;
    font-size: .8rem;
    background: transparent;
}
.bascule--mince input { width: 17px; height: 17px; }

.modal__attente { padding: 34px; text-align: center; color: var(--on-surface-variant); }


/* ══ LA DENSITE DU BACK-OFFICE ═══════════════════════════════════════════════

   Reprise du back-office minier, ou la meme question s'etait posee et avait
   ete tranchee. Deux principes, et ils tiennent tout le reste.

   **UNE SEULE HAUTEUR DE BOUTON.** Un « ajouter » a 56 px a cote d'un
   « annuler » a 48 et d'une action de ligne a 32, c'etaient trois echelles
   pour un seul travail — et la plus haute achetait sa largeur sans rien
   donner en retour. Tout passe a 30 px ; `.btn--sm` reste un alias pour que
   les gabarits qui le demandent se lisent encore.

   **L'ESPACE VIENT DU CONTENEUR, JAMAIS DE L'ENFANT.** Un `gap` sur le parent
   et une `margin-bottom` sur l'enfant s'additionnent : la page des filtres
   respirait a 30 px la ou les cartes se suivaient a 14. Les marges partent,
   le `gap` decide seul — une valeur, 12 px, du haut de la page au bas d'une
   grille.

   Tout est ici, sous `.office`, et NULLE PART AILLEURS : le front de nuit
   garde ses cibles au pouce. On est debout dans une salle noire, pas assis
   devant un tableau. Groupe en un bloc pour pouvoir se relire et se reregler
   d'un seul coup d'oeil. */

/* ── Les boutons ── */
.office .btn,
.office .btn--sm {
    min-height: 30px;
    height: 30px;
    padding: 0 13px;
    font-size: .78rem;
    gap: 6px;
}
.office .btn .ico { font-size: 17px; }
/* Le bouton principal d'une page garde sa couleur et son coin adouci — il
   n'est plus le plus haut, il reste le plus visible. */
.office .btn--primaire { border-radius: var(--r-sm); }
.office .btn--primaire:hover { filter: brightness(1.06); }
/* Les actions de ligne rejoignent la meme hauteur : une table ou les boutons
   ne s'alignent pas sur ceux de l'entete se lit comme deux tables. */
.office .acte--table { width: 30px; height: 30px; }
.office .acte--table .ico { font-size: 17px; }

/* ── L'echelle typographique ──
   Le texte courant n'avait pas de taille a lui et restait a la racine, pendant
   que tables, champs et titres descendaient chacun. Dans une carte, une phrase
   ordinaire devenait la plus grosse chose dessus — plus grosse que le titre de
   la carte. Il rejoint les tables a .9rem, ce qui remet l'echelle en ordre :
   titre .98, champ .92, texte et tables .9, discret .8. */
.office { font-size: .9rem; }
.office .card-entete h2,
.office .modal__entete h2 { font-size: .98rem; }
/* `min-height` et non `height` : une barre a hauteur figee deborde des qu'un
   titre long ou un bouton d'action large s'y ajoute. */
/* Meme gouttiere que le corps : le titre se pose exactement au-dessus de la
   premiere carte, a toutes les largeurs. `min-height` et non `height` — une
   barre figee deborde des qu'un titre long ou un bouton large s'y ajoute. */
.office .page-barre {
    min-height: 52px;
    padding: 6px max(var(--gouttiere), (100% - var(--mesure-jour)) / 2);
    flex-wrap: wrap;
}
.office .page-barre h1 { font-size: 1.05rem; }
.office .stat-valeur { font-size: 19px; }
.office .discret { font-size: .8rem; }

/* ── L'espace ──
   Une seule valeur, 12 px, de la page a la grille. Le bourrage des cartes
   descend avec : 24 px de marge interieure autour d'un tableau dense, c'etait
   une bordure blanche qui prenait la place du contenu. */
/* Ces deux valeurs vivent desormais dans `.page-corps` lui-meme, avec la
   mesure : les separer faisait qu'une correction de l'un oubliait l'autre. */
.office .card { padding: 16px; }
.office .card-entete { margin-bottom: 10px; }
.office .stat-grille { gap: 12px; }
.office .grille-cartes { gap: 12px; }
.office .stat-carte { padding: 13px; gap: 12px; }
.office .stat-marque { width: 36px; height: 36px; font-size: 20px; border-radius: var(--r-sm); }
.office .form-pile { gap: 12px; }
.office .modal__corps .card + .card { margin-top: 14px; padding-top: 14px; }

/* ── Les tables ──
   Elles portent l'essentiel du back-office : une ligne plus courte, c'est deux
   lignes de plus a l'ecran sans rien perdre. */
.office .data-table th { padding: 7px 12px; }
.office .data-table td { padding: 8px 12px; }

/* Les cases a remplir d'un tableau de reception etaient calibrees pour un
   pouce : 46 px de haut dans une table dense, la ligne faisait 62 px et on en
   voyait huit. Elles rejoignent l'echelle assise — un gerant au quai est sur
   une tablette, pas dans le noir. */
.office .saisie { min-height: 34px; font-size: .9rem; padding: 0 10px; }
.office .saisie.mini { width: 76px; min-height: 34px; font-size: .9rem; }
.office .saisie.mini.large { width: 108px; }

/* ── Les puces ── */
.office .filter-chip { height: 30px; padding: 0 14px; }
.office .badge { height: 24px; padding: 0 10px; }

@media (max-width: 768px) {
    /* Plus serre sur un telephone, ou chaque pixel de largeur appartient au
       contenu. On baisse LA GOUTTIERE, pas chaque bourrage un par un : tout ce
       qui s'aligne dessus suit d'un coup, et rien ne peut se desynchroniser.
       Pas en dessous de 10 : une carte collee au bord de l'ecran se lit mal. */
    :root { --gouttiere: 10px; }
    .page-corps { padding-block: 10px; gap: 10px; }
    .office .card { padding: 12px; }
    /* Un champ de filtre a mi-largeur sur un telephone, c'est un champ qu'on
       ne peut pas lire : ils passent chacun sur leur ligne. */
    .filter-field { flex: 1 1 100%; max-width: none; }
}

/* ══ LES MESSAGES ════════════════════════════════════════════════════════════

   Une couche fixe, au-dessus des modales (300 contre 200) : un message reste
   lisible meme si une boite est ouverte.

   La PILE ne recoit pas les clics, chaque MESSAGE si — sinon une bande
   invisible en travers de l'ecran avalerait les clics du contenu en dessous. */
.toasts {
    position: fixed;
    z-index: 300;
    display: flex;
    flex-direction: column;
    gap: 8px;
    pointer-events: none;
    width: min(420px, calc(100vw - 28px));
    /* Le sens d'ou le message arrive, et ou il repart. */
    --depart: -12px;
    /* Coque de nuit : EN HAUT. Le bas de l'ecran appartient au pouce et au
       panneau d'addition — un message pose la se ferait toucher par erreur. */
    top: 12px;
    left: 50%;
    transform: translateX(-50%);
}
/* Back-office : EN BAS A DROITE. En haut, la barre de page est collante et le
   message la recouvrirait ; en bas a droite il ne masque ni le titre, ni le
   bouton d'action, ni la premiere ligne d'un tableau. */
.office .toasts {
    --depart: 12px;
    top: auto;
    bottom: 16px;
    left: auto;
    right: 16px;
    transform: none;
    align-items: flex-end;
}

.toast {
    pointer-events: auto;
    display: flex;
    align-items: flex-start;
    gap: 10px;
    width: 100%;
    padding: 12px 12px 12px 14px;
    border-radius: var(--r-md);
    background: var(--inverse-surface);
    color: var(--inverse-on-surface);
    border-right: 1px solid var(--outline);
    font-size: 15px;
    line-height: 1.4;
    animation: toast-entre .22s ease both;
}
.office .toast { font-size: .85rem; padding: 10px 10px 10px 12px; }

/* La couleur porte le sens, l'icone le repete : a 3 h du matin on lit une
   forme avant de lire un mot. */
.toast--succes  { background: var(--success-container); color: var(--on-success-container); }
.toast--erreur  { background: var(--error-container);   color: var(--on-error-container); }
.toast--attente { background: var(--warning-container); color: var(--warning); }

.toast__ico { font-size: 20px; flex: 0 0 auto; margin-top: 1px; }
.toast__texte { flex: 1 1 auto; min-width: 0; }
.toast__fermer {
    flex: 0 0 auto;
    display: grid;
    place-items: center;
    width: 26px; height: 26px;
    margin: -3px -2px 0 0;
    border: none;
    border-radius: var(--r-full);
    background: transparent;
    color: inherit;
    opacity: .65;
    cursor: pointer;
    padding: 0;
}
.toast__fermer:hover { opacity: 1; background: rgba(0, 0, 0, .10); }
.toast__fermer .ico { font-size: 18px; }

.toast.partant {
    opacity: 0;
    transform: translateY(var(--depart));
    transition: opacity .2s ease, transform .2s ease;
}
@keyframes toast-entre {
    from { opacity: 0; transform: translateY(var(--depart)); }
    to   { opacity: 1; transform: none; }
}
/* Un message qui glisse pendant qu'on lit derriere, c'est du mouvement qu'on
   n'a pas demande. */
@media (prefers-reduced-motion: reduce) {
    .aide::after, .aide::before { animation: none; }
    .toast { animation: none; }
    .toast.partant { transform: none; transition: opacity .15s ease; }
}

/* ══ LE FILET ════════════════════════════════════════════════════════════════

   Ce qui casse une mise en page n'est presque jamais la mise en page : c'est
   une donnee inattendue. Un nom d'article sans espace, une image plus large
   que sa carte, un libelle de trois mots la ou on en attendait un.

   Ces regles ne changent rien tant que tout va bien. Elles evitent qu'une
   seule saisie de travers deforme un ecran — et personne ne saisit droit a
   3 h du matin. */

/* Une image ne deborde jamais de son cadre, ou qu'on la mette. */
img, svg, video, canvas { max-width: 100%; }

/* Coupe UNIQUEMENT si le mot seul ne rentre pas — les mots normaux gardent
   leur cesure ordinaire. Sur les tuiles et les cartes, dont la largeur est
   fixee par la grille, il n'y a pas d'echappatoire : c'est couper ou deborder. */
.carte-produit__nom, .produit .nom, .entete-article .nom,
.data-table td, .data-table .sous, .toast__texte, .field-aide,
.stat-libelle, .detail-grille dd { overflow-wrap: break-word; }

/* Un enfant de flex ou de grille refuse de retrecir en dessous de son contenu
   tant qu'on ne le lui dit pas : `min-width: auto` est le defaut. C'est la
   cause la plus frequente d'un debordement lateral qu'on ne s'explique pas. */
.entete-cmd .ident, .topbar .titre, .page-barre h1,
.carte-produit__corps, .toast__texte { min-width: 0; }

/* Les conteneurs de grille et leurs enfants, une bonne fois. */
.dash-grille > *, .stat-grille > *, .grille-cartes > *,
.form-row > *, .detail-grille > *, .chiffres > *,
.stat-carte > *, .stat-carte { min-width: 0; }

/* ── Le détail d'un événement, à plat ────────────────────────────────────────
   Du JSON brut ne se lit pas à 4 h du matin. Des couples clef/valeur qui se
   replient sur eux-mêmes tiennent dans une cellule sans la faire exploser. */
.detail-plat { display: flex; flex-wrap: wrap; gap: 4px 10px; max-width: 52ch; }
.detail-plat .paire { font-size: .8rem; color: var(--on-surface-variant); }
.detail-plat .paire b {
    font-weight: 600;
    color: var(--on-surface);
    font-variant-numeric: tabular-nums;
}

.pagination { display: flex; justify-content: space-between; gap: 10px; margin-top: 12px; }
.pagination .btn:only-child { margin-left: auto; }

/* ── Le tableau de bord ──────────────────────────────────────────────────────

   Deux colonnes sur un écran de bureau, une seule dès qu'il se rétrécit. Le
   graphe des nuits est le plus dense : il prend toute la largeur. */
.dash-grille {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(340px, 100%), 1fr));
    gap: 12px;
}
.dash-graphique { margin: 0; }
.dash-graphique:first-child { grid-column: 1 / -1; }

/* Une HAUTEUR FIXE, et c'est nécessaire : un canvas sans hauteur déclarée
   grandit à chaque redimensionnement, indéfiniment. `position: relative` donne
   à Chart.js le conteneur dont il mesure la taille — et `width: 100%` l'empêche
   de mesurer le canvas qu'il vient lui-même de dimensionner, ce qui est la
   boucle par laquelle une page se met à défiler latéralement. */
.cadre-graphe { position: relative; width: 100%; min-width: 0; height: 240px; }
/* `display: block` : un canvas est en ligne par défaut, donc posé sur une
   ligne de texte — d'où quelques pixels de blanc sous chaque graphique. */
.cadre-graphe canvas { display: block; }
.dash-graphique:first-child .cadre-graphe { height: 280px; }

/* Le pied de tableau porte les totaux : une ligne qui se distingue des autres
   sans crier. */
.data-table tfoot td {
    border-top: 2px solid var(--outline-variant);
    border-bottom: none;
    padding-top: 10px;
}

@media (max-width: 560px) {
    .cadre-graphe,
    .dash-graphique:first-child .cadre-graphe { height: 210px; }
}

/* ── Le logo « NK Lounge, by NimKora » ─────────────────────────────────────
   SVG en ligne (voir _logo.html) : l'anneau prend le primaire, le monogramme
   et la fumee la couleur du texte. A cote, le lockup de la marque : « NK
   Lounge » en Marcellus, « Lounge » en primaire, et la signature « BY
   NIMKORA » en capitales espacees, gris. Les proportions sont celles de
   nk-lounge-lockup.svg : mot 34/96 du cote de l'icone, signature 10/96
   espacee de 4/96, alignes sur le meme bord gauche. */
.logo {
    display: inline-flex; align-items: center; color: var(--on-surface);
    --logo-taille: 28px;
    gap: calc(var(--logo-taille) * .05);
}
.logo svg { flex: 0 0 auto; display: block; }
.logo__texte { display: flex; flex-direction: column; align-items: flex-start; line-height: 1; }
.logo__mot {
    font-family: var(--marque); font-weight: 400;
    font-size: calc(var(--logo-taille) * .354);
    letter-spacing: 0; white-space: nowrap;
}
.logo__mot em { font-style: normal; color: var(--primary); }
/* PLANCHER A 8 PX sur la signature. Le rapport de la marque (10/96) donne
   4,6 px sous un anneau de 44 : une trainee grise, pas un mot. En dessous de
   8 px, une capitale espacee n'est plus lisible a bout de bras — on garde le
   rapport tant qu'il tient, et la lisibilite quand il ne tient plus. */
.logo__par {
    font-family: var(--font); font-weight: 500;
    font-size: max(8px, calc(var(--logo-taille) * .104));
    letter-spacing: .4em; color: var(--on-surface-variant);
    margin-top: calc(var(--logo-taille) * .09);
    white-space: nowrap;
}
/* Debout dans le noir, la marque se pose en colonne au-dessus du clavier. */
.pin-marque .logo { flex-direction: column; gap: calc(var(--logo-taille) * .1); }
.pin-marque .logo__texte { align-items: center; }

/* ══ FIDELITE AU HANDOFF ═════════════════════════════════════════════════════

   Les jetons etaient justes ; la COMPOSITION ne l'etait pas. Ce bloc rapproche
   chaque ecran de sa maquette, mesure par mesure, apres les avoir vues cote a
   cote. Groupe ici pour se relire d'un coup, comme la passe de densite.

   Regle du handoff qui tient tout : aucune ombre, fond + bordure 1 px, rayons
   14 (cartes) / 10 (champs, nav, petits boutons) / 999 (puces). */

/* ── Le tiroir : 200 px, entrees a 10 px de rayon, icones 18, actif creme ── */
.lateral { padding: 14px 10px; gap: 2px; }
.lateral-marque { padding: 6px 8px 14px; }
.lateral-nav a {
    min-height: 38px;
    padding: 0 10px;
    gap: 10px;
    border-radius: var(--r-sm);
    font-size: 13.5px;
    font-weight: 500;
    color: var(--on-surface-variant);
}
.lateral-nav a .ico { font-size: 19px; }
.lateral-nav a.actif { background: var(--primary-container); color: var(--on-primary-container); font-weight: 600; }
.lateral-qui {
    margin-top: auto;
    padding: 12px 6px 4px;
    border-top: 1px solid var(--outline-variant);
    display: flex; align-items: center; gap: 10px;
}
.lateral-qui .pastille {
    width: 32px; height: 32px; flex: 0 0 auto;
    display: grid; place-items: center;
    border-radius: var(--r-full);
    background: var(--primary-container); color: var(--on-primary-container);
    font-size: 12px; font-weight: 700; font-family: var(--font);
}
.lateral-qui .infos { display: flex; flex-direction: column; min-width: 0; flex: 1; gap: 1px; }
.lateral-qui .nom { font-size: 13px; font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.lateral-qui .role { font-size: 11.5px; color: var(--on-surface-variant); line-height: 1.3; }
.lateral-qui .sortir {
    width: 28px; height: 28px; flex: 0 0 auto;
    display: grid; place-items: center;
    border-radius: var(--r-full); color: var(--on-surface-variant);
}
.lateral-qui .sortir .ico { font-size: 18px; }

/* ── L'en-tete de page : un titre dans la page, pas une barre ─────────────── */
.office .page-barre {
    position: static;
    background: transparent;
    border-bottom: none;
    min-height: 0;
    padding: 24px max(var(--gouttiere), (100% - var(--mesure-jour)) / 2) 0;
    gap: 14px;
}
.office .page-barre h1 { font-size: 20px; font-weight: 700; }
.office .page-corps { padding-top: 14px; }

/* ── Les champs : libelle en minuscules, aide sous le champ en 11 px ──────── */
.office .field > span,
.office .field > label {
    font-size: 12px;
    font-weight: 500;
    text-transform: none;
    letter-spacing: 0;
    color: var(--on-surface-variant);
}
.office .field-aide {
    font-size: 11px;
    font-weight: 400;
    text-transform: none;
    letter-spacing: 0;
    color: var(--outline);
}
.office .filter-field > span { text-transform: none; letter-spacing: 0; font-size: 12px; font-weight: 500; }

/* ── Les cartes de stat : valeur au-dessus, libelle dessous ──────────────── */
.stat-carte > span:last-child,
.stat-carte > div:last-child { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.stat-valeur { display: block; }
.stat-libelle { display: block; font-size: 12px; margin-top: 0; }
.stat-libelle .aide { vertical-align: 1px; }

/* ── Les actions de ligne : des icones nues, pas des pastilles ───────────── */
.office .acte--table { background: transparent; color: var(--on-surface-variant); }
.office .acte--table:hover { background: var(--surface-container); color: var(--on-surface); }

/* ── Les puces de filtre : l'active en creme, pas en brun plein ───────────── */
.office .filter-chip { height: 30px; font-size: 12.5px; border-color: var(--outline-variant); background: var(--surface); }
.office .filter-chip.actif { background: var(--primary-container); color: var(--on-primary-container); border-color: transparent; font-weight: 600; }

/* ── Les barres a pistes : ce qui fait le chiffre, ou part l'argent ───────
   Une barre par ligne, sur une piste claire, la valeur en mono a droite. Pas
   de canvas : trois cellules de grille suffisent, et ca se lit sans script. */
.barres { display: flex; flex-direction: column; gap: 11px; }
.barre-ligne {
    display: grid;
    grid-template-columns: minmax(0, 11ch) minmax(0, 1fr) auto;
    align-items: center;
    gap: 12px;
    font-size: 13px;
}
.barre-ligne .etiquette { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.barre-ligne .piste { height: 10px; border-radius: var(--r-full); background: var(--surface-container); overflow: hidden; }
.barre-ligne .rempli { display: block; height: 100%; border-radius: var(--r-full); background: var(--primary); opacity: .85; }
.barre-ligne .valeur { font-size: 12.5px; color: var(--on-surface-variant); }

/* ── Deux colonnes : tableau de bord (2/1) et depenses (1/2) ─────────────── */
.dash-grille { grid-template-columns: 2fr 1fr; }
.dash-graphique:first-child { grid-column: auto; }
.dash-graphique .cadre-graphe { height: 300px; }
.deux-colonnes { display: grid; grid-template-columns: 1fr 2fr; gap: 12px; align-items: start; }
.deux-colonnes--egales { grid-template-columns: 1fr 1fr; }
@media (max-width: 900px) {
    .dash-grille, .deux-colonnes { grid-template-columns: 1fr; }
}

/* ── La carte : la grille a nu, 4 colonnes, media plein avec initiales blanches */
.grille-cartes { grid-template-columns: repeat(auto-fill, minmax(min(220px, 100%), 1fr)); gap: 16px; }
.carte-produit__media { aspect-ratio: auto; height: 110px; background: var(--c, var(--outline)); }
.carte-produit__media .lettre { color: #fff; font-family: var(--font); font-size: 26px; font-weight: 700; }
.carte-produit__poste { font-size: 12px; color: var(--on-surface-variant); }
.carte-produit__corps { padding: 11px 13px 12px; gap: 3px; }
.carte-produit__nom { font-size: 13px; }
.carte-produit__prix { font-size: 13.5px; color: var(--primary); }
.carte-produit__prix .unite { color: var(--primary); font-weight: 700; margin-left: 5px; }

/* ── Nuit : l'ecran du code, touches rondes de 76 px ─────────────────────── */
.pin-touche { width: 76px; height: 76px; border-radius: var(--r-full); margin: 0 auto; padding: 0; }
.pin-marque .sous { text-transform: none; letter-spacing: 0; font-size: 14px; color: var(--on-surface-variant); }

/* ── Nuit : les chiffres du gerant, libelle en minuscules ─────────────────── */
.chiffre .t { text-transform: none; letter-spacing: 0; font-size: 12px; font-weight: 500; }

/* ── Nuit : mon argent, le gros chiffre a 32 px ───────────────────────────── */
.chiffre--gros .t { text-transform: none; letter-spacing: 0; font-size: 13px; font-weight: 600; }
.chiffre--gros .v { font-size: 32px; }
.chantier b { font-weight: 700; }

/* ── Poste : la file en trois colonnes, « Pret » pleine largeur ──────────── */
.file-postes { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(280px, 100%), 1fr)); gap: 12px; align-content: start; }
.file-postes .commande { display: flex; flex-direction: column; gap: 10px; margin: 0; }
.file-postes .commande .agir { margin-top: auto; }
.file-postes .commande .agir form { display: flex; }
.file-postes .commande .agir .btn { flex: 1; min-height: 56px; border-radius: var(--r-sm); }
.file-postes .plier > summary { font-size: 12px; color: var(--on-surface-variant); }

/* ── Nuit : la carte d'addition, code + place / detail / total + etat ────── */
.addition--fiche { display: grid; grid-template-columns: 1fr auto; gap: 4px 12px; padding: 13px 14px; align-items: start; }
.addition--fiche .num { font-size: 16px; font-weight: 700; }
.addition--fiche .ou { font-size: 13px; color: var(--on-surface-variant); margin-left: 6px; }
.addition--fiche .detail { grid-column: 1; font-size: 12px; color: var(--on-surface-variant); }
.addition--fiche .montant { grid-column: 2; grid-row: 1; font-size: 15px; font-weight: 700; text-align: right; }
.addition--fiche .etats { grid-column: 2; grid-row: 2; justify-self: end; display: flex; gap: 4px; }

/* Etat de la nuit a droite du titre, et une pile de cartes dans un formulaire. */
.etat-nuit { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; }
.etat-nuit .ico { font-size: 17px; }
.pile-cartes { display: flex; flex-direction: column; gap: 12px; min-width: 0; }
.liens-discrets { display: inline-flex; gap: 14px; align-items: center; }

/* Le pied du tiroir : deux icones plus petites, pour que le nom tienne. */
.lateral-qui { gap: 8px; padding-left: 4px; padding-right: 0; }
.lateral-qui .sortir { width: 24px; height: 24px; }
.lateral-qui .sortir .ico { font-size: 17px; }
/* Les etiquettes des barres : quinze caracteres avant de couper, comme les
   noms de la maquette qui tiennent entiers. */
.barre-ligne { grid-template-columns: minmax(0, 15ch) minmax(0, 1fr) auto; }

/* Les paves de tables portent une bordure fine, comme la maquette ; le code
   d'une addition se lit en blanc et en Roboto, pas en mono orange. */
.table-case { border: 1px solid var(--outline-variant); }
.addition--fiche .num { color: var(--on-surface); font-family: var(--font); }

/* Nuit : les chiffres du gerant en 18 px mono/700 comme la maquette ; le gros
   chiffre de « Mon argent » garde ses 32 px. */
.chiffres .chiffre .v { font-size: 18px; }
.chiffre--gros .v { font-size: 32px; }
/* Poste : les tournees pretes en cartes vertes, bordure et fond du jeton OK. */
.panier.pretes .ligne { border: 1px solid var(--success); background: var(--success-container); color: var(--on-success-container); }
.panier.pretes .ligne small { color: var(--on-success-container); opacity: .8; }
/* Poste : le bouton du bas a gauche, en largeur de contenu, 48 px de haut. */
.barre-bas--gauche { flex-direction: row; }
.barre-bas--gauche .btn { width: auto; min-height: 48px; padding: 0 22px; }

/* Poste : le bouton « Pret » prend toute la largeur de sa carte, et le repli
   « Details » redevient une ligne de texte discrete avec un vrai chevron —
   la ligature d'avant n'etait pas dans le sous-ensemble de la fonte et se
   rendait en lettres. */
.file-postes .commande .agir { display: flex; width: 100%; justify-content: stretch; }
.file-postes .commande .agir form { display: flex; flex: 1 1 100%; width: 100%; }
.file-postes .commande .agir .btn { flex: 1 1 100%; width: 100%; }
.file-postes .plier > summary { background: transparent; padding: 2px 0; min-height: 0; border-radius: 0; }
.file-postes .plier > summary::after { content: "\25BE"; font-family: var(--font); font-size: 11px; }

/* Une photo se depose sur la carte : le cadre s attend, puis remercie. */
.carte-produit.depose { outline: 2px dashed var(--primary); outline-offset: -2px; }
.carte-produit.depose .carte-produit__media::after {
    content: "Deposer la photo";
    position: absolute; inset: 0;
    display: grid; place-items: center;
    background: color-mix(in srgb, var(--primary) 70%, transparent);
    color: #fff; font-weight: 700; font-size: 13px;
}
.carte-produit.envoi .carte-produit__media { opacity: .5; }

/* ── La tuile de commande, uniforme, photo ou pas ─────────────────────────
   Mesure sur la capture : la tuile avec photo faisait 160 px, celle aux
   initiales 100 — un <button> ne s etire pas dans une grille, il garde sa
   largeur de contenu, et la photo en avait plus. Chaque tuile prend donc sa
   colonne, et la vignette occupe toute la largeur en 4/3 : les rangees
   restent alignees, et une photo devient une vraie image lumineuse dans une
   salle noire, pas un timbre de 44 px. Trois colonnes a 360 px. */
.produits { grid-template-columns: repeat(auto-fill, minmax(min(100px, 100%), 1fr)); gap: 9px; }
.produit { width: 100%; justify-self: stretch; min-width: 0; padding: 8px; gap: 6px; min-height: 0; }
.produit .vignette { width: 100%; aspect-ratio: 4 / 3; height: auto; }
.produit .vignette .lettre { font-size: 20px; }
.produit .nom { font-size: 12.5px; line-height: 1.25; overflow-wrap: anywhere; }
.produit .prix { font-size: 12.5px; }
/* Meme hauteur sur la rangee : un nom sur deux lignes ne fait pas une tuile
   plus haute que ses voisines. */
.produit { height: 100%; align-self: stretch; justify-content: flex-start; }
