/* =============================================================================
   EuroMillions Stats — feuille de style unique.

   Implémente le système de design de DESIGN.md. Celui-ci décrit une cible
   Tailwind v4 (`@theme`, classes utilitaires) ; le projet interdit tout build
   et tout CDN, la grammaire est donc transposée en CSS natif :

     @theme { --color-x }      ->  :root { --color-x }
     class="bg-default-card"   ->  .card { background: var(--color-default-card) }

   Les tokens gardent EXACTEMENT les noms du document : c'est ce qui permet de
   relire DESIGN.md et de retrouver chaque valeur.

   Écarts assumés, tous justifiés par DESIGN.md §6 (« ce qu'il ne faut pas
   reprendre ») :
     - aucune duplication mobile/desktop dans le DOM (lecteurs d'écran) ;
     - aucun `user-scalable=no` : le zoom reste possible ;
     - la palette FDJ est remplacée par la palette neutre du §7, comme le
       document l'exige (couleurs et logos protégés).
   ============================================================================= */

/* -----------------------------------------------------------------------------
   1. Fondations — DESIGN.md §2.1
   L'échelle entière repose sur 1rem = 10px. Le zoom texte du navigateur reste
   opérant (critère RGAA), sans casser la grille.
   -------------------------------------------------------------------------- */

html {
    font-size: 62.5%;
    -webkit-text-size-adjust: 100%;
}

