/* src/ui/styles/tokens.css */
:root {
  color-scheme: light;
  /* Thème « Noir & blanc, boutons fluo » (14/10/2026, 2e itération, direction « Mono strict » retenue) :
     noir, blanc et gris purs pour TOUT ce qui n'est pas un appel à l'action, données comprises (états, paiement, ménage,
     maisons = luminosité, contour, motif, forme). Les SEULES couleurs de l'interface sont les six fluos des boutons
     (--cta-*), toujours avec du texte noir (--cta-ink) et un contour noir de 1 px qui ne disparaît sur aucun état actif.
     Mode clair seul (décision de Baptiste, 30/09/2026) : aucun jeu de couleurs sombre.
     Toutes les couleurs des écrans passent par ces variables : un seul endroit à ajuster.
     Les jetons testés (test/nfr-accessibility) restent des hexadécimaux littéraux #rrggbb : ni var(), ni rgba(), ni color-mix(). */

  /* ── Palette fluo des appels à l'action : UNE couleur par famille d'action, texte noir dessus ──
        create  = lime    : créer, enregistrer, confirmer (primaire par défaut), « + Réservation »
        confirm = cyan    : faire avancer un séjour (check-in, check-out)
        money   = jaune   : argent (encaisser, rembourser, facture, solde)
        done    = vert    : terminé (Tâche traitée, Fait)
        remind  = orange  : à relancer (Rappeler)
        danger  = rouge vif : annuler une réservation, supprimer, refuser
        Les boutons secondaires (Annuler, Aujourd'hui, Gérer…) restent blancs : aucun fluo.
        Un fluo sur blanc ne fait pas 3:1 (lime 1,2 ; jaune 1,2 ; cyan 1,5 ; vert 1,4) : c'est le contour noir de 1 px qui porte la
        limite du bouton. Ne JAMAIS le retirer d'un bouton fluo. */
  --cta-ink: #0a0a0a;             /* texte, icône et contour de tout bouton fluo */
  --cta-create: #c8ff00;
  --cta-confirm: #00e5ff;
  --cta-money: #fff200;
  --cta-done: #39ff14;
  --cta-remind: #ff6a00;
  --cta-danger: #ff2a2a;         /* rouge vif (demande de Baptiste du 14/10) : noir dessus 5,3:1, 3,7:1 sur blanc */
  /* États communs : au SURVOL le bouton s'inverse (fond noir, texte et icône de SA couleur fluo) ; à l'APPUI le fond passe au
     gris #262626, le bouton glisse de 1 px et l'ombre se réduit. Chaque fluo sur ces deux fonds fait ≥ 4,7:1. */
  --cta-hover-bg: #0a0a0a;
  --cta-press-bg: #171717;         /* appui : assez sombre pour le rouge vif (4,8:1), les autres fluos ≥ 6:1 */
  --cta-shadow: 2px 2px 0 #0a0a0a;          /* ombre dure des boutons fluo (2 px vers le bas et la droite, sans flou) */
  --cta-shadow-press: 1px 1px 0 #0a0a0a;

  /* ── Accent (primaire : onglet actif, aujourd'hui, ligne « maintenant », interrupteurs, sélection, lien de menu actif) : NOIR ── */
  --accent: #0a0a0a;          /* blanc dessus 19,8:1 */
  --accent-dark: #000000;     /* texte d'accent sur blanc ou sur fond doux, survol */
  --accent-deep: #000000;     /* état appuyé */
  --accent-bg: #e8e8e8;       /* fond doux : avatar, sélection */
  --accent-line: #a3a3a3;     /* bordure d'un élément survolé */
  --on-accent: #ffffff;       /* texte sur noir (pastille, aujourd'hui, danger plein, surréservation) */
  --accent-2: #404040;        /* ex-orange des données (ménage « sale ») : un gris foncé, jamais un bouton */
  --accent-2-bg: #ececec;

  /* ── Admin : noms historiques conservés. --green / --green-dark / --sage portent désormais l'ACCENT NOIR.
        Ils ne sont PAS les fluos : ce sont les « sélectionné / actif / coché » (puce de filtre active, étape courante, case
        cochée, interrupteur, barre d'onglet, curseur), texte blanc dessus. Les boutons d'action passent par --cta-*. ── */
  --ink: #0a0a0a;             /* titres, chiffres clés */
  --text: #1a1a1a;            /* texte courant */
  --text-2: #404040;          /* texte secondaire fort (boutons fantômes) */
  --muted: #525252;           /* texte secondaire */
  --green: #0a0a0a;           /* = --accent (primaire historique) */
  --green-dark: #000000;      /* = --accent-dark */
  --sage: #e8e8e8;            /* = --accent-bg : FOND clair d'accent (jamais un aplat d'action) */
  --cream: #f4f4f4;           /* fond de page : gris neutre pur */
  --paper: #ffffff;           /* cartes, menu, barre du haut, grille du planning */
  --line: #d4d4d4;            /* filets et bordures de cartes */
  --line-strong: #0a0a0a;     /* survol des cartes cliquables, traits de structure */
  --line-soft: #e8e8e8;       /* séparateurs de lignes de tableau */
  --warning: #262626;
  --warning-bg: #e4e4e4;

  /* Encres de ménage de main (anneau du point .hk-dot et texte des pastilles) : points vifs rouge (sale) / bleu électrique (inspectée) /
     vert fluo (propre) à anneau noir, encres foncées pour les pastilles à texte. */
  --hk-dirty-ink: #991b1b;      /* encres des pastilles à texte (Sale / Propre / Inspectée) : foncées, lisibles sur fond pâle */
  --hk-clean-ink: #166534;
  --hk-inspected-ink: #1e40af;
  --hk-dirty-bg: #fee2e2;       --hk-clean-bg: #dcfce7;       --hk-inspected-bg: #dbeafe;
  /* Blocage d'une chambre (D-138, jetons de main) : en noir et blanc, un gris plein (jamais l'orange, réservé aux boutons « relancer »).
     Fond PLEIN (la règle du planning le mélange avec color-mix) ; encre noire 11:1, filet gris très foncé. */
  --st-block-works: #cfcfcf;   --st-block-works-ink: #0a0a0a; --st-block-works-edge: #404040;

  /* ── Surfaces et textes dérivés ── */
  --sidebar: #ffffff;
  --sidebar-line: #0a0a0a;    /* filet noir de 1 px entre le menu et la page : la signature « noir et blanc » */
  --nav-hover: #ececec;
  --nav-active: #0a0a0a;      /* lien actif : plein noir, texte et icône blancs */
  --nav-ink: #262626;         /* libellé de lien du menu au repos */
  --nav-ink-active: #ffffff;  /* lien actif : texte et icône (blanc sur noir 19,8:1) */
  --nav-icon: #404040;        /* icônes du menu au repos */
  --nav-label: #5c5c5c;       /* libellés de groupe (L'EXPLOITATION…) et eyebrow */
  --brand: #0a0a0a;           /* marque Guarana */
  --topbar: #ffffff;
  --search-bg: #f0f0f0;       /* champ de recherche au repos */
  --field: #ffffff;
  --field-line: #737373;      /* bordure de champ : 4,7:1 sur blanc (WCAG 1.4.11) */
  --switch-off: #8a8a8a;      /* piste d'un interrupteur éteint : 3,5:1 sur blanc, un état doit se voir */
  --field-hover: #0a0a0a;     /* bordure de champ / bouton secondaire au survol */
  --soft: #f6f6f6;            /* tuiles de chiffres, en-têtes de tableau, lignes de maison */
  --soft-2: #ececec;          /* piste du segmenté, ligne de synthèse, bouton désactivé */
  --row-hover: #f2f2f2;       /* survol de ligne */
  --subtle: #5c5c5c;          /* repères discrets */
  --handle: #8a8a8a;          /* poignées de redimensionnement : 3,45:1 sur blanc, 3,19:1 sur --soft (WCAG 1.4.11) ; contour des boutons inactifs */
  --focus: #0a0a0a;           /* contour de focus : 3 px noir, décalé de 2 px (visible sur blanc, gris et fluo) */
  --focus-ring: rgba(10, 10, 10, 0.18);   /* halo 3 px des champs en focus (décor : hors test de contraste) */
  --overlay: rgba(10, 10, 10, 0.55);
  --shadow-sm: 0 1px 0 rgba(10, 10, 10, 0.06);
  --shadow-md: 0 6px 16px -6px rgba(10, 10, 10, 0.2), 0 1px 0 rgba(10, 10, 10, 0.08);
  --shadow-lg: 0 24px 48px -16px rgba(10, 10, 10, 0.36), 0 2px 6px rgba(10, 10, 10, 0.1);
  --toast-bg: #0a0a0a;
  --toast-ink: #ffffff;
  --toast-ok: #c8ff00;        /* l'action « Annuler » d'un toast est un appel à l'action : lime sur noir (16,7:1) */

  /* ── Tons sémantiques (texte / fond) : le texte est toujours noir, la gravité monte avec le gris du fond
        (ok < info < warn < danger) ; la pastille danger est en plus NOIRE PLEINE à texte blanc (règle dans components.css) ── */
  --ok: #0a0a0a;        --ok-bg: #f0f0f0;
  --info: #0a0a0a;      --info-bg: #e4e4e4;
  --warn: #0a0a0a;      --warn-bg: #d4d4d4;
  --danger: #0a0a0a;    --danger-bg: #bcbcbc;
  --violet: #0a0a0a;    --violet-bg: #ffffff;   /* « Nouveau » / « Démo » : marqueur, jamais une couleur */
  --neutral: #404040;   --neutral-bg: #ececec;

  /* ── Touches de couleur (proposition v2 du 15/10) : jetons de SIGNAL, posés seulement sur les badges de paiement, les badges de
        statut là où le statut est l'information de la ligne, le montant du solde, le trait de paiement sous les barres du planning,
        les points de ménage et les cartes « problème » des écrans Paiements et Ménage. Tout le reste reste gris ; les boutons restent fluo. ── */
  --sig-ok: #166534;     --sig-ok-bg: #dcfce7;     --sig-ok-edge: #15803d;     /* réglé, arrivé (check-in), terminé */
  --sig-due: #991b1b;    --sig-due-bg: #fee2e2;    --sig-due-edge: #b91c1c;    /* reste à payer, impayé, incident, annulée, non-présentation */
  --sig-wait: #92400e;   --sig-wait-bg: #fef3c7;   --sig-wait-edge: #b45309;   /* lien envoyé, à rembourser, préréservation */
  --sig-info: #1e40af;   --sig-info-bg: #dbeafe;   --sig-info-edge: #1d4ed8;   /* confirmée, carte enregistrée */

  /* ── Planning : grille et aujourd'hui ── */
  /* Aujourd'hui en bleu pastel (demande de Baptiste du 17/10/2026, à la place du gris ; rose et lavande essayés puis écartés) :
     seule teinte du planning, distincte du cyan des boutons de confirmation. Blanc sur --pl-today-ink 10,4:1 ;
     --pl-today-ink sur --pl-today-bg 8,5:1. */
  --pl-today-bg: #dceafb;      /* en-tête de la colonne « aujourd'hui » (et colonne du jour de la carte Occupation) */
  --pl-today-col: rgb(37 99 235 / 7%); /* voile translucide de la colonne du jour (≈ #f0f4fe sur blanc) : les filets de la grille restent visibles */
  --pl-today-ink: #1e3a8a;     /* pastille du numéro, jour de la semaine et trait de l'heure */
  --pl-grid: #e4e4e4;          /* filets verticaux de la grille */

  /* ── États de séjour (barres du planning) : luminosité + contour + motif, jamais la couleur ── */
  --st-confirmed: #e0e0e0;     --st-confirmed-ink: #0a0a0a;  --st-confirmed-edge: #404040;   /* gris clair, filet gris très foncé */
  --st-inhouse: #ffffff;       --st-inhouse-ink: #0a0a0a;    --st-inhouse-edge: #0a0a0a;     /* blanc, contour noir, texte gras : check-in fait (15/10, à la place du noir plein, trop présent) */
  --st-checkedout: #f5f5f5;    --st-checkedout-ink: #5c5c5c; --st-checkedout-edge: #c4c4c4;  /* presque blanc, estompé */
  --st-pending: #ffffff;       --st-pending-ink: #0a0a0a;    --st-pending-edge: #4d4d4d;     /* blanc hachuré (135°) */
  --st-pending-stripe: #b8b8b8;                              /* trait de hachure de la préréservation (noir dessus : 10,4:1) */
  --st-noshow: #ffffff;        --st-noshow-ink: #0a0a0a;     --st-noshow-edge: #0a0a0a;      /* blanc, contour noir de 1,5 px (--danger) */
  --st-unassigned: #aaaaaa;    --st-unassigned-ink: #0a0a0a; --st-unassigned-edge: #0a0a0a;  /* gris soutenu + filet noir + filet de maison */
  --st-closed: repeating-linear-gradient(45deg, #cfcfcf 0 1.5px, #f6f6f6 1.5px 5px);          /* fines hachures à 45° (la préréservation est à 135°) */
  --st-closed-ink: #404040;

  /* ── Paiement (filet de 3 px sous la barre, pastille) : le filet est dessiné par un motif dans la couleur du sens (voir planning.css) : plein = payé,
        tirets = dû, traits obliques = incident, gris plein = carte. Ces gris servent aux usages en couleur pleine. ── */
  --pay-paid: #15803d;         /* payé : plein VERT (touche de couleur, proposition v2 du 15/10) */
  --pay-due: #b91c1c;          /* dû : tirets ROUGES */
  --pay-incident: #c2410c;     /* incident : traits obliques rouge-orangé */
  --pay-card: #8c8c8c;         /* carte enregistrée : gris plein (rien à faire) */
  /* Variantes claires des trois couleurs pour le trait posé sur une barre NOIRE (séjour en cours, surréservation) : ≥ 3:1 sur #0a0a0a. */
  --pay-paid-on-dark: #4ade80; --pay-due-on-dark: #f87171; --pay-incident-on-dark: #fb923c;
  /* Filets de priorité des tâches (pointillé « prioritaire », plein « urgent ») : ils restent gris / noir, séparés du paiement. */
  --prio-high: #5c5c5c;        --prio-urgent: #0a0a0a;

  /* ── Ménage (pastilles de 10 px et de 7 px) : sale = rouge vif, propre = vert fluo, inspectée = bleu électrique à
        point central noir, hors service = hachuré. Le cercle noir de 1,5 px est posé par la règle (box-shadow inset), pas par
        le jeton. Ces jetons sont des FONDS (propriété background) : valeurs de dégradé permises. ── */
  --hk-dirty: #ff2a2a;                                                     /* sale : rouge vif */
  --hk-clean: #39ff14;                                                     /* propre : vert fluo */
  --hk-inspected: radial-gradient(circle, #0a0a0a 0 1.5px, #0a5cff 1.9px); /* inspectée : bleu électrique à point central noir */
  --hk-oos: repeating-linear-gradient(135deg, #0a0a0a 0 1.6px, #ffffff 1.6px 3.4px); /* hors service : hachures, inchangé */

  /* ── Couleurs des maisons : cinq gris sombres (texte blanc dessus ≥ 4,5:1) + une FORME par maison posée par les règles
        `.dot[data-house*="house-xx"]` / `.dot[style*="--house-xx"]` (disque, carré, losange, triangle, anneau).
        Ces jetons et ces formes ne valent que si colorVar vaut `var(--house-xx)` (prototype / jeu de données fictif).
        Sur les données réelles, la couleur arrive en hexadécimal depuis la base : les pastilles restent alors des disques
        de teinte (exception assumée, cf. les teintes désaturées) et la distinction passe par la teinte et par le nom de
        la maison, toujours écrit à côté. ── */
  --house-cp: #0a0a0a;   /* Chambres Panda : disque */
  --house-mb: #2e2e2e;   /* Maison Beauval : carré */
  --house-mc: #4a4a4a;   /* Maison du Châtelain : losange */
  --house-co: #626262;   /* La Collégiale : triangle */
  --house-mf: #757575;   /* Maison des Fleurs : anneau */

  /* ── Canaux ── */
  --ch-booking: #0a0a0a;
  --ch-direct: #4a4a4a;
  --ch-whatsapp: #262626;
  /* Pastilles rondes des canaux (demande de Baptiste du 19/10/2026, D-186) : seule exception aux signaux sans couleur
     (D-173, charte 21 §6) — des couleurs d'identité, jamais de gravité : bleu Booking.com, vert WhatsApp, noir e-mail,
     gris SMS, blanc cerclé note interne ; glyphe blanc, point du « B. » bleu clair comme dans le logo. */
  --ch-booking-bg: #003b95;
  --ch-booking-dot: #00bafc;
  --ch-whatsapp-bg: #1da851;
  --ch-email-bg: #0a0a0a;
  --ch-sms-bg: #4a4a4a;
  --ch-note-bg: #ffffff;
  --ch-on: #ffffff;

  /* ── Mise en page (valeurs inchangées) ; rayons resserrés pour un trait plus graphique ── */
  --sidebar-w: 246px;
  --topbar-h: 64px;
  /* Hauteur offerte aux vues pleine hauteur (planning, messagerie) : la fenêtre moins la barre du haut de la page
     autonome. Dans l'admin, #pms-host la redéfinit avec sa propre barre et ses marges (admin/public/admin.css). */
  --pms-view-h: calc(100dvh - var(--topbar-h));
  --radius-sm: 4px;
  --radius: 6px;
  --radius-lg: 8px;
  --radius-bar: 5px;           /* barres du planning */

  /* ── Typographie : Bricolage Grotesque (marque, titres, menu, boutons, en-têtes de tableau, chiffres clés) + Instrument Sans (corps) ── */
  --font-display: "Bricolage Grotesque", "Instrument Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  --font: "Instrument Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  --mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}

/* src/ui/styles/base.css */
/* Base typographique : Bricolage Grotesque (titres, marque, menu, boutons, chiffres clés) et Instrument Sans (corps), polices variables auto-hébergées (OFL), servies sous /pms/fonts/ (CSP font-src 'self'). Noir et blanc : les couleurs viennent de tokens.css. */
/* Les trois *-override donnent aux deux familles la boîte de contenu et la ligne de base d'Inter (96,875 % / 24,121 % / 0 %) : aucune barre, bouton ou ligne ne bouge verticalement, et le basculement du font-display: swap ne fait sauter aucune ligne. */
@font-face { font-family: "Bricolage Grotesque"; font-style: normal; font-weight: 200 800; font-display: swap; src: url(/pms/fonts/bricolage-grotesque-latin-ext-wght-normal.woff2) format('woff2'); unicode-range: U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF; ascent-override: 96.875%; descent-override: 24.121%; line-gap-override: 0%; }
@font-face { font-family: "Bricolage Grotesque"; font-style: normal; font-weight: 200 800; font-display: swap; src: url(/pms/fonts/bricolage-grotesque-latin-wght-normal.woff2) format('woff2'); unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD; ascent-override: 96.875%; descent-override: 24.121%; line-gap-override: 0%; }
@font-face { font-family: "Instrument Sans"; font-style: normal; font-weight: 400 700; font-display: swap; src: url(/pms/fonts/instrument-sans-latin-ext-wght-normal.woff2) format('woff2'); unicode-range: U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF; ascent-override: 96.875%; descent-override: 24.121%; line-gap-override: 0%; }
@font-face { font-family: "Instrument Sans"; font-style: normal; font-weight: 400 700; font-display: swap; src: url(/pms/fonts/instrument-sans-latin-wght-normal.woff2) format('woff2'); unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD; ascent-override: 96.875%; descent-override: 24.121%; line-gap-override: 0%; }
*, *::before, *::after { box-sizing: border-box; }
html, body { height: 100%; }
body {
  margin: 0;
  font-family: var(--font);
  font-size: 14px;
  line-height: 1.5;
  font-weight: 400;
  letter-spacing: 0;
  color: var(--text);
  background: var(--cream);
  font-synthesis: none;
  -webkit-font-smoothing: antialiased;
}
button, input, select, textarea { font: inherit; color: inherit; }
button { cursor: pointer; border: 0; background: none; -webkit-tap-highlight-color: transparent; touch-action: manipulation; }
button:disabled { cursor: not-allowed; opacity: 0.55; }
a { color: inherit; text-decoration: none; }
h1, h2, h3, h4, p { margin: 0; }
/* Titres en Bricolage Grotesque, plus lourde et plus serrée : c'est elle qui donne l'identité « enseigne » au produit (le corps reste en Instrument Sans). */
h1, h2, h3, h4 { font-family: var(--font-display); }
h1 { font-size: 28px; line-height: 1.2; font-weight: 700; letter-spacing: -0.9px; color: var(--ink); text-wrap: balance; }
h2 { font-size: 18px; line-height: 1.3; font-weight: 700; letter-spacing: -0.3px; color: var(--ink); text-wrap: balance; }
h3 { font-size: 14px; line-height: 1.35; font-weight: 700; letter-spacing: -0.1px; color: var(--ink); }
svg { display: block; flex-shrink: 0; }
:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; border-radius: 4px; }
[hidden] { display: none !important; }
.num { font-variant-numeric: tabular-nums; }
.muted { color: var(--muted); }
.small { font-size: 12px; }
.tiny { font-size: 11px; }
/* Interligne figé à l'ancienne valeur calculée (10 px × 1,5) : la taille monte, la hauteur de ligne ne bouge pas. */
.eyebrow { font-family: var(--font-display); font-size: 11px; line-height: 15px; letter-spacing: 1.1px; text-transform: uppercase; color: var(--nav-label); font-weight: 700; }
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }
.mono { font-family: var(--mono); font-size: 12px; }
.row { display: flex; align-items: center; gap: 8px; }
.row-wrap { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.stack { display: flex; flex-direction: column; gap: 8px; }
.spacer { flex: 1; }
.nowrap { white-space: nowrap; }
.truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 0.01ms !important; transition: none !important; scroll-behavior: auto !important; }
}