:root {
    /* --- Typographie — DESIGN.md §2.4 -------------------------------------
       Metropolis est sous licence SIL OFL mais n'est pas embarquée (aucun
       asset externe autorisé, et l'auto-héberger alourdirait le dépôt sans
       nécessité). On prend la pile système, géométrique en premier choix.
       Chaque token embarque son interlignage : jamais laissé au hasard. */
    --font-body: "Segoe UI", system-ui, -apple-system, "Helvetica Neue", Arial, sans-serif;
    --font-display: var(--font-body);
    --font-legal: "Roboto", "Segoe UI", system-ui, Arial, sans-serif;
    --font-mono: ui-monospace, "Cascadia Mono", "SFMono-Regular", Consolas, monospace;

    --text-display-4: 4rem;      --text-display-4-lh: 1;
    --text-display-5: 3rem;      --text-display-5-lh: 1;
    --text-heading-1: 3.2rem;    --text-heading-1-lh: 1.15;
    --text-heading-2: 2.4rem;    --text-heading-2-lh: 1.2;
    --text-heading-3: 2rem;      --text-heading-3-lh: 1.2;
    --text-heading-5: 1.6rem;    --text-heading-5-lh: 1.25;
    --text-heading-sm: 1.4rem;   --text-heading-sm-lh: 1.25;
    --text-subheading-lg: 2rem;  --text-subheading-lg-lh: 1.1;
    --text-subheading-md: 1.8rem;--text-subheading-md-lh: 1.1;
    --text-subheading-sm: 1.6rem;--text-subheading-sm-lh: 1.1;
    --text-body: 1.6rem;         --text-body-lh: 1.3;
    --text-caption: 1.4rem;      --text-caption-lh: 1.2;
    --text-mention: 1rem;        --text-mention-lh: 1.3;

    /* --- Espacement — DESIGN.md §2.5 ---------------------------------------
       Échelle nommée uniquement. Aucune valeur numérique brute ailleurs. */
    --spacing-2xs: 0.4rem;
    --spacing-xs:  0.8rem;
    --spacing-sm:  1.2rem;
    --spacing-md:  1.6rem;
    --spacing-lg:  2.4rem;
    --spacing-xl:  3.2rem;
    --spacing-2xl: 4.8rem;

    /* --- Rayons — DESIGN.md §2.6 ------------------------------------------
       Les boutons sont plus arrondis que les cartes : c'est volontaire. */
    --radius-xs: 0.4rem;
    --radius-sm: 0.8rem;
    --radius-lg: 1.2rem;
    --radius-full: 999rem;

    /* --- Élévation — DESIGN.md §2.7 ---------------------------------------
       Jamais de nombre magique. Le bandeau réglementaire passe au-dessus de
       tout : la contrainte légale prime sur la hiérarchie visuelle. */
    --z-below:  -1;
    --z-card:   10;
    --z-banner: 20;
    --z-inpes:  30;
    --z-header: 40;

    /* --- Ombres — DESIGN.md §2.6 ------------------------------------------ */
    --shadow-md: 0 0.2rem 0.8rem rgba(31, 35, 82, .10);
    --shadow-lg: 0 0.8rem 2.4rem rgba(31, 35, 82, .16);

    /* --- Couleurs — DESIGN.md §2.3 et §7 -----------------------------------
       Palette neutre de départ du document. Les couleurs FDJ sont protégées
       et ne sont pas reprises. */
    --color-default-bg: #f7f7f9;
    --color-default-card: #ffffff;
    --color-background: #ffffff;
    --color-default-surface: #ffffff;
    --color-default-surface-disabled: #ececed;
    --color-default-content-disabled: #a5a5ae;

    --color-primary: #1f2352;
    --color-primary-brand: #1f2352;
    --color-primary-450: #3a4090;
    --color-secondary-brand: #ffd23f;
    --color-standard: #2b2b2b;
    --color-standard-500: #6b6b76;
    --color-standard-100: #e3e3e8;
    --color-default-primary-invert: #ffffff;
    --color-default-primary-constant-invert: #ffffff;

    --color-border-default-primary: #e3e3e8;
    --color-secondary: #d4d4dc;

    --color-cta-filled-bg-primary: #1f2352;
    --color-cta-filled-text-primary: #ffffff;

    /* Boules de tirage — token métier, DESIGN.md §2.3 */
    --color-ball-bg-primary-selected: #1f2352;
    --color-ball-text-primary-selected: #ffffff;
    --color-ball-bg-secondary-selected: #ffd23f;
    --color-ball-text-secondary-selected: #1f2352;
    --color-ball-bg-tertiary-selected: #e3e3e8;
    --color-ball-text-tertiary-selected: #1f2352;

    --color-gradient-primary: linear-gradient(135deg, #1f2352, #3a4090);

    --color-yellow-mmeg: #ffe45c;
    --color-info: #6f9ffb;

    /* Sémantique de statut, propre à ce projet (absente de DESIGN.md) */
    --color-ok:   #1a7f45;
    --color-warn: #9a6700;
    --color-err:  #b42318;
}

/* --- Thèmes par marque — DESIGN.md §2.2 ----------------------------------
   L'idée centrale du système : un composant écrit une fois, sa couleur
   d'accent pilotée par le `data-theme` du conteneur. Ici, un thème par
   modèle statistique plutôt que par jeu — même mécanique, autre domaine. */

[data-theme="euromillions"] {
    --color-primary: #1f2352;
    --color-ball-bg-primary-selected: #1f2352;
    --color-ball-bg-secondary-selected: #ffd23f;
    --color-gradient-primary: linear-gradient(135deg, #1f2352, #4a51b5);
}

[data-theme="weighted_frequency"] {
    --color-primary: #1d6fa5;
    --color-ball-bg-primary-selected: #1d6fa5;
    --color-gradient-primary: linear-gradient(135deg, #1d6fa5, #0d3550);
}

[data-theme="gap"] {
    --color-primary: #8a5a1b;
    --color-ball-bg-primary-selected: #8a5a1b;
    --color-gradient-primary: linear-gradient(135deg, #8a5a1b, #4a2f08);
}

[data-theme="anti_popularity"] {
    --color-primary: #1a7f45;
    --color-ball-bg-primary-selected: #1a7f45;
    --color-gradient-primary: linear-gradient(135deg, #1a7f45, #0a3f20);
}

[data-theme="markov"] {
    --color-primary: #6b3fa0;
    --color-ball-bg-primary-selected: #6b3fa0;
    --color-gradient-primary: linear-gradient(135deg, #6b3fa0, #34194f);
}

[data-theme="dirichlet"] {
    --color-primary: #a03f6b;
    --color-ball-bg-primary-selected: #a03f6b;
    --color-gradient-primary: linear-gradient(135deg, #a03f6b, #4f1934);
}

[data-theme="random"] {
    --color-primary: #6b6b76;
    --color-ball-bg-primary-selected: #6b6b76;
    --color-gradient-primary: linear-gradient(135deg, #6b6b76, #33333a);
}

/* -----------------------------------------------------------------------------
   2. Réinitialisation minimale
   -------------------------------------------------------------------------- */

*, *::before, *::after { box-sizing: border-box; }

body {
    margin: 0;
    background: var(--color-default-bg);
    color: var(--color-standard);
    font-family: var(--font-body);
    font-size: var(--text-body);
    line-height: var(--text-body-lh);
    /* DESIGN.md §4.1 : marge basse réservée à une barre flottante. */
    margin-bottom: var(--spacing-2xl);
}

img, svg { max-width: 100%; }

h1, h2, h3, h4 {
    margin: 0;
    color: var(--color-primary);
    font-weight: 700;
    /* DESIGN.md §2.4 : jamais de coupure sauvage sur les montants et les noms. */
    word-break: normal;
    overflow-wrap: break-word;
}

h1 { font-size: var(--text-heading-1); line-height: var(--text-heading-1-lh); }
h2 { font-size: var(--text-heading-2); line-height: var(--text-heading-2-lh); }
h3 { font-size: var(--text-heading-3); line-height: var(--text-heading-3-lh); }

p { margin: 0 0 var(--spacing-sm); }
p:last-child { margin-bottom: 0; }

/* --- Lien — DESIGN.md §3.5 -----------------------------------------------
   Signature du système : soulignement épais 2px, très décollé (6px). */
a {
    color: var(--color-primary-brand);
    font-size: var(--text-body);
    cursor: pointer;
    text-decoration: underline;
    text-decoration-thickness: 0.2rem;
    text-underline-offset: 0.6rem;
}

a:hover { color: var(--color-primary-450); }

/* Variante navigation : soulignement au survol seulement. */
a.nav-link { text-decoration: none; }
a.nav-link:hover { text-decoration: underline; }

/* DESIGN.md §6 : focus visible partout. */
:focus-visible {
    outline: 0.2rem solid var(--color-primary-brand);
    outline-offset: 0.2rem;
}

code {
    font-family: var(--font-mono);
    font-size: 0.9em;
    background: var(--color-default-bg);
    border: 0.1rem solid var(--color-border-default-primary);
    border-radius: var(--radius-xs);
    padding: 0.1em 0.4em;
}

/* Aperçu d'un message tel qu'il partira — SMS ou notification.
   Le chasse-fixe n'est pas décoratif : il rend visibles les espaces et
   l'alignement des grilles, et c'est ce qui permet de compter les caractères
   à l'œil avant d'engager un segment facturé. Le retour à la ligne est forcé
   (`pre-wrap`) plutôt que laissé au défilement : un message tronqué à droite
   donnerait l'illusion d'être plus court qu'il n'est. */
.msg-preview {
    margin: var(--spacing-2xs) 0 0;
    font-family: var(--font-mono);
    font-size: var(--text-mention);
    line-height: 1.5;
    white-space: pre-wrap;
    overflow-wrap: anywhere;
    background: var(--color-default-bg);
    border: 0.1rem solid var(--color-border-default-primary);
    border-radius: var(--radius-sm);
    padding: var(--spacing-sm);
}

/* -----------------------------------------------------------------------------
   3. Liens d'évitement — DESIGN.md §6
   Nuls visuellement, complets au clavier.
   -------------------------------------------------------------------------- */

.skip-links {
    background: #f2f2f2;
    display: flex;
    gap: var(--spacing-md);
    justify-content: center;
    height: 0;
    overflow: hidden;
}

.skip-links:focus-within {
    height: auto;
    padding: var(--spacing-xs);
}

.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;
}

/* -----------------------------------------------------------------------------
   4. Bandeau réglementaire — DESIGN.md §3.10
   Élévation z-inpes : au-dessus de tout le reste du header.
   -------------------------------------------------------------------------- */

.inpes {
    position: relative;
    z-index: var(--z-inpes);
    background: var(--color-yellow-mmeg);
    color: #1a1a1a;
    font-family: var(--font-legal);
    font-weight: 700;
    text-transform: uppercase;
}

.inpes .container {
    display: flex;
    align-items: center;
    gap: var(--spacing-md);
    padding-block: var(--spacing-xs);
}

.inpes-text { font-size: 0.9rem; line-height: 1.3; }
.inpes-text .secondary { display: block; font-size: 0.8rem; text-transform: none; font-weight: 400; }

.inpes-age {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 4rem; height: 4rem;
    border: 0.2rem solid #1a1a1a;
    border-radius: var(--radius-full);
    font-size: var(--text-caption);
}

@media (min-width: 768px) {
    .inpes-text { font-size: var(--text-heading-sm); }
    .inpes-text .secondary { font-size: var(--text-body); }
    .inpes-age { width: 6rem; height: 6rem; font-size: var(--text-heading-3); }
}

/* -----------------------------------------------------------------------------
   5. Conteneur et sections — DESIGN.md §4.2
   La couleur de fond d'une section est une variable injectée en inline, pour
   qu'un changement éditorial ne touche pas au code.
   -------------------------------------------------------------------------- */

.container {
    width: 100%;
    max-width: 128rem;
    margin-inline: auto;
    padding-inline: var(--spacing-md);
}

@media (min-width: 1024px) {
    .container { padding-inline: var(--spacing-lg); }
}

.section {
    position: relative;
    width: 100%;
    background: var(--color-background-block, transparent);
}

.section > .container { padding-block: var(--spacing-lg); }
.section--tight > .container { padding-block: var(--spacing-md); }
.section--loose > .container { padding-block: var(--spacing-xl); }

/* --- En-tête de section — DESIGN.md §3.9 --------------------------------
   Titre + filet court de 40x2px. Marqueur discret et réutilisable. */
.section-head {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--spacing-sm);
    margin-bottom: var(--spacing-md);
}

.section-head hr {
    height: 0.2rem;
    width: 4rem;
    margin: 0;
    border: 0;
    background: var(--color-standard-100);
}

.section-head .sub {
    font-size: var(--text-caption);
    line-height: var(--text-caption-lh);
    color: var(--color-standard-500);
    font-weight: 400;
}

/* -----------------------------------------------------------------------------
   6. En-tête de page — DESIGN.md §4.1
   -------------------------------------------------------------------------- */

.masthead {
    position: sticky;
    top: 0;
    z-index: var(--z-header);
    background: var(--color-default-card);
    border-bottom: 0.1rem solid var(--color-secondary);
}

.masthead-bar {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: var(--spacing-xs) var(--spacing-md);
    padding-block: var(--spacing-sm);
}

/* Le bloc de session est poussé à droite, la baseline du titre est conservée
   pour le reste de la barre. */
.masthead-bar .masthead-session { margin-left: auto; align-self: center; }

.masthead h1 { font-size: var(--text-heading-3); }

.masthead .claim {
    margin: 0;
    font-size: var(--text-caption);
    line-height: var(--text-caption-lh);
    color: var(--color-standard-500);
}

.tabs {
    display: flex;
    flex-wrap: wrap;
    gap: var(--spacing-2xs);
    padding-bottom: var(--spacing-xs);
}

.tabs a {
    padding: var(--spacing-2xs) var(--spacing-sm);
    border-radius: var(--radius-lg);
    font-size: var(--text-caption);
    line-height: var(--text-caption-lh);
    color: var(--color-standard-500);
    text-decoration: none;
}

.tabs a:hover {
    background: var(--color-default-bg);
    color: var(--color-primary-brand);
}

.tabs a[aria-current="page"] {
    background: var(--color-primary-brand);
    color: var(--color-default-primary-invert);
    font-weight: 700;
}

.tabs a[aria-disabled="true"] {
    color: var(--color-default-content-disabled);
    cursor: not-allowed;
}

/* -----------------------------------------------------------------------------
   7. Boule de tirage — DESIGN.md §3.1, le composant signature
   35px en mobile (cible tactile), 25px en desktop (densité). Contre-intuitif
   et volontaire.

   Écart assumé : DESIGN.md duplique le chiffre dans deux <div> (un par palier
   typo). §6 signale que cette duplication pollue les lecteurs d'écran. Un
   seul nœud ici, la taille bascule en CSS.
   -------------------------------------------------------------------------- */

.balls {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--spacing-xs);
}

/* Une grille dans une cellule de tableau : la colonne est étroite et le
   `flex-wrap` du conteneur empilerait les sept numéros les uns sous les
   autres, ce qui étire la ligne sur sept hauteurs de boule. Ici la grille
   reste sur une ligne — le tableau, lui, défile déjà horizontalement. */
.balls--tight {
    flex-wrap: nowrap;
    gap: var(--spacing-2xs);
}

.ball {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: 3.5rem;
    height: 3.5rem;
    border-radius: var(--radius-full);
    background: var(--color-ball-bg-primary-selected);
    color: var(--color-ball-text-primary-selected);
    font-size: var(--text-subheading-sm);
    line-height: var(--text-subheading-sm-lh);
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    user-select: none;
}

@media (min-width: 1024px) {
    .ball {
        width: 2.5rem;
        height: 2.5rem;
        font-size: var(--text-caption);
        line-height: var(--text-caption-lh);
    }
}

/* --- Variante « forme » — DESIGN.md §3.1 --------------------------------
   Le fond n'est plus un cercle : un SVG en position absolue derrière le
   chiffre, coloré par le token secondaire.

   Écart assumé par rapport au document : l'étoile est agrandie d'environ un
   tiers par rapport à la boule ronde. À diamètre égal, une étoile à cinq
   branches offre bien moins de surface utile qu'un cercle, et un nombre à
   deux chiffres (« 10 », « 12 ») débordait des branches. La FDJ n'a pas ce
   problème : son numéro chance ne dépasse jamais 10 et tient sur un chiffre.
   Le rapport de taille visuel reste équivalent, les branches compensant. */
.ball--star {
    width: 4.6rem;
    height: 4.6rem;
    background: transparent;
    color: var(--color-ball-text-secondary-selected);
}

@media (min-width: 1024px) {
    .ball--star { width: 3.4rem; height: 3.4rem; }
}

.ball--star svg {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    fill: var(--color-ball-bg-secondary-selected);
}

.ball--star span {
    position: relative;
    /* Correction optique : compense le centre de gravité de l'étoile, dont la
       masse est plus haute que le centre géométrique de la boîte. */
    top: 0.15rem;
}

.ball--muted {
    background: var(--color-ball-bg-tertiary-selected);
    color: var(--color-ball-text-tertiary-selected);
}

/* -----------------------------------------------------------------------------
   8. Carte — DESIGN.md §3.2
   Le geste le plus économique du système : une arête de 10px qui identifie
   la source, et qui MIGRE du haut (mobile) vers la gauche (desktop).
   Zéro logo coloré, zéro fond teinté.
   -------------------------------------------------------------------------- */

.card {
    background: var(--color-default-card);
    border: 0.1rem solid var(--color-border-default-primary);
    border-radius: var(--radius-sm);
    padding: var(--spacing-lg);
}

.card--accent {
    border-inline: 0;
    border-top: 1rem solid var(--color-primary);
    border-bottom: 0;
}

@media (min-width: 1024px) {
    .card--accent {
        border-block: 0;
        border-right: 0;
        border-left: 1rem solid var(--color-primary);
    }
}

.card--flush { padding: 0; overflow: hidden; }

.card-head {
    font-size: var(--text-caption);
    line-height: var(--text-caption-lh);
    font-weight: 700;
    color: var(--color-primary);
}

.card-date {
    font-size: var(--text-body);
    line-height: var(--text-body-lh);
    font-weight: 700;
    color: var(--color-standard);
}

/* Carte résultat : disposition colonne -> ligne au palier lg. DESIGN.md §3.2 */
.result-card {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-md);
    align-items: flex-start;
}

@media (min-width: 1024px) {
    .result-card {
        flex-direction: row;
        align-items: center;
        gap: var(--spacing-lg);
    }
    .result-card .result-main { flex: 1 1 auto; }
    .result-card .result-aside {
        flex: 0 0 26rem;
        border-left: 0.1rem solid var(--color-standard-100);
        padding-left: var(--spacing-lg);
    }
}

/* -----------------------------------------------------------------------------
   9. Encart dégradé — DESIGN.md §3.3
   Rayons neutralisés du côté collé à la carte.
   -------------------------------------------------------------------------- */

.panel-gradient {
    display: flex;
    flex-direction: column;
    justify-content: center;
    width: 100%;
    background: var(--color-gradient-primary);
    color: var(--color-default-primary-constant-invert);
    border-radius: var(--radius-sm);
    padding: var(--spacing-sm) var(--spacing-md);
}

.panel-gradient .amount {
    font-size: var(--text-display-5);
    line-height: var(--text-display-5-lh);
    font-weight: 900;
}

@media (min-width: 1024px) {
    .panel-gradient .amount {
        font-size: var(--text-display-4);
        line-height: var(--text-display-4-lh);
    }
}

.panel-gradient .amount--accent { color: var(--color-secondary-brand); }

.panel-gradient .label {
    font-size: var(--text-caption);
    line-height: var(--text-caption-lh);
    opacity: .85;
}

sup.mention {
    font-size: var(--text-mention);
    line-height: var(--text-mention-lh);
}

/* -----------------------------------------------------------------------------
   10. Bouton — DESIGN.md §3.4
   Hauteur figée (min-h = max-h) : tous les boutons s'alignent, quelle que
   soit la longueur du libellé. Survol par voile blanc 8 % en ::before —
   une seule règle qui fonctionne sur toutes les couleurs de thème.
   -------------------------------------------------------------------------- */

.btn {
    position: relative;
    display: inline-flex;
    flex-direction: row;
    align-items: center;
    justify-content: center;
    gap: var(--spacing-xs);
    min-height: 4rem;
    max-height: 4rem;
    padding: 0.4rem 3.2rem;
    border-radius: var(--radius-lg);
    font-family: inherit;
    font-size: var(--text-body);
    font-weight: 500;
    line-height: 1;
    text-align: center;
    text-decoration: none;
    white-space: nowrap;
    cursor: pointer;
    transition: all 75ms linear;
}

.btn::before {
    content: "";
    position: absolute;
    inset: 0;
    background: var(--color-background);
    opacity: 0;
    border-radius: var(--radius-lg);
    pointer-events: none;
    transition: opacity 75ms linear;
}

.btn:hover::before { opacity: .08; }
.btn:focus-visible::before { opacity: .10; }

.btn:disabled,
.btn[aria-disabled="true"] {
    cursor: not-allowed;
    background: var(--color-default-surface-disabled);
    color: var(--color-default-content-disabled);
    border-color: transparent;
}

.btn--filled {
    border: 0;
    background: var(--color-cta-filled-bg-primary);
    color: var(--color-cta-filled-text-primary);
}

.btn--outlined {
    border: 0.1rem solid var(--color-border-default-primary);
    background: var(--color-default-surface);
    color: var(--color-primary-brand);
}

.btn--sm {
    min-height: 3.2rem;
    max-height: 3.2rem;
    padding-inline: var(--spacing-md);
    font-size: var(--text-caption);
}

/* -----------------------------------------------------------------------------
   11. Tuiles de chiffres et grilles
   -------------------------------------------------------------------------- */

.grid {
    display: grid;
    gap: var(--spacing-md);
    grid-template-columns: 1fr;
}

@media (min-width: 768px) {
    .grid--2 { grid-template-columns: repeat(2, 1fr); }
    .grid--3 { grid-template-columns: repeat(3, 1fr); }
    .grid--4 { grid-template-columns: repeat(2, 1fr); }
}

@media (min-width: 1024px) {
    .grid--4 { grid-template-columns: repeat(4, 1fr); }
}

.stat .label {
    display: block;
    font-size: var(--text-caption);
    line-height: var(--text-caption-lh);
    color: var(--color-standard-500);
}

.stat .value {
    display: block;
    margin-top: var(--spacing-2xs);
    font-size: var(--text-display-5);
    line-height: var(--text-display-5-lh);
    font-weight: 900;
    font-variant-numeric: tabular-nums;
    color: var(--color-primary);
}

.stat .note {
    display: block;
    margin-top: var(--spacing-2xs);
    font-size: var(--text-caption);
    line-height: var(--text-caption-lh);
    color: var(--color-standard-500);
}

.value--ok   { color: var(--color-ok); }
.value--warn { color: var(--color-warn); }
.value--err  { color: var(--color-err); }

/* -----------------------------------------------------------------------------
   12. Bandeau de message
   -------------------------------------------------------------------------- */

.banner {
    background: var(--color-default-card);
    border: 0.1rem solid var(--color-border-default-primary);
    border-left: 1rem solid var(--color-primary);
    border-radius: var(--radius-sm);
    padding: var(--spacing-md) var(--spacing-lg);
    font-size: var(--text-body);
    line-height: var(--text-body-lh);
}

.banner strong {
    display: block;
    margin-bottom: var(--spacing-2xs);
    color: var(--color-primary);
    font-size: var(--text-heading-5);
    line-height: var(--text-heading-5-lh);
}

.banner p { color: var(--color-standard-500); }

.banner--ok   { border-left-color: var(--color-ok); }
.banner--warn { border-left-color: var(--color-warn); }
.banner--err  { border-left-color: var(--color-err); }

/* -----------------------------------------------------------------------------
   13. Tableaux
   -------------------------------------------------------------------------- */

.scroll-x { overflow-x: auto; }

table {
    width: 100%;
    border-collapse: collapse;
    font-size: var(--text-caption);
    line-height: var(--text-caption-lh);
}

th, td {
    text-align: left;
    padding: var(--spacing-xs) var(--spacing-sm);
    border-bottom: 0.1rem solid var(--color-standard-100);
    white-space: nowrap;
}

th {
    color: var(--color-standard-500);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .04em;
    font-size: var(--text-mention);
    line-height: var(--text-mention-lh);
}

tbody tr:last-child td { border-bottom: 0; }
tbody tr:hover td { background: var(--color-default-bg); }

td.num, th.num {
    text-align: right;
    font-variant-numeric: tabular-nums;
    font-family: var(--font-mono);
}

td.wrap { white-space: normal; }

tfoot td, tfoot th {
    border-top: 0.2rem solid var(--color-standard-100);
    font-weight: 700;
}

/* Note explicative en pied de tableau : c'est une phrase, pas un en-tête de
   colonne. Elle ne doit hériter ni des capitales ni de l'interlettrage. */
.table-note {
    white-space: normal;
    text-transform: none;
    letter-spacing: normal;
    font-weight: 400;
    font-size: var(--text-caption);
    line-height: var(--text-caption-lh);
    color: var(--color-standard-500);
}

/* -----------------------------------------------------------------------------
   14. Barres et heatmap — CSS pur, aucun JS (contrainte projet)
   -------------------------------------------------------------------------- */

.bar {
    height: 0.6rem;
    min-width: 6rem;
    border-radius: var(--radius-full);
    background: var(--color-standard-100);
    overflow: hidden;
}

.bar > span {
    display: block;
    height: 100%;
    background: var(--color-primary);
}

.heatmap {
    display: flex;
    flex-wrap: wrap;
    gap: var(--spacing-2xs);
}

.heat {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 3.5rem;
    height: 3.5rem;
    border-radius: var(--radius-full);
    font-size: var(--text-caption);
    line-height: var(--text-caption-lh);
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    /* --heat va de 0 (froid) à 1 (chaud), posé en inline par le PHP. */
    background: color-mix(in srgb,
        var(--color-primary) calc(var(--heat, 0) * 100%),
        var(--color-standard-100));
    color: var(--color-default-primary-invert);
}

/* Sous ~55 % de mélange le fond est trop clair pour du texte blanc : le PHP
   pose cette classe et le chiffre repasse en encre foncée. Sans elle, le
   numéro le plus froid devient illisible — exactement celui qu'on veut lire. */
.heat--cool { color: var(--color-primary); }

/* Repli si color-mix n'est pas supporté : fond neutre lisible. */
@supports not (background: color-mix(in srgb, red 50%, blue)) {
    .heat { background: var(--color-standard-100); color: var(--color-primary); }
}

/* -----------------------------------------------------------------------------
   15. Liste clé / valeur
   -------------------------------------------------------------------------- */

dl.kv {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: var(--spacing-2xs) var(--spacing-md);
    margin: 0;
    font-size: var(--text-caption);
    line-height: var(--text-caption-lh);
}

dl.kv dt { color: var(--color-standard-500); }
dl.kv dd { margin: 0; font-family: var(--font-mono); color: var(--color-standard); }

/* -----------------------------------------------------------------------------
   16. Pied de page et mentions légales — DESIGN.md §3.10
   -------------------------------------------------------------------------- */

.site-footer {
    background: var(--color-primary);
    color: var(--color-default-primary-invert);
}

.site-footer .container { padding-block: var(--spacing-xl); }
.site-footer a { color: var(--color-default-primary-invert); }
.site-footer h2 {
    color: var(--color-default-primary-invert);
    font-size: var(--text-subheading-lg);
    line-height: var(--text-subheading-lg-lh);
}

.legal { background: var(--color-default-bg); }
.legal .container { padding-block: var(--spacing-lg); }

.legal ul {
    margin: 0;
    padding: 0;
    list-style: none;
    display: grid;
    gap: var(--spacing-xs);
}

.legal li {
    font-size: var(--text-caption);
    line-height: var(--text-caption-lh);
    text-align: justify;
    color: var(--color-standard-500);
}

.legal li sup {
    font-size: var(--text-mention);
    margin-right: var(--spacing-2xs);
}

/* -----------------------------------------------------------------------------
   17. Animation — DESIGN.md §5
   Interaction directe = 75ms · feedback contextuel = 300ms · mise en avant = 500ms.
   -------------------------------------------------------------------------- */

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

/* -----------------------------------------------------------------------------
   18. Champs de formulaire — back-office
   DESIGN.md ne spécifie pas de champ de saisie : le site public n'en a aucun.
   Le back-office en a besoin (filtres, coût, saisie manuelle). La grammaire
   est celle des boutons du §3.4 — même hauteur, même rayon, mêmes tokens —
   pour qu'un champ et un bouton s'alignent sur la même ligne.
   -------------------------------------------------------------------------- */

.field {
    display: inline-flex;
    flex-direction: column;
    gap: var(--spacing-2xs);
}

.field > label {
    font-size: var(--text-mention);
    line-height: var(--text-mention-lh);
    text-transform: uppercase;
    letter-spacing: .04em;
    font-weight: 700;
    color: var(--color-standard-500);
}

.input {
    min-height: 4rem;
    max-height: 4rem;
    padding: 0 var(--spacing-sm);
    border: 0.1rem solid var(--color-border-default-primary);
    border-radius: var(--radius-sm);
    background: var(--color-default-surface);
    color: var(--color-standard);
    font-family: inherit;
    font-size: var(--text-body);
    line-height: 1;
}

.input--sm {
    min-height: 3.2rem;
    max-height: 3.2rem;
    font-size: var(--text-caption);
    padding-inline: var(--spacing-xs);
}

.input--num {
    width: 8rem;
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
    text-align: right;
}

.input:focus-visible,
.btn:focus-visible {
    outline: 0.2rem solid var(--color-primary);
    outline-offset: 0.2rem;
}

/* Une barre d'outils : filtres, actions, tout ce qui s'aligne sur une ligne
   et repasse en colonne quand la place manque. */
.toolbar {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: var(--spacing-sm);
}

.toolbar .grow { flex: 1 1 auto; }

/* Un formulaire d'une seule action, posé dans une cellule de tableau : il ne
   doit ni créer de bloc ni décaler la ligne de base. */
.inline-form {
    display: inline-flex;
    align-items: center;
    gap: var(--spacing-2xs);
    margin: 0;
}

/* -----------------------------------------------------------------------------
   19. Pastille de statut
   -------------------------------------------------------------------------- */

.pill {
    display: inline-block;
    padding: 0.2rem var(--spacing-xs);
    border-radius: var(--radius-full);
    background: var(--color-standard-100);
    color: var(--color-primary);
    font-size: var(--text-mention);
    line-height: var(--text-mention-lh);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .04em;
    white-space: nowrap;
}

.pill--played  { background: var(--color-primary); color: var(--color-default-primary-invert); }
.pill--skipped { background: var(--color-standard-100); color: var(--color-standard-500); }
.pill--warn    { background: var(--color-warn); color: var(--color-default-primary-invert); }

/* -----------------------------------------------------------------------------
   20. Barre divergente — solde cumulé
   Le solde passe sous zéro et y reste : une barre qui part de la gauche ne
   saurait pas le montrer. Celle-ci a un axe au centre, la perte s'étend à
   gauche et le gain à droite. CSS pur, aucun JS (contrainte projet).
   -------------------------------------------------------------------------- */

.dbar {
    display: flex;
    align-items: stretch;
    min-width: 16rem;
    height: 1.2rem;
}

.dbar-half {
    position: relative;
    flex: 1 1 50%;
    background: var(--color-default-bg);
}

.dbar-half--neg { border-right: 0.1rem solid var(--color-standard-500); }

.dbar-fill {
    position: absolute;
    top: 0;
    bottom: 0;
    /* --w est posé en style inline par le PHP : 0 à 100 % de la demi-largeur. */
    width: var(--w, 0%);
    border-radius: var(--radius-xs);
}

.dbar-half--neg .dbar-fill { right: 0; background: var(--color-err); }
.dbar-half--pos .dbar-fill { left: 0; background: var(--color-ok); }

/* -----------------------------------------------------------------------------
   21. Jauge de plafond
   -------------------------------------------------------------------------- */

.gauge {
    height: 0.8rem;
    border-radius: var(--radius-full);
    background: var(--color-standard-100);
    overflow: hidden;
}

.gauge > span {
    display: block;
    height: 100%;
    width: var(--w, 0%);
    background: var(--color-ok);
}

.gauge--warn > span { background: var(--color-warn); }
.gauge--over > span { background: var(--color-err); }

/* -----------------------------------------------------------------------------
   22. Barre d'administration
   Signale sans ambiguïté qu'on est dans une zone qui écrit en base.
   -------------------------------------------------------------------------- */

.adminbar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--spacing-sm);
    padding: var(--spacing-xs) 0;
    font-size: var(--text-caption);
    line-height: var(--text-caption-lh);
    color: var(--color-standard-500);
}

.adminbar strong { color: var(--color-primary); }

/* -----------------------------------------------------------------------------
   23. Bouton icône
   -------------------------------------------------------------------------- */

.btn--icon {
    min-height: 3.2rem;
    max-height: 3.2rem;
    width: 3.2rem;
    padding: 0;
}

.btn--icon svg { display: block; }

/* -----------------------------------------------------------------------------
   24. Fenêtre modale — attribut natif `popover`, zéro JavaScript

   Les commandes d'une grille (coût, ticket, option, bascules) sont trop
   nombreuses pour tenir sur la ligne du tableau : elles vivent dans une
   fenêtre ouverte par `popovertarget`. Le navigateur fournit l'ouverture, la
   fermeture au clic extérieur, la touche Échap et le placement en top layer —
   ce qui aurait demandé un script, que le projet s'interdit et que la CSP de
   `public/.htaccess` bloquerait de toute façon.

   ORDRE DES RÈGLES, IMPORTANT : le repli est écrit en premier, hors de tout
   `@supports`. Un navigateur qui ignore `popover` affiche donc le bloc en
   flux, sous la ligne — moche mais utilisable. Les styles de fenêtre ne
   s'appliquent qu'à l'intérieur du `@supports`, sans quoi un navigateur sans
   `popover` se retrouverait avec un panneau `position: fixed` affiché en
   permanence par-dessus la page.
   -------------------------------------------------------------------------- */

.modal {
    margin: var(--spacing-xs) 0 0;
    padding: var(--spacing-md);
    border: 0.1rem solid var(--color-border-default-primary);
    border-radius: var(--radius-sm);
    background: var(--color-default-card);
    color: var(--color-standard);
    white-space: normal;
}

.modal-title {
    margin: 0;
    color: var(--color-primary);
    font-size: var(--text-heading-5);
    line-height: var(--text-heading-5-lh);
    font-weight: 700;
}

.modal-grid { margin-top: var(--spacing-sm); }

.modal-sub {
    margin: var(--spacing-sm) 0 0;
    color: var(--color-standard-500);
    font-size: var(--text-caption);
    line-height: var(--text-caption-lh);
}

.modal-fields {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: var(--spacing-sm);
    margin-top: var(--spacing-md);
}

.modal-fields .field.grow { flex: 1 1 16rem; }
.modal-fields .field.grow .input { width: 100%; }

.modal-check {
    margin: var(--spacing-sm) 0 0;
    font-size: var(--text-caption);
    line-height: var(--text-caption-lh);
    color: var(--color-standard-500);
}

.modal-hint {
    margin: var(--spacing-2xs) 0 0;
    font-size: var(--text-mention);
    line-height: var(--text-mention-lh);
    color: var(--color-standard-500);
}

.modal-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--spacing-xs);
    margin: var(--spacing-md) 0 0;
}

.modal-actions .inline-form label { color: var(--color-standard-500); }

/* Séparation entre le formulaire d'édition et les bascules de statut. */
.modal form + .modal-actions {
    padding-top: var(--spacing-md);
    border-top: 0.1rem solid var(--color-standard-100);
}

.modal-close { margin-top: var(--spacing-md); }

@supports selector(:popover-open) {
    .modal {
        position: fixed;
        inset: 0;
        margin: auto;
        width: min(48rem, calc(100vw - 3.2rem));
        max-height: calc(100vh - 6.4rem);
        overflow: auto;
        padding: var(--spacing-lg);
        border: 0;
        border-radius: var(--radius-lg);
        box-shadow: var(--shadow-lg);
    }

    .modal::backdrop { background: rgba(31, 35, 82, .45); }
}

/* Titre de carte portant une commande à droite (roue crantée des plafonds). */
.card-head--action {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--spacing-sm);
}

/* Groupe de commandes dans une cellule de tableau. */
.rowbar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--spacing-xs);
}

/* Zone d'action irréversible dans une fenêtre modale : séparée du reste par un
   filet, et seule de son bloc. Sans JavaScript il n'y a pas de `confirm()` —
   c'est donc la mise en page qui doit empêcher le clic distrait. */
.modal-danger {
    margin-top: var(--spacing-lg);
    padding-top: var(--spacing-md);
    border-top: 0.1rem solid var(--color-standard-100);
}