/* src/ui/login/login.css */
/* Page de connexion du back-office (docs/pms/01 §5.3 ; 17 NFR-048, NFR-049 ; D-127). Ajoutée à la suite des jetons et de la base
   du PMS (styles/tokens.css, styles/base.css) dans dist/ui/connexion.css (scripts/build-ui.mjs) : ces règles ne sont jamais
   dans la feuille du back-office. Mode clair seul. Mobile d'abord, lisible à 360 px : champs de 16 px (pas de zoom d'iOS à la
   saisie), cibles tactiles d'au moins 44 px, texte à 4,5:1 au moins et bords des champs à 3:1 au moins. Logo Guarana servi localement ; aucune police distante. Ni style en ligne ni ressource externe (politique de sécurité de l'admin).
   Thème « noir et blanc, boutons fluo » (D-172) : la page n'est composée que de tokens.css + base.css + cette feuille (pas de
   components.css), donc les boutons, liens et champs sont redéfinis ici avec les mêmes jetons que le back-office : le bouton
   d'action est lime (--cta-create), texte et contour noirs, ombre dure, inversé au survol ; les liens sont soulignés en noir
   avec le surligneur lime ; les champs sont blancs à contour --field-line ; titres et boutons en Bricolage Grotesque
   (--font-display), corps en Instrument Sans. Aucune autre couleur que les fluos des boutons. */

.login {
  --login-gap: 16px;
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: max(20px, env(safe-area-inset-top)) max(16px, env(safe-area-inset-right)) max(24px, env(safe-area-inset-bottom)) max(16px, env(safe-area-inset-left));
}
@media (min-height: 640px) and (min-width: 480px) {
  .login { padding-top: clamp(32px, 11vh, 120px); }
}

.login-card {
  width: 100%;
  max-width: 420px;
  display: flex;
  flex-direction: column;
  gap: var(--login-gap);
  padding: 28px 24px 24px;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
}
@media (max-width: 400px) {
  .login-card { padding: 22px 16px 18px; }
}

/* ─── Marque (même tracé que la barre latérale du back-office) ─────────────── */
.login-brand { display: flex; flex-direction: column; align-items: flex-start; gap: 5px; color: var(--brand); }
.login-logo { position: relative; display: block; width: 210px; max-width: 100%; aspect-ratio: 524 / 140; overflow: hidden; flex: none; }
.login-logo img { position: absolute; width: 293.13%; max-width: none; height: auto; left: -16.6%; top: -571.43%; mix-blend-mode: multiply; filter: brightness(1.08); }

/* ─── Titre et textes ──────────────────────────────────────────────────────── */
.login-title { font-family: var(--font-display); font-size: 26px; font-weight: 700; letter-spacing: -0.7px; color: var(--ink); overflow-wrap: anywhere; }
@media (max-width: 380px) {
  .login-title { font-size: 24px; }
}
.login-lead { font-size: 15px; line-height: 1.5; color: var(--text); overflow-wrap: anywhere; }
.login-lead strong, .login-account strong { color: var(--ink); font-weight: 600; overflow-wrap: anywhere; }
.login-account { font-size: 14px; color: var(--text); overflow-wrap: anywhere; }
.login-help { font-size: 13px; line-height: 1.4; color: var(--neutral); }
/* Encart d'information : fond gris, contour de 1 px par ombre interne (pas de bordure en plus), texte noir. */
.login-note { padding: 10px 12px; border-radius: var(--radius); background: var(--info-bg); box-shadow: inset 0 0 0 1px var(--field-line); color: var(--info); font-size: 14px; line-height: 1.45; }
/* Éléments pris au clavier par programme (titre, textes de résultat) : lus par le lecteur d'écran, sans cadre. */
.login [tabindex="-1"]:focus, .login [tabindex="-1"]:focus-visible { outline: none; }