.btn--danger {
    border-color: var(--color-err);
    color: var(--color-err);
}

/* Bloc de session dans l'en-tête : identifiant + déconnexion, présent sur
   toutes les pages depuis que l'authentification couvre tout le site. */
.masthead-session {
    display: flex;
    align-items: center;
    gap: var(--spacing-sm);
    margin: 0;
    font-size: var(--text-caption);
    line-height: var(--text-caption-lh);
    color: var(--color-standard-500);
}

/* -----------------------------------------------------------------------------
   25. Page de connexion — mise en page nue
   La seule page sans en-tête ni pied de page : un visiteur non connecté n'a
   rien à faire d'une navigation dont tous les liens le ramèneraient ici. Une
   carte centrée, rien d'autre.
   -------------------------------------------------------------------------- */

.auth-body {
    /* Annule la marge basse réservée à la barre flottante (§2) : sans elle, la
       carte n'est pas centrée mais légèrement haute. */
    margin-bottom: 0;
    background: var(--color-default-bg);
}

.auth {
    display: flex;
    flex-direction: column;
    justify-content: center;
    min-height: 100vh;
    min-height: 100svh;
    padding: var(--spacing-lg);
}

.auth-card {
    width: 100%;
    max-width: 38rem;
    margin: 0 auto;
    padding: var(--spacing-xl);
    background: var(--color-default-card);
    border: 0.1rem solid var(--color-border-default-primary);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-md);
}