/* ─── Étapes et formulaires ────────────────────────────────────────────────── */
.login-step, .login-form, .login-panel { display: flex; flex-direction: column; gap: var(--login-gap); min-width: 0; }
.login-field { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.login-label { font-family: var(--font-display); font-size: 14px; font-weight: 700; color: var(--ink); }

.login-input {
  width: 100%;
  min-height: 48px;
  padding: 10px 14px;
  border: 1px solid var(--field-line);
  border-radius: var(--radius);
  background: var(--field);
  color: var(--text);
  font-size: 16px;
  line-height: 1.3;
  transition: border-color 0.14s, box-shadow 0.14s;
}
/* Contour de champ : gris 4,7:1 au repos, noir au survol, noir et halo de 3 px au focus (comme .input des composants). */
.login-input:hover { border-color: var(--field-hover); }
.login-input:focus { border-color: var(--focus); box-shadow: 0 0 0 3px var(--focus-ring); }
/* Champ refusé : contour noir et barre interne de 3 px à gauche (la forme porte le sens, pas la couleur). */
.login-input[aria-invalid="true"] { border-color: var(--danger); box-shadow: inset 3px 0 0 var(--danger); }
.login-input[aria-invalid="true"]:focus { box-shadow: inset 3px 0 0 var(--danger), 0 0 0 3px var(--focus-ring); }
.login-code {
  padding-left: calc(14px + 0.35em);
  font-family: var(--mono);
  font-size: 26px;
  letter-spacing: 0.35em;
  text-align: center;
  font-variant-numeric: tabular-nums;
}

/* Mot de passe : bouton « Afficher / Masquer » dans le champ, cible de 44 px. */
.login-password { position: relative; }
.login-password .login-input { padding-right: 104px; }
.login-reveal {
  position: absolute;
  top: 2px;
  right: 2px;
  bottom: 2px;
  min-width: 44px;
  padding: 0 14px;
  border-radius: calc(var(--radius) - 2px);
  color: var(--ink);
  font-family: var(--font-display);
  font-size: 14px;
  font-weight: 600;
  /* Lien d'action : souligné en noir, surligneur lime sur le bas du texte (bande de 1,25 em centrée, limitée au texte). */
  text-decoration: underline;
  text-decoration-thickness: 1.5px;
  text-decoration-color: var(--ink);
  text-underline-offset: 3px;
  background: linear-gradient(transparent 58%, var(--cta-create) 58%) 50% 50% / 100% 1.25em no-repeat;
  background-origin: content-box;
  background-clip: content-box;
  transition: color 0.12s, background 0.12s;
}
.login-reveal:hover { background: var(--cta-create); background-origin: content-box; background-clip: content-box; }

.login-check {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  min-height: 44px;
  padding: 8px 0;
  font-size: 15px;
  line-height: 1.4;
  color: var(--text);
  cursor: pointer;
}
.login-check input { flex: none; width: 22px; height: 22px; margin: 0; accent-color: var(--accent); cursor: pointer; }

/* ─── Boutons ──────────────────────────────────────────────────────────────── */
/* Comme .btn des composants : Bricolage Grotesque 650, contour de 1 px. Les couleurs viennent de la variante. */
.login-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  width: 100%;
  min-height: 48px;
  padding: 10px 18px;
  border: 1px solid transparent;
  border-radius: var(--radius);
  font-family: var(--font-display);
  font-size: 16px;
  font-weight: 650;
  line-height: 1.2;
  transition: background 0.12s, border-color 0.12s, box-shadow 0.12s, color 0.12s;
}
/* Primaire = « créer / enregistrer / confirmer » : lime, texte et contour noirs (le contour porte la limite : le lime ne fait que
   1,2:1 sur blanc), ombre dure. Survol : le bouton s'inverse (fond noir, texte lime). Appui : fond gris foncé, ombre réduite. */
.login-btn-primary { background: var(--cta-create); color: var(--cta-ink); border-color: var(--cta-ink); box-shadow: var(--cta-shadow); }
.login-btn-primary:hover:not(:disabled) { background: var(--cta-hover-bg); color: var(--cta-create); }
.login-btn-primary:active:not(:disabled) { background: var(--cta-press-bg); color: var(--cta-create); box-shadow: var(--cta-shadow-press); }
/* Secondaire : blanc à contour de champ, sans fluo ; au survol il passe au noir à texte blanc comme .btn-secondary. */
.login-btn-secondary { background: var(--field); color: var(--ink); border-color: var(--field-line); }
.login-btn-secondary:hover:not(:disabled) { background: var(--cta-hover-bg); color: var(--on-accent); border-color: var(--cta-ink); }
.login-btn-secondary:active:not(:disabled) { background: var(--cta-press-bg); color: var(--on-accent); border-color: var(--cta-ink); }
/* Désactivé (étape « codes de secours » avant la case cochée) : gris plat, contour gris, ni ombre ni fluo : on voit qu'il est éteint
   par la forme (plus d'ombre dure) et non par la seule teinte. Le texte reste lisible (6,6:1). */
.login-btn-primary:disabled, .login-btn-secondary:disabled { background: var(--soft-2); border-color: var(--handle); color: var(--muted); box-shadow: none; opacity: 1; }
/* Requête en cours : bouton désactivé mais pas estompé ; il garde l'état « appuyé » (fond gris foncé, texte et témoin tournant lime). */
.login-btn[aria-busy="true"] { opacity: 1; cursor: progress; }
.login-btn-primary[aria-busy="true"] { background: var(--cta-press-bg); border-color: var(--cta-ink); color: var(--cta-create); box-shadow: var(--cta-shadow-press); }
.login-btn-secondary[aria-busy="true"] { background: var(--cta-press-bg); border-color: var(--cta-ink); color: var(--on-accent); }
.login-btn[aria-busy="true"]::before { content: ""; }
.login-btn[aria-busy="true"]::before, .login-spinner {
  flex: none;
  width: 16px;
  height: 16px;
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  animation: login-spin 0.8s linear infinite;
}
.login-spinner { display: inline-block; vertical-align: -3px; margin-right: 8px; color: var(--ink); }
@keyframes login-spin { to { transform: rotate(360deg); } }