.auth-brand {
    margin: 0;
    font-size: var(--text-mention);
    line-height: var(--text-mention-lh);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .08em;
    color: var(--color-standard-500);
}

.auth-card h1 {
    margin: var(--spacing-xs) 0 var(--spacing-lg);
    font-size: var(--text-heading-2);
    line-height: var(--text-heading-2-lh);
    color: var(--color-primary);
}

.auth-lead {
    margin: 0 0 var(--spacing-sm);
    font-size: var(--text-caption);
    line-height: var(--text-caption-lh);
    color: var(--color-standard-500);
}

/* Un message d'erreur, pas un bandeau : la page ne porte que le formulaire,
   une carte dans la carte serait un cadre de trop. */
.auth-error {
    margin: 0 0 var(--spacing-md);
    padding-left: var(--spacing-sm);
    border-left: 0.3rem solid var(--color-err);
    font-size: var(--text-caption);
    line-height: var(--text-caption-lh);
    color: var(--color-err);
}

.auth-form {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-md);
}

.auth-form .field { width: 100%; }
.auth-form .btn { margin-top: var(--spacing-xs); }

/* Plusieurs indications empilées dans une carte (page Paramètres) : sans
   respiration entre elles, trois paragraphes se lisent comme un seul bloc. */
.card > .modal-hint + .modal-hint { margin-top: var(--spacing-sm); }