.login-link {
  align-self: center;
  min-height: 44px;
  padding: 10px 12px;
  border-radius: var(--radius-sm);
  color: var(--ink);
  font-family: var(--font-display);
  font-size: 15px;
  font-weight: 600;
  /* Lien d'action (comme .link-btn) : souligné en noir de 1,5 px, surligneur lime sur le bas du texte (bande de 1,25 em limitée
     au texte, sans toucher à la zone de 44 px) ; au survol, aplat lime. */
  text-decoration: underline;
  text-decoration-thickness: 1.5px;
  text-decoration-color: var(--ink);
  text-underline-offset: 3px;
  background: linear-gradient(transparent 58%, var(--cta-create) 58%) 50% 50% / 100% 1.25em no-repeat;
  background-origin: content-box;
  background-clip: content-box;
  white-space: nowrap;
  transition: color 0.12s, background 0.12s;
}
.login-link:hover { background: var(--cta-create); background-origin: content-box; background-clip: content-box; }
/* Lien-bouton dont le texte peut être long (« Utiliser le code de l'application ») : il passe à la ligne plutôt que de déborder. */
.login-link-wrap { white-space: normal; text-align: center; }
/* Bouton d'action secondaire dans un bloc (copier la clé, copier les codes) : à la largeur de son texte. */
.login-btn-compact { width: auto; align-self: flex-start; min-height: 44px; padding: 8px 16px; font-size: 15px; }
/* Pendant une requête, le reste de l'étape ne répond plus (les gestionnaires l'ignorent aussi). */
.login-step[aria-busy="true"] .login-link, .login-step[aria-busy="true"] .login-btn:not([aria-busy="true"]) { opacity: 0.6; pointer-events: none; }

/* ─── Application d'authentification : étapes, QR code, clé ────────────────── */
.login-enroll {
  display: flex;
  flex-direction: column;
  gap: 14px;
  min-width: 0;
  padding: 16px 14px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--soft);
}
.login-subtitle { font-family: var(--font-display); font-size: 17px; font-weight: 700; letter-spacing: -0.2px; overflow-wrap: anywhere; }
.login-steps { margin: 0; padding-left: 22px; display: flex; flex-direction: column; gap: 8px; font-size: 14px; line-height: 1.5; color: var(--text); }
.login-steps li { padding-left: 4px; overflow-wrap: anywhere; }
.login-steps li::marker { color: var(--ink); font-weight: 600; }

/* QR code : toujours noir sur blanc (même marge blanche que la norme, 4 modules, dans le tracé), bordure discrète (le blanc est une
   exception assumée au thème : un QR code doit rester noir sur blanc pour être lu). */
.login-qr {
  align-self: center;
  width: 216px;
  max-width: 100%;
  padding: 8px;
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--radius);
}
.login-qr svg { display: block; width: 100%; height: auto; aspect-ratio: 1 / 1; }

/* Clé à saisir à la main : chasse fixe, groupes de 4 qui passent à la ligne entre deux groupes, sélection d'un clic. */
.login-keybox { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.login-key {
  display: block;
  padding: 10px 12px;
  border: 1px solid var(--field-line);
  border-radius: var(--radius);
  background: var(--paper);
  color: var(--ink);
  font-family: var(--mono);
  font-size: 16px;
  font-weight: 600;
  line-height: 1.6;
  letter-spacing: 0.06em;
  text-align: center;
  overflow-wrap: anywhere;
  user-select: all;
  -webkit-user-select: all;
}
.login-key:empty { display: none; }
/* Zone d'état de la copie, vide : gardée dans l'arbre d'accessibilité (l'annonce est lue dès que le texte arrive) mais sans espace. */
.login-panel > .login-help:empty { margin-top: calc(var(--login-gap) * -1); height: 0; overflow: hidden; }
.login-keybox > .login-help:empty { margin-top: -8px; height: 0; overflow: hidden; }

/* ─── Codes de secours : deux colonnes quand la place le permet, une sous 400 px ────────────────────────────────── */
.login-codes {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 6px 14px;
  margin: 0;
  padding: 14px;
  list-style: none;
  border: 1px solid var(--field-line);
  border-radius: var(--radius);
  background: var(--soft);
}
.login-codes li {
  min-width: 0;
  font-family: var(--mono);
  font-size: 16px;
  font-weight: 600;
  line-height: 1.7;
  letter-spacing: 0.04em;
  color: var(--ink);
  overflow-wrap: anywhere;
}
@media (max-width: 400px) {
  .login-codes { grid-template-columns: minmax(0, 1fr); }
  .login-enroll { padding: 14px 12px; }
}

/* ─── Erreurs : sous le formulaire, jamais par la seule couleur (bord épais et texte explicite) ─────────────────── */
.login-message {
  padding: 10px 12px;
  border-left: 4px solid var(--danger);
  border-radius: var(--radius-sm);
  /* Gris soutenu (gravité = luminosité du fond), contour noir de 1 px par ombre interne, barre noire à gauche : jamais la couleur seule. */
  background: var(--danger-bg);
  box-shadow: inset 0 0 0 1px var(--ink);
  color: var(--danger);
  font-size: 14px;
  font-weight: 600;
  line-height: 1.45;
  overflow-wrap: anywhere;
}
/* Vide, la zone reste dans l'arbre d'accessibilité (une annonce y est lue dès que le texte arrive) mais ne prend aucune place. */
.login-message:empty { margin-top: calc(var(--login-gap) * -1); padding: 0; border: 0; height: 0; overflow: hidden; background: none; box-shadow: none; }

@media (prefers-reduced-motion: reduce) {
  .login-btn[aria-busy="true"]::before, .login-spinner { animation: none; }
}

@media (forced-colors: active) {
  .login-btn { border-color: ButtonText; }
  .login-input[aria-invalid="true"] { border-width: 3px; }
}
