/* =====================================================================
   Ulalu — espace organisateur
   ---------------------------------------------------------------------
   Complément à ulalu.css, chargé uniquement par les pages du compte et
   de l'espace organisateur (@section Head). Aucun jeton n'est redéfini
   ici : tout s'appuie sur les variables de ulalu.css, donc le mode
   sombre suit automatiquement.

   Sommaire : 0 console de l'événement · 1 en-têtes de page · 2 compteurs
   · 3 parcours par étapes
   · 4 sections repliables · 5 galeries longues · 6 choix de musique
   · 7 suivi de production · 8 invitation · 9 authentification
   · 10 formulaires · 11 divers
   ===================================================================== */

/* ---------- 0. Console de l'événement (D-143) ---------- */
/*
 * Un événement n'est pas une page, c'est un atelier : le lien de dépôt, l'appareil jetable, les
 * contributions, le film. On y revient au jour 3 et au jour 10, dans le désordre. La coque range
 * ces lieux dans une barre à gauche et n'en affiche qu'un seul à la fois.
 *
 * Mêmes mesures et même grammaire que la coque d'administration (admin.css § 1), à dessein : elle
 * a déjà été mesurée, et sous 62 rem elle sait se replier au-dessus du contenu en pastilles plutôt
 * qu'en tiroir. C'est délibéré : l'en-tête du site porte déjà un bouton ☰ sous 52 rem, et deux
 * hamburgers sur le même écran, c'est pile ou face.
 */
.evshell {
    display: grid;
    grid-template-columns: 15.5rem minmax(0, 1fr);
    gap: 1.6rem;
    align-items: start;
}

.evside {
    position: sticky;
    /* La même réserve que .rail laisse à l'en-tête collant (scroll-margin-top). */
    top: 5rem;
    /* Un menu plus haut que l'écran défile au lieu de sortir par le bas. */
    max-height: calc(100vh - 6rem);
    overflow-y: auto;
    display: grid;
    gap: .8rem;
    align-content: start;
    padding: .9rem .8rem 1rem;
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--r);
}

/* Le menu est une case de la grille de la barre : sans cela, il garde la largeur de sa ligne de
   pastilles, qui ne défile plus mais pousse la page — 1 323 px de large sur un téléphone de 375.
   Mesuré le 2026-09-22, à 375 px. */
.evnav { min-width: 0; }
.evnav ul, .evnav ol { list-style: none; margin: 0; padding: 0; display: grid; gap: .1rem; }
.evnav li { min-width: 0; }

/* Le parcours ne s'écrit qu'ici (D-143) : numéro, libellé, état en toutes lettres. C'est l'ancien rail,
   descendu dans la barre — il n'y a plus de bandeau en haut du contenu ni d'accordéon dessous. */
.evnav__steps { margin-bottom: .2rem; }
.evnav__num {
    grid-area: num;
    display: grid;
    place-items: center;
    width: 1.5rem;
    height: 1.5rem;
    border-radius: 50%;
    background: var(--surface-2);
    color: var(--muted-ink);
    font-size: var(--t-xs);
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}
.evnav .is-done .evnav__num { background: color-mix(in srgb, var(--jade) 18%, var(--surface)); color: var(--jade); }
.evnav .is-running .evnav__num { background: color-mix(in srgb, var(--amber) 28%, var(--surface)); color: var(--ink); }
.evnav .is-error .evnav__num { background: var(--danger); color: var(--btn-ink); }
.evnav .is-current .evnav__num { background: var(--btn-solid); color: var(--btn-ink); }
.evnav .is-current .evnav__state { color: var(--ember-text); font-weight: 650; }
.evnav a[aria-current="page"] .evnav__num:not(:empty) { background: var(--paper); color: var(--ink); }
.evnav a[aria-current="page"] .evnav__state { color: var(--paper); font-weight: 500; }

/* Une entrée sans numéro garde la colonne, mais pas la pastille : un rond plein et vide se lit comme
   une case à cocher, et sur l'entrée ouverte comme un bouton radio sélectionné (relevé par Rachid). */
.evnav__num:empty { background: none; }

/* Une entrée est un lien quand il y a quelque chose à y faire ; sinon c'est du texte, ni cliquable
   ni atteignable au clavier — la même règle que le rail. */
/*
 * Le mot d'état passe SOUS le libellé, comme le faisait le rail. Côte à côte dans une colonne de
 * 15,5 rem, les deux se disputaient la largeur : « Inviter vos invités · Prochaine étape » tenait sur
 * quatre lignes et 106 px de haut, et l'étape du moment devenait un gros bloc noir. Mesuré le
 * 2026-09-22 sur l'événement de Rachid.
 */
.evnav a, .evnav .evnav__off {
    display: grid;
    grid-template-columns: 1.5rem minmax(0, 1fr);
    grid-template-areas:
        "num label"
        "num state";
    align-items: center;
    column-gap: .55rem;
    row-gap: .05rem;
    min-height: 44px;
    padding: .4rem .6rem;
    border-radius: var(--r-sm);
    font-size: var(--t-sm);
    font-weight: 600;
    color: var(--ink-2);
    text-decoration: none;
    transition: background .18s, color .18s;
}
.evnav .evnav__off { color: var(--muted-ink); font-weight: 500; }
.evnav a:hover { background: var(--surface-2); color: var(--ink); }
.evnav a[aria-current="page"] { background: var(--ink); color: var(--paper); }

.evnav__label { grid-area: label; min-width: 0; overflow-wrap: anywhere; line-height: 1.25; }
.evnav__state { grid-area: state; font-size: var(--t-xs); font-weight: 500; color: var(--muted-ink); }
.evnav a[aria-current="page"] .evnav__state { color: var(--paper); }

.evnav__sep { margin: .45rem .2rem .25rem; border: 0; border-top: 1px solid var(--line); }

.evmain { min-width: 0; }

/*
 * L'écran est une feuille, et son titre en est l'en-tête. Posé au-dessus, le titre tombait 26 px à
 * gauche du texte qu'il nomme, à 19 px de la carte sur trois écrans et à 38 px sur deux autres ; et la
 * carte, elle, commençait sans en-tête, son premier mot à 1 px de son bord — le panneau d'avant avait
 * un résumé à cette place, et sa conversion en écran a laissé le trou. Mesuré le 2026-09-22.
 */
.evsheet {
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--r-lg);
    box-shadow: var(--shadow-1);
    padding: var(--pad);
}
.evsheet > .path { margin-block: 0; gap: 0; }
.evsheet > .evsection__title { margin-top: 0; }


/* Le pied d'un outil : ce que la loi demande, et rien à vendre. */
.foot--tool { margin-top: 2.5rem; padding: 1.1rem 0; border-top: 1px solid var(--line); background: none; }
.foot--tool .container { display: block; }
.foot--tool .legal { display: flex; flex-wrap: wrap; gap: .35rem 1.2rem; margin: 0; font-size: var(--t-xs); color: var(--muted-ink); }
.foot--tool .legal a { color: var(--ink-2); text-decoration: none; min-height: 0; }
.foot--tool .legal a:hover { color: var(--ember-text); text-decoration: underline; }

/* Sous 62 rem : la barre passe au-dessus et sa liste devient des pastilles qui reviennent à la
   ligne. Rien à ouvrir, rien à fermer, tout reste visible. */
@media (max-width: 62rem) {
    .evshell { grid-template-columns: minmax(0, 1fr); gap: 1.1rem; }
    .evside { position: static; max-height: none; overflow: visible; padding: .8rem; gap: .7rem; }

    /* Une seule ligne qui défile. En pastilles qui reviennent à la ligne, neuf entrées avec leur état
       mesuraient 386 px et repoussaient le contenu à 816 px — sous la ligne de flottaison. Le mot d'état
       reste : c'est lui qui dit où en est chaque lieu, et aucune couleur ne le remplace. */
    .evnav ul, .evnav ol { display: flex; flex-wrap: nowrap; overflow-x: auto; gap: .35rem; padding-bottom: .2rem; scrollbar-width: thin; }
    .evnav__steps { margin-bottom: .35rem; }
    .evnav li { flex: 0 0 auto; }
    /* Repliée en pastilles, l'entrée redevient une ligne : c'est la ligne qui défile, pas la pastille qui grandit. */
    .evnav a, .evnav .evnav__off {
        display: flex;
        align-items: center;
        gap: .45rem;
        border: 1px solid var(--line);
        border-radius: 999px;
        padding: .4rem .85rem;
        white-space: nowrap;
    }
    .evnav__label { overflow-wrap: normal; }
    .evnav a[aria-current="page"] { border-color: var(--ink); }
    .evnav__state { margin-left: .35rem; }
    .evnav__sep { display: none; }
}

/* Le fil d'Ariane : un chemin, pas une décoration. Le dernier terme est la page où l'on est, et
   n'est donc pas un lien. */
.trail { margin: 0 0 .9rem; }
.trail ol { list-style: none; display: flex; flex-wrap: wrap; align-items: baseline; gap: .3rem; margin: 0; padding: 0; font-size: var(--t-xs); }
.trail li { color: var(--muted-ink); }
.trail li::after { content: "\203A"; margin-left: .35rem; color: var(--line-strong); }
.trail li:last-child::after { content: none; }
.trail a { color: var(--ink-2); text-decoration: none; }
.trail a:hover { color: var(--ember-text); text-decoration: underline; }

/* Le titre de l'écran ouvert. Il vient sous le nom de l'événement, qui reste le h1 de la page : la page
   est l'événement, l'écran en est une partie, et il n'y a qu'un h1 (docs/08, règle 3). */
.evsection__title { font-size: var(--t-xl); margin: 0 0 .9rem; }

/* Le titre d'un bloc à l'intérieur de l'écran vient après celui de l'écran. Ils faisaient tous deux
   25 px : on lisait le sous-titre comme le titre, d'autant qu'il est décalé plus à droite. */
.evmain .step__body h3, .evmain .sources__title { font-size: var(--t-lg); }

/* ---------- 1. En-têtes de page ---------- */
.head { margin-bottom: 1.4rem; }
.head > div > :last-child { margin-bottom: 0; }
.head h1 { margin-bottom: .45rem; font-size: var(--t-2xl); }
.head .lead { margin-bottom: 0; }

@media (min-width: 48rem) {
    .head--split { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 1.2rem; align-items: end; }
    .head--split .head__side { justify-self: end; }
}

/* Fil d'Ariane : cible tactile confortable, jamais souligné par défaut */
.crumb {
    display: inline-flex;
    align-items: center;
    gap: .4rem;
    min-height: 40px;
    font-size: var(--t-sm);
    color: var(--muted-ink);
    text-decoration: none;
}
.crumb:hover { color: var(--ember-text); }

/* ---------- 2. Compteurs ---------- */
/* ---------- Ce que le film prendra (D-140) ---------- */
.film-sources__line {
    display: flex;
    align-items: flex-start;
    gap: .55rem;
    min-height: 44px;
    padding-block: .25rem;
    cursor: pointer;
}

.film-sources__line input { margin-top: .25rem; }

/* ---------- Ce que chaque dépôt a rapporté (D-137) ---------- */
/*
 * Une ligne par source — la pellicule, la galerie, les voix — avec ses chiffres et son
 * téléchargement. Même grammaire que .stats juste dessous : c'est le même coin d'écran,
 * qui répond à deux questions différentes (d'où ça vient, et dans quel état c'est).
 */
.sources { margin-block: 1.1rem; }

.sources__title { margin: 0 0 .15rem; font-size: var(--t-md); }

.sources__help { margin: 0 0 .7rem; font-size: var(--t-xs); }

.sources__list {
    list-style: none;
    padding: 0;
    margin: 0;
    display: grid;
    gap: .55rem;
}

.source {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .35rem .9rem;
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--r);
    padding: .7rem .9rem;
    box-shadow: var(--shadow-1);
}

.source__name {
    flex: 1 1 11rem;
    font-family: var(--font-display);
    font-variation-settings: "SOFT" 20, "WONK" 0, "opsz" 40;
    font-size: var(--t-md);
}

/* Les chiffres sur une ligne qui peut retomber : « 124 fichiers · 118 exploitables · 412 Mo ». */
.source__figures {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: .15rem .5rem;
    font-size: var(--t-xs);
}

.source__figures b { font-weight: 700; font-size: var(--t-sm); }

.source__figures .muted { font-size: var(--t-xs); }

.source .btn { margin-inline-start: auto; }

.stats {
    display: grid;
    gap: .7rem;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 8.5rem), 1fr));
    list-style: none;
    padding: 0;
    margin-block: 1.1rem;
}
.stats li {
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--r);
    padding: .7rem .9rem;
    box-shadow: var(--shadow-1);
}
.stats b {
    display: block;
    font-family: var(--font-display);
    font-variation-settings: "SOFT" 20, "WONK" 0, "opsz" 40;
    font-size: var(--t-xl);
    font-weight: 700;
    line-height: 1.15;
}
.stats span { font-size: var(--t-xs); color: var(--muted-ink); }
.stats li.is-quiet b { color: var(--muted-ink); font-weight: 600; }

/* ---------- 3. Parcours par étapes ---------- */
/* La page de l'événement est un parcours, pas un mur : un rail dit où l'on
   en est, un seul panneau est déplié — celui de l'étape du moment. Chaque
   état porte son mot (« Fait », « À venir », « Facultative »…) : la couleur
   ne porte jamais l'information seule. Le repli est un <details> natif, donc
   tout reste utilisable sans JavaScript. */

.rail { margin: 1.3rem 0 1.5rem; scroll-margin-top: 5rem; }
.rail__list { display: grid; gap: .35rem; list-style: none; margin: 0; padding: 0; }
.rail__item { min-width: 0; }

/* Une étape faite ou ouvrable est un lien ; les autres sont un <a> sans
   adresse, donc du texte, ni cliquable ni atteignable au clavier. */
.rail__link {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    grid-template-areas: "num title" "num state";
    align-items: center;
    column-gap: .65rem;
    min-height: 44px;
    padding: .5rem .7rem;
    border: 1px solid var(--line);
    border-radius: var(--r);
    background: var(--surface);
    color: var(--ink-2);
    text-decoration: none;
    transition: border-color .18s, background .18s, color .18s;
}
a[href].rail__link:hover { border-color: var(--line-strong); color: var(--ink); }
/* Une étape à venir n'est pas un lien : contour pointillé, fond de page. */
.rail__item.is-todo .rail__link { background: transparent; border-style: dashed; }

.rail__num {
    grid-area: num;
    display: grid;
    place-items: center;
    width: 1.7rem;
    height: 1.7rem;
    border-radius: 50%;
    background: var(--surface-2);
    color: var(--muted-ink);
    font-size: var(--t-xs);
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}
.rail__title { grid-area: title; font-size: var(--t-sm); font-weight: 620; line-height: 1.25; }
.rail__state { grid-area: state; font-size: var(--t-xs); color: var(--muted-ink); }

/* Le pictogramme double le mot ; il ne le remplace jamais. */
.rail__state::before, .step__state::before { content: "\25CB"; margin-right: .3rem; }
.is-optional .rail__state::before, .is-optional .step__state::before { content: "\25C7"; }
.is-done .rail__state::before, .is-done .step__state::before { content: "\2713"; }
.is-current .rail__state::before, .is-current .step__state::before { content: "\25B8"; }
.is-running .rail__state::before, .is-running .step__state::before { content: "\2026"; }
.is-error .rail__state::before, .is-error .step__state::before { content: "\26A0"; }

.rail .is-done .rail__num { background: color-mix(in srgb, var(--jade) 18%, var(--surface)); color: var(--jade); }
.rail .is-running .rail__num { background: color-mix(in srgb, var(--amber) 28%, var(--surface)); color: var(--ink); }
.rail .is-error .rail__num { background: var(--danger); color: var(--btn-ink); }
.rail .is-current .rail__link { border-color: var(--ember); background: color-mix(in srgb, var(--ember) 7%, var(--surface)); color: var(--ink); }
.rail .is-current .rail__num { background: var(--btn-solid); color: var(--btn-ink); }
.rail .is-current .rail__state { color: var(--ember-deep); font-weight: 650; }

/* Sept colonnes seulement quand il y a la place ; en dessous, une liste
   compacte qui se lit d'un coup d'œil plutôt que sept colonnes écrasées,
   sur deux colonnes dès qu'une tablette le permet (l'ordre se lit par
   ligne, et chaque étape porte son numéro). */
@media (min-width: 36rem) and (max-width: 57.99rem) {
    .rail__list { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (min-width: 58rem) {
    .rail__list { grid-template-columns: repeat(7, minmax(0, 1fr)); gap: .5rem; }
    .rail__link {
        grid-template-columns: minmax(0, 1fr);
        grid-template-areas: "num" "title" "state";
        align-items: start;
        align-content: start;
        row-gap: .3rem;
        padding: .7rem .75rem;
    }
}

/* ---- Panneaux ---- */
/* Le parcours de l'organisateur. Nommé « path » : « steps » appartient au site vitrine (ulalu.css),
   et ses règles de liste numérotée s'appliquaient à toutes les listes des panneaux. */
.path { display: grid; gap: .8rem; margin-block: 1.2rem; }

/* Un bloc de la feuille de l'écran. Ce n'était pas un bloc mais une carte, du temps où les écrans
   étaient des panneaux dépliants empilés sur une même page : une carte dans une feuille fait deux
   contours pour une seule chose. Un filet sépare deux blocs, et la feuille porte le fond. */
.step { scroll-margin-top: 5rem; }
.step + .step { margin-top: 1.5rem; padding-top: 1.3rem; border-top: 1px solid var(--line); }
.step__body { padding: 0; }
.step__body > :first-child { margin-top: 0; }
.step__body > :last-child { margin-bottom: 0; }

/* Sous-blocs d'un panneau : le lien d'invitation, la prolongation, la
   galerie. Un filet les sépare, aucun n'est une carte de plus. */
.step__block { margin-top: 1.6rem; padding-top: 1.2rem; border-top: 1px solid var(--line); }
.step__block:first-child { margin-top: 0; padding-top: 0; border-top: 0; }
.step__block > h3 { margin-top: 0; }
.step__block > :last-child { margin-bottom: 0; }
.step__after { margin-top: 1.4rem; }
.step__jump { font-size: var(--t-sm); font-weight: 600; }

/* Étape à venir : la phrase de sa condition, sur la feuille de l'écrna, et rien d'autre. */
.step__locked { margin: 0 0 .5rem; font-size: var(--t-sm); color: var(--ink-2); max-width: 62ch; }

/* Vérifier le tri : « Vérifier » et « Lancer sans vérifier » côte à côte ;
   sur un téléphone, l'une sous l'autre et sur toute la largeur, pour que
   le second ne se retrouve pas coupé en bout de ligne. */
.review-actions > form { margin: 0; }
@media (max-width: 30rem) {
    .review-actions { flex-direction: column; align-items: stretch; }
    .review-actions > .button, .review-actions > form, .review-actions > form > button { width: 100%; }
}

/* ---- Pied d'écran : ni compteurs ni export ne sont des étapes ---- */
.page-foot { margin-top: 2.4rem; padding-top: 1.2rem; border-top: 1px solid var(--line); }
.page-foot .stats { margin-block: 0 .9rem; }
.page-foot .fold { margin-block: 0; }
.stats--quiet li { background: transparent; border-color: transparent; box-shadow: none; padding: .3rem .1rem; }
.stats--quiet b { font-size: var(--t-lg); }

.meter {
    height: 6px;
    border-radius: 3px;
    background: var(--surface-2);
    overflow: hidden;
    margin: .2rem 0 .5rem;
}
.meter i { display: block; height: 100%; background: var(--mirror); }

/* Encart d'avertissement, plus doux qu'une erreur */
.note {
    padding: .75rem .95rem;
    border: 1px solid color-mix(in srgb, var(--amber) 45%, var(--line));
    border-radius: var(--r);
    background: color-mix(in srgb, var(--amber) 12%, var(--surface));
    font-size: var(--t-sm);
    color: var(--ink-2);
    margin-block: 1rem;
    max-width: none;
}

/* ---------- 4. Sections repliables ---------- */
.fold {
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--r-lg);
    box-shadow: var(--shadow-1);
    margin-block: 1.1rem;
}
.fold > summary {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    min-height: 44px;
    padding: var(--pad);
    cursor: pointer;
    list-style: none;
}
.fold > summary::-webkit-details-marker { display: none; }
.fold > summary::after {
    content: "+";
    flex: none;
    color: var(--ember);
    font-size: 1.4rem;
    line-height: 1;
}
.fold[open] > summary::after { content: "\2212"; }
.fold > summary:hover .fold__title { color: var(--ember-text); }
.fold__title {
    margin: 0;
    font-size: var(--t-xl);
    transition: color .18s;
}
.fold__body { padding: 0 var(--pad) var(--pad); }
.fold__body > :first-child { margin-top: 0; }
.fold__body > :last-child { margin-bottom: 0; }

/* Repli secondaire, imbriqué dans une carte : plus discret */
.fold--inline {
    box-shadow: none;
    border-color: transparent;
    background: var(--surface-2);
    border-radius: var(--r);
}
.fold--inline > summary { padding: .7rem .9rem; }
.fold--inline > summary::after { font-size: 1.15rem; }
.fold--inline .fold__title { font-size: var(--t-md); font-family: var(--font-ui); font-weight: 650; letter-spacing: 0; }
.fold--inline .fold__body { padding: 0 .9rem .9rem; }

/* ---------- 5. Galeries longues ---------- */
/* 275 vignettes doivent rester fluides : rendu différé des tuiles hors écran. La galerie défile avec la page. Elle
   était une boîte bornée qui défilait seule et gardait la molette (overscroll-behavior: contain) : sous la souris,
   la page ne défilait plus. */
.gallery--long .tile {
    content-visibility: auto;
    contain-intrinsic-size: auto 13rem;
    /* Un geste ramène à sa vignette par son ancre : elle se pose sous l'en-tête collant, pas dessous. */
    scroll-margin-top: 5rem;
}

/* ---------- 6. Choix de musique ---------- */
/* Liste générique de choix : un radio par ligne, encadré. */
.choices {
    display: grid;
    gap: .6rem;
    border: 0;
    padding: 0;
    margin: 1rem 0;
    min-inline-size: 0;
}
.choice {
    border: 1px solid var(--line);
    border-radius: var(--r);
    background: var(--surface);
    padding: .7rem .85rem;
    transition: border-color .18s, background .18s;
}
.choice:hover { border-color: var(--line-strong); }
.choice:has(input:checked) {
    border-color: var(--ember);
    background: color-mix(in srgb, var(--ember) 6%, var(--surface));
}
.choice > label { margin: 0; min-height: 40px; }
.choice .muted { display: block; }
.choice audio { margin-top: .55rem; }

/* ---------- 7. Suivi de production ---------- */
.prod { display: grid; gap: .75rem; }
.prod > * { margin: 0; }
.prod__bar {
    height: 14px;
    border-radius: 999px;
    background: var(--surface-2);
    border: 1px solid var(--line);
    overflow: hidden;
}
.prod__bar > i {
    display: block;
    height: 100%;
    width: 0;
    background: var(--mirror);
    background-size: 200% 100%;
    transition: width .6s cubic-bezier(.2, .8, .2, 1);
}
.prod__figures { display: flex; align-items: baseline; flex-wrap: wrap; gap: .2rem .7rem; }
.prod__percent {
    font-family: var(--font-display);
    font-variation-settings: "SOFT" 20, "WONK" 0, "opsz" 40;
    font-size: var(--t-2xl);
    font-weight: 700;
    line-height: 1;
    font-variant-numeric: tabular-nums;
}
.prod__stage { font-size: var(--t-md); font-weight: 600; color: var(--ink); }
.prod__detail { font-size: var(--t-sm); color: var(--muted-ink); font-variant-numeric: tabular-nums; }

.prod-fold { margin-top: .8rem; }
.prod-fold > summary { cursor: pointer; display: inline-flex; align-items: center; gap: .4rem; padding: .3rem 0; }
.prod-fold > summary::marker { color: var(--muted-ink); }
.prod-fold > summary:hover { color: var(--ink); }
/* La liste défile si elle dépasse : sur un téléphone elle ne doit pas repousser le reste du panneau. */
.prod-steps { list-style: none; padding: 0; margin: .4rem 0 0; display: grid; gap: .3rem; max-height: 14rem; overflow-y: auto; scroll-behavior: smooth; }
.prod-steps li {
    display: grid;
    grid-template-columns: 1.1rem minmax(0, 1fr);
    gap: .5rem;
    align-items: baseline;
    font-size: var(--t-sm);
    color: var(--muted-ink);
}
.prod-steps li::before { content: "\25CB"; color: var(--line-strong); font-size: .85em; }
.prod-steps li.is-done { color: var(--ink-2); }
.prod-steps li.is-done::before { content: "\2713"; color: var(--jade); font-weight: 700; }
.prod-steps li.is-current { color: var(--ink); font-weight: 650; }
.prod-steps li.is-current::before { content: "\25CF"; color: var(--ember); }

/* Le balayage du dégradé palindrome dit que quelque chose travaille. */
@media (prefers-reduced-motion: no-preference) {
    .prod__bar > i { animation: prod-sweep 3s linear infinite; }
}
@keyframes prod-sweep {
    from { background-position: 0 0; }
    to { background-position: 200% 0; }
}

/* ---------- 8. Invitation ---------- */
.invite { display: grid; gap: 1.2rem; align-items: start; }
@media (min-width: 40rem) { .invite { grid-template-columns: auto minmax(0, 1fr); } }
.invite figure { margin: 0; text-align: center; }
.invite figcaption { margin-top: .5rem; max-width: 12rem; }
.invite .qr { width: 11rem; height: 11rem; }
.invite .linkbox { margin-top: 0; }

.mono-link { word-break: break-all; }

/* ---------- 9. Authentification ---------- */
.auth {
    display: grid;
    gap: clamp(1.2rem, 1rem + 2vw, 2.4rem);
    align-items: start;
    width: min(100%, 56rem);
    margin-inline: auto;
}
@media (min-width: 56rem) {
    .auth { grid-template-columns: minmax(0, 26rem) minmax(0, 21rem); justify-content: center; }
    /* La connexion n'a pas de colonne de vente : sa carte est seule, et centrée pour de bon. */
    .auth--single { grid-template-columns: minmax(0, 26rem); }
    .auth__aside { position: sticky; top: 5rem; }
}
.auth .card { margin-block: 0; }
.auth__aside .check-list li { color: var(--ink-2); }

.narrow { width: min(100%, 40rem); margin-inline: auto; }

/* « Mon compte » (D-121, revu par D-147) : un compte, pas un formulaire. Une ligne par fait — son nom, sa valeur
   écrite en entier, « Modifier » à droite —, et le formulaire de la ligne s'ouvre sous elle, seul. */
.account .card h2 { font-size: var(--t-lg); margin-bottom: .4rem; }
.acct { padding-bottom: .4rem; }
.acct__title { margin: 0 0 .1rem; }
/* Le nom du fait et son action sur une ligne, la valeur en pleine largeur dessous : une adresse longue ne se
   dispute plus la place avec « Modifier », même à 375 px. L'ordre du document reste nom, valeur, action. */
.acct-row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas: "label action" "main main" "form form";
    column-gap: 1rem;
    align-items: center;
    padding-block: .7rem 1rem;
}
.acct-row + .acct-row { border-top: 1px solid var(--line); }
.acct-row__main { grid-area: main; min-width: 0; overflow-wrap: anywhere; }
.acct-row__label { grid-area: label; margin: 0; font-size: var(--t-sm); font-weight: 600; color: var(--muted-ink); }
.acct-row__value { margin: 0; font-weight: 600; color: var(--ink); overflow-wrap: anywhere; }
.acct-row__value--none { font-weight: 400; color: var(--ink-2); }
.acct-row__value--email { display: flex; flex-wrap: wrap; align-items: center; gap: .3rem .6rem; }
.acct-row__help { margin: .25rem 0 0; font-size: var(--t-sm); color: var(--ink-2); max-width: 60ch; }
.acct-row__address { white-space: pre-line; }
.acct-row__saved { margin: .7rem 0 0; }
.acct-row__action {
    grid-area: action;
    justify-self: end;
    display: inline-flex;
    align-items: center;
    min-height: 2.75rem;
    font-size: var(--t-sm);
    font-weight: 600;
    white-space: nowrap;
}
.acct-row__form { grid-area: form; margin-top: .3rem; }
.acct-row__buttons { display: flex; flex-wrap: wrap; gap: .6rem; align-items: center; }
.acct-row__buttons .acct-row__remove { margin-left: auto; }
.acct-foot { display: flex; flex-wrap: wrap; align-items: center; gap: .8rem 1.4rem; margin-top: 1.6rem; }
.acct-foot .muted { font-size: var(--t-sm); }

/* L'état d'une adresse, dans les teintes des statuts d'événement : confirmée comme une collecte ouverte, à
   confirmer comme ce qui attend. */
.status--ok { background: color-mix(in srgb, var(--jade) 14%, transparent); color: color-mix(in srgb, var(--jade) 75%, var(--ink)); }
.status--wait { background: color-mix(in srgb, var(--amber) 20%, transparent); color: #8a5a04; }
@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) .status--wait { color: var(--amber); }
}
:root[data-theme="dark"] .status--wait { color: var(--amber); }

/* Un changement d'adresse qui attend son lien (D-147). */
.address-pending {
    margin-block: 1rem 1.2rem;
    padding: 1rem 1.1rem;
    border: 1px solid color-mix(in srgb, var(--amber) 45%, var(--line));
    border-radius: var(--r-sm);
    background: color-mix(in srgb, var(--amber) 8%, var(--surface));
}
.address-pending__title { margin: 0 0 .35rem; font-size: var(--t-md); }
.address-pending .cluster { margin-block: .6rem; }

/* ---------- 10. Formulaires ---------- */
/* Deux champs courts côte à côte dès qu'il y a la place. */
.fields { display: grid; gap: 0 1.1rem; grid-template-columns: repeat(auto-fit, minmax(min(100%, 13rem), 1fr)); }
.fields > div > label:first-child { margin-top: .9rem; }

.form-actions { margin-top: 1.4rem; }
.form-actions > * { margin: 0; }

/* Cartes placées dans une grille : pas de marge verticale propre. */
.cards-grid > .card { margin-block: 0; }
.cards-grid .card h2, .cards-grid .card h3 { font-size: var(--t-lg); }

/* Liste des événements : ceux en cours, puis ceux terminés, chacun sous son
   titre et son nombre. Le titre d'une carte terminée est un lien sans
   soulignement ; les actions de la carte restent des boutons à part. */
.events-group { margin-top: 2.2rem; }
.events-group > h2 { display: flex; align-items: baseline; gap: .55rem; font-size: var(--t-xl); margin-bottom: .6rem; }
.events-group > .muted { margin-top: -.2rem; }
.events-group__count { font-family: var(--font-ui); font-size: var(--t-sm); font-weight: 600; color: var(--muted-ink); font-variant-numeric: tabular-nums; }
.card__title-link { color: inherit; text-decoration: none; }
.card__title-link:hover { color: var(--ember-text); }
.cards-grid .card > :last-child { margin-bottom: 0; }

/* Une carte seule garde sa largeur de carte : « auto-fit » étirait un événement terminé sur toute la page. */
.events-grid { grid-template-columns: repeat(auto-fill, minmax(min(100%, 26rem), 1fr)); }
.card-actions { margin-top: 1rem; }

/* En cours · Terminés (D-147) : deux onglets dès que les deux groupes existent, un seul visible. Sans :has(), les
   deux groupes se suivent avec leurs titres, comme avant ; ulalu.js en fait de vrais onglets (data-tabs). */
.tabs {
    display: flex;
    gap: 1.6rem;
    margin-top: 1.8rem;
    border-bottom: 1px solid var(--line);
    overflow-x: auto;
    scrollbar-width: none;
}
.tabs::-webkit-scrollbar { display: none; }
.tab {
    display: inline-flex;
    flex: none;
    align-items: center;
    gap: .5rem;
    min-height: 3rem;
    margin-bottom: -1px;
    border-bottom: 3px solid transparent;
    color: var(--ink-2);
    font-weight: 600;
    text-decoration: none;
    white-space: nowrap;
}
.tab:hover { color: var(--ink); }
.tab:focus-visible { outline: 2px solid var(--focus-line); outline-offset: -2px; border-radius: var(--r-sm); }
.tab[aria-selected="true"] { color: var(--ink); border-bottom-color: var(--ember); }
.tab__n {
    min-width: 1.6rem;
    padding: 0 .45rem;
    border-radius: 999px;
    background: var(--surface-2);
    color: var(--ink);
    font-size: var(--t-xs);
    font-weight: 650;
    text-align: center;
    font-variant-numeric: tabular-nums;
}
/* Une suppression proche : la pastille d'avertissement, et les mots à côté (même encre que « Production en cours »). */
.tab__n--warn { background: color-mix(in srgb, var(--amber) 32%, transparent); color: #7a4f03; }
.tab__soon { font-size: var(--t-xs); font-weight: 600; color: #8a5a04; }
/* Sur un téléphone, « dont 1 bientôt supprimé » ne tient plus à côté : il passe sous « Terminés » plutôt que de
   sortir de la barre, où personne ne devinerait qu'elle défile. Mesuré à 375 px. */
@media (max-width: 30rem) {
    /* Une grille, pas un flex qui revient à la ligne : sa largeur est celle de sa plus longue ligne, pas des deux bout à bout. */
    .tab { display: inline-grid; grid-template-columns: auto 1fr; justify-items: start; align-content: start; column-gap: .5rem; padding-block: .6rem .35rem; }
    .tab__soon { grid-column: 1 / -1; }
}
@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) .tab__n--warn, :root:not([data-theme="light"]) .tab__soon { color: var(--amber); }
}
:root[data-theme="dark"] .tab__n--warn, :root[data-theme="dark"] .tab__soon { color: var(--amber); }

.events-book > .events-group { margin-top: 1.4rem; scroll-margin-top: 10rem; }
@supports selector(:has(*)) {
    .events-book:not(.is-tabbed):not(:has(> .tab-panel:target)) > .tab-panel:not(:first-of-type),
    .events-book:not(.is-tabbed):has(> .tab-panel:target) > .tab-panel:not(:target) { display: none; }
    /* L'onglet nomme déjà le groupe : son titre ne reste que pour les lecteurs d'écran. */
    .events-book .events-group__title {
        position: absolute;
        width: 1px;
        height: 1px;
        margin: -1px;
        overflow: hidden;
        clip: rect(0, 0, 0, 0);
        white-space: nowrap;
    }
}

/* La prochaine étape d'un événement, en bas de sa carte. Quand c'est à
   l'organisateur d'agir, le mot est en encre forte et précédé d'un signe :
   la couleur ne porte jamais l'information seule. */
.card-next { margin-top: .5rem; font-size: var(--t-sm); color: var(--ink-2); max-width: none; }
.card-next.is-action { color: var(--ink); font-weight: 620; }
.card-next.is-action::before { content: "\25B8"; margin-right: .35rem; color: var(--ember); }

/* Statut ajouté au sprint 9, absent du système de design : « tri prêt, à
   vérifier » attend l'organisateur, comme « film prêt, à valider », et en
   reprend la teinte. En clair, l'encre est un peu plus foncée que celle de
   PreviewReady (4,3:1 à 4,5:1 selon le fond) : 5,3:1 sur papier, 5,5:1 sur
   carte, 5,0:1 sur le fond atténué ; en sombre, 5,0:1 sur carte. */
.status.ReviewReady { background: color-mix(in srgb, var(--ember) 14%, transparent); color: color-mix(in srgb, var(--ember-deep) 85%, var(--ink)); }
@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) .status.ReviewReady { color: var(--ember); }
}
:root[data-theme="dark"] .status.ReviewReady { color: var(--ember); }

/* Dépôt de fichiers : le champ reste atteignable au clavier (masqué
   visuellement plutôt que retiré du flux), et l'étiquette-bouton montre
   le focus du champ qu'elle commande. */
.drop { position: relative; }
.drop input[type=file] {
    display: block;
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}
.drop label.button:has(+ input[type=file]:focus-visible) { box-shadow: var(--focus); }

/* Statut ajouté le 2026-09-16 (D-073) : un événement « en création » dont
   l'offre est réglée attend sa description, comme « tri prêt, à vérifier »
   attend l'organisateur ; il en reprend la teinte et les contrastes. */
.status.Draft { background: color-mix(in srgb, var(--ember) 14%, transparent); color: color-mix(in srgb, var(--ember-deep) 85%, var(--ink)); }
@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) .status.Draft { color: var(--ember); }
}
:root[data-theme="dark"] .status.Draft { color: var(--ember); }

/* ---------- 11. Divers ---------- */
.center .feature-icon { margin-inline: auto; }
.cluster--center { justify-content: center; }

.tile figcaption { margin: 0; }

/* Petite intertitre de liste, au-dessus des ambiances et des étapes. */
.caption {
    margin: .5rem 0 -.1rem;
    font-size: var(--t-xs);
    font-weight: 650;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--muted-ink);
}

/* Les composants imposent leur display : sans cela, un élément marqué
   hidden par le script resterait visible. */
[hidden] { display: none !important; }

/* Cibles tactiles : 44 px sur mobile, y compris les petits boutons des vignettes et les liens du fil d'Ariane.
   C'était 40 ici alors que docs/08 annonce 44 et qu'ulalu.css pose déjà 44 sous « pointer: coarse » — ce fichier
   étant chargé après, c'est le 40 qui gagnait sur un téléphone (mesuré le 2026-09-21). Une seule valeur, celle
   qui est écrite dans le système de design. */
@media (max-width: 48rem) {
    .button, .btn, button.primary, button.secondary, button.danger { min-height: 44px; }
    .btn--sm { min-height: 44px; }
    .tile .actions button { min-height: 44px; flex: 1 1 6rem; }
    .invite .qr { width: 9.5rem; height: 9.5rem; }
}

/* ---------- 8. Repère d'étape sur les écrans secondaires ---------- */
.stepbadge {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .6rem 1rem;
    justify-content: space-between;
    padding: .6rem .9rem;
    margin-bottom: 1.4rem;
    border: 1px solid var(--line);
    border-radius: 999px;
    background: var(--surface);
}
/* Le retour est le seul chemin en arrière de ces pages : il se vise au doigt comme une commande. */
.stepbadge__back {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    color: var(--ink-2);
    text-decoration: none;
    font-size: var(--t-sm);
    font-weight: 550;
}
.stepbadge__back:hover { color: var(--ember-text); }
.stepbadge__where { display: inline-flex; align-items: center; gap: .5rem; font-size: var(--t-sm); color: var(--muted-ink); }
.stepbadge__num {
    display: grid;
    place-items: center;
    width: 1.6rem;
    height: 1.6rem;
    border-radius: 50%;
    background: var(--mirror-soft);
    color: var(--ember-deep);
    font-weight: 700;
    font-size: var(--t-xs);
    flex: none;
}
@media (max-width: 30rem) { .stepbadge { border-radius: var(--r); } }

/* ---------- Couverture de la collecte ----------
   Affiché dans l'étape « clôturer », tant que le lien est ouvert. */
.cov { margin: 1rem 0; }
.cov__title { margin: 0 0 .4rem; font-size: var(--t-lg); }
.cov__list { margin: 0; padding-left: 1.1rem; }
.cov__list li { margin: .2rem 0; }
.cov__cta { margin-top: .6rem; font-size: var(--t-sm); }

/* ---------- Facture ---------- */
/* Une page sobre, qui s'imprime telle quelle : c'est ainsi qu'on l'enregistre en PDF. */
.invoice__head { display: flex; flex-wrap: wrap; gap: 1rem; align-items: flex-start; justify-content: space-between; }
.invoice__parties { display: grid; grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr)); gap: 1.5rem; margin: 1.5rem 0; }
.invoice__parties h2 { font-size: 1rem; margin-bottom: .35rem; }
.invoice__lines { width: 100%; border-collapse: collapse; margin: 1rem 0; }
.invoice__lines th, .invoice__lines td { padding: .5rem .25rem; border-bottom: 1px solid var(--line); text-align: left; vertical-align: top; }
.invoice__lines .num { text-align: right; white-space: nowrap; }
.invoice__lines tfoot th { text-align: right; }
.invoice__due th, .invoice__due td { font-weight: 600; border-bottom: 0; }

/* ---------- Trois offres, appareil photo jetable (D-078, D-079, docs/09 § 16) ---------- */
/* Choix de l'offre : l'offre retenue en détail, les deux autres en cartes courtes qui rechargent la page. */
.plans-offer .price { margin-block: .2rem .6rem; }
/* Les trois écrans de l'achat, en tête de « Nouveau » et de « Creer ». Nommée « buy-path » comme « path » :
   « steps » appartient au site vitrine (ulalu.css) et numérote toutes les listes qu'elle touche. */
.buy-path {
    display: flex;
    flex-wrap: wrap;
    gap: .3rem 1.1rem;
    margin: 0 0 1.4rem;
    padding: 0;
    list-style: none;
    font-size: var(--t-sm);
}
.buy-path__item { display: flex; align-items: center; gap: .45rem; color: var(--muted-ink); }
.buy-path__num {
    display: grid;
    place-items: center;
    width: 1.45rem;
    height: 1.45rem;
    flex: none;
    border: 1px solid var(--line);
    border-radius: 50%;
    font-size: var(--t-xs);
    font-weight: 700;
}
.buy-path__item.is-current { color: var(--ink); font-weight: 650; }
.buy-path__item.is-current .buy-path__num { border-color: var(--ember); background: var(--ember); color: #fff; }
.buy-path__item.is-done { color: var(--ink-2); }
.buy-path__item.is-done .buy-path__num { border-color: var(--jade); color: var(--jade); }

/* Deux lignes concrètes par carte : un nom, un prix et une phrase ne disaient pas ce qu'on reçoit. */
.plans-mini .check-list { margin: .6rem 0 .2rem; }
.plans-mini .check-list li { font-size: var(--t-xs); }

.plans-others { margin-top: 2rem; }
.plans-others > h2 { font-size: var(--t-xl); margin-bottom: .2rem; }
.plans-others__grid { display: grid; gap: 0 1rem; grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr)); }
.plans-mini { display: flex; flex-direction: column; }
.plans-mini > :last-child { margin-top: auto; padding-top: .4rem; }
.plans-mini__price { font-size: var(--t-2xl); margin-block: .1rem .5rem; }

/* L'appareil : ses réglages se montrent dès que la case est cochée, sans script. Un navigateur sans :has les montre
   toujours, et le serveur ignore les réglages d'un appareil désactivé. */
.plans-camera { margin-block: 1.2rem .4rem; }
.plans-camera__switch { font-weight: 550; }
.plans-camera__settings { border: 0; padding: 0; margin: .2rem 0 0; min-inline-size: 0; }
.plans-camera:has([data-plans-camera-toggle]):not(:has([data-plans-camera-toggle]:checked)) .plans-camera__settings { display: none; }

/* Ce que l'on demande au film (D-196) : des pastilles qu'on touche d'un doigt, boutons radio pour le ton, cases pour les
   moments. La case reste posée sous sa pastille, invisible mais focalisable : le clavier et les lecteurs d'écran la
   trouvent, la pastille montre son état. */
.brief-chips { border: 0; padding: 0; margin: 1.2rem 0 .4rem; min-inline-size: 0; }
.brief-chips > legend { padding: 0; margin-bottom: .45rem; font-size: var(--t-sm); font-weight: 550; color: var(--ink); }
.brief-chips__list { display: flex; flex-wrap: wrap; gap: .45rem; }
.brief-chips label.brief-chip { position: relative; display: inline-flex; align-items: stretch; margin: 0; gap: 0; font-weight: 500; line-height: 1.2; }
.brief-chip > input[type=radio], .brief-chip > input[type=checkbox] {
    position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: pointer;
}
.brief-chip > span {
    display: inline-flex;
    align-items: center;
    min-height: 40px;
    padding: .45rem .95rem;
    border: 1px solid var(--line-strong);
    border-radius: 999px;
    background: var(--surface);
    color: var(--ink);
    font-size: var(--t-sm);
    transition: border-color .18s, background .18s;
}
.brief-chip:hover > span { border-color: var(--ember); }
.brief-chip > input:checked + span {
    border-color: var(--ember);
    background: color-mix(in srgb, var(--ember) 12%, var(--surface));
    font-weight: 600;
}
.brief-chip > input[type=checkbox]:checked + span::before { content: "✓"; margin-inline-end: .35rem; color: var(--ember-text); }
.brief-chip > input:focus-visible + span { outline: 2px solid var(--focus-line); outline-offset: 2px; }
/* Une liste de moments par type, celle du type choisi seule : avec :has sans script, sinon par la classe is-current que
   le serveur pose et que plans.js suit. La console ne rend que la liste de l'événement, sans sélecteur de type : la règle
   :has ne touche qu'un formulaire qui en a un. */
.brief-chips__list[data-brief-type]:not(.is-current) { display: none; }
@supports selector(:has(*)) {
    form:has(#type) .brief-chips__list[data-brief-type] { display: none; }
    form:has(#type option[value="wedding"]:checked) [data-brief-type="wedding"],
    form:has(#type option[value="birthday"]:checked) [data-brief-type="birthday"],
    form:has(#type option[value="birth"]:checked) [data-brief-type="birth"],
    form:has(#type option[value="festival"]:checked) [data-brief-type="festival"],
    form:has(#type option[value="family"]:checked) [data-brief-type="family"],
    form:has(#type option[value="other"]:checked) [data-brief-type="other"] { display: flex; }
}
/* Le champ d'heure n'a pas de style de base dans ulalu.css : il prend celui des autres champs. */
input[type=time] {
    width: 100%;
    padding: .72rem .9rem;
    border: 1px solid var(--line-strong);
    border-radius: var(--r);
    font: inherit;
    color: var(--ink);
    background: var(--surface);
    transition: border-color .18s, box-shadow .18s;
}
@media (max-width: 30rem) { fieldset.plans-camera { padding: .9rem .8rem; } }
.plans-looks { margin-top: 1rem; }
.plans-looks legend { padding-inline: 0; margin-bottom: .2rem; font-size: var(--t-sm); }
.plans-looks .choice label > span > * { display: block; }
.plans-reveal { margin-top: 1rem; padding-top: .9rem; border-top: 1px solid var(--line); }
.plans-roll__stats { margin-block: .4rem .2rem; }

/* Commandes et factures de l'étape de l'offre. */
.plans-orders { list-style: none; padding: 0; margin: .6rem 0 0; display: grid; gap: .5rem; }
.plans-orders li { display: flex; flex-wrap: wrap; align-items: center; gap: .3rem .8rem; padding: .55rem .75rem; border: 1px solid var(--line); border-radius: var(--r); background: var(--surface); }
.plans-orders__what { font-weight: 600; }
.plans-orders li .btn { margin-left: auto; }
.plans-upfold { margin-top: 1rem; }
.plans-upgrade__price { margin-block: .6rem; }

/* Liens nommés : chacun son QR code, tracé en SVG, sur fond blanc pour rester lisible. */
.plans-qr { display: block; margin-inline: auto; background: #fff; }
.invite + .invite { margin-top: 1.4rem; padding-top: 1.4rem; border-top: 1px solid var(--line); }
.plans-newlink + .cluster { margin-top: .9rem; }
.plans-link__label { font-size: var(--t-md); }
.plans-newlink { max-width: 34rem; }
.plans-newlink input[type=text] { flex: 1 1 14rem; width: auto; min-width: 0; }

/* ---------- Paliers (D-088, D-089, docs/09 § 18) ---------- */
/* Un palier par ligne : ce qu'il ouvre à gauche, son prix à droite ; sous 30 rem, le prix passe dessous. */
.plans-offer .price.plans-price-from { font-size: var(--t-2xl); }
.plans-tiers { margin-block: .4rem .2rem; }
.plans-tiers legend { padding-inline: 0; margin-bottom: .1rem; font-weight: 650; color: var(--ink); }
.plans-tiers > .field-help { margin: 0 0 .2rem; }
.plans-tier > label { display: flex; align-items: center; gap: .3rem .75rem; flex-wrap: wrap; cursor: pointer; }
.plans-tier input[type=radio] { flex: none; margin: 0; }
.plans-tier__what { flex: 1 1 12rem; min-width: 0; }
.plans-tier__what > * { display: block; }
.plans-tier__price { flex: none; margin-left: auto; font-weight: 650; font-variant-numeric: tabular-nums; white-space: nowrap; }
@media (max-width: 30rem) { .plans-tier__price { margin-left: 1.7rem; } }

/* Pellicules distribuées sur le palier, et la carte du palier suivant. */
.plans-guests { margin-block: .6rem .4rem; display: grid; gap: .4rem; }
.plans-guests__count { margin: 0; font-size: var(--t-md); font-variant-numeric: tabular-nums; }
.plans-guests .meter { margin: 0; }
.plans-guests.is-warn .meter i { background: var(--amber); }
.plans-guests.is-full .meter i { background: var(--danger); }
.plans-tiers-card { margin-top: 1rem; padding-top: 1rem; border-top: 1px solid var(--line); }
.plans-tiers-card > h3 { margin-top: 0; }

/* Le bandeau : ambre à 80 %, appuyé quand toutes les pellicules sont distribuées. */
.plans-guests-alert > h2 { font-size: var(--t-lg); }
.plans-guests-alert.is-full { border-width: 2px; border-color: color-mix(in srgb, var(--danger) 55%, var(--line)); background: color-mix(in srgb, var(--danger) 7%, var(--surface)); }

/* Le formulaire de contact (D-125). Le piège à robots sort de l'écran sans disparaître : un champ en display:none est
   ignoré par une partie des robots, et masqué ainsi il reste hors du parcours au clavier (tabindex) et des lecteurs
   d'écran (aria-hidden), que la page pose elle-même. */
.hp {
    position: absolute;
    left: -9999px;
    width: 1px;
    height: 1px;
    overflow: hidden;
}
.contact-pair { display: grid; gap: 0 1.2rem; }
@media (min-width: 34rem) { .contact-pair { grid-template-columns: 1fr 1fr; } }

/* Le rappel de commande des écrans de compte (D-124) : ce que le visiteur achetait quand on lui a demandé un compte. */
.buy-intent { margin-block: 1rem 1.4rem; padding: .9rem 1.1rem; }
.buy-intent .eyebrow { margin-bottom: .3rem; }
.buy-intent__offer {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: space-between;
    gap: .4rem 1rem;
    margin: 0 0 .35rem;
    font-size: var(--t-lg);
}
.buy-intent__price { font-weight: 650; font-variant-numeric: tabular-nums; white-space: nowrap; }

@media print {
    .top, .site-footer, [data-print] { display: none !important; }
    .card { border: 0; box-shadow: none; padding: 0; }
}

/* ---------- 12. Le livre d'or dans la console (docs/09 § 35, lot B) ---------- */
/*
 * Une liste, pas une frise : sur un téléphone, un message par ligne — sa photo, son prénom, sa durée —, puis de quoi
 * l'écouter ou le lire, la case « Projection » et « Masquer » à portée de pouce, le reste (couper, épingler) replié.
 * Chaque commande fait 44 px (docs/08, règle 3). La jauge de la version projection garde les mots : la couleur ne dit
 * jamais seule qu'on dépasse.
 */
.gb-nav { margin: 0 0 1.1rem; gap: 1.2rem; }
.gb-nav .tab[aria-current] { color: var(--ink); border-bottom-color: var(--ember); }

.gb-summary .lead { margin-bottom: .35rem; }
.gb-summary > .muted { margin: 0 0 .6rem; }
.gb-summary > :last-child { margin-bottom: 0; }

.gb-gauge { display: flex; flex-wrap: wrap; align-items: baseline; gap: .2rem .8rem; margin: 0 0 .3rem; }
.gb-gauge strong { font-size: var(--t-lg); font-variant-numeric: tabular-nums; }
.gb-meter { height: 8px; }
.gb-meter.is-over i { background: var(--danger); }
.gb-screening__form { margin-top: .6rem; }
.gb-screening__form .error:empty { display: none; }

.gb-list { list-style: none; margin: .4rem 0 0; padding: 0; display: grid; }
.gb-item { padding-block: .95rem; border-top: 1px solid var(--line); scroll-margin-top: 5rem; min-width: 0; }
.gb-item:first-child { border-top: 0; padding-top: .3rem; }
.gb-item.is-hidden { color: var(--ink-2); }
.gb-item.is-hidden .gb-item__photo { opacity: .6; }

.gb-item__head { display: grid; grid-template-columns: 3.5rem minmax(0, 1fr) auto; gap: .75rem; align-items: center; }
/* Une photo qui ne se charge pas garde sa case, sans répandre son texte de remplacement sur le prénom. */
.gb-item__photo {
    display: block;
    width: 3.5rem;
    height: 3.5rem;
    overflow: hidden;
    border-radius: var(--r-sm);
    object-fit: cover;
    background: var(--surface-2);
    color: transparent;
    font-size: 0;
}
.gb-item__who { min-width: 0; }
.gb-item__name { margin: 0; font-weight: 650; color: var(--ink); overflow-wrap: anywhere; }
.gb-item__meta { margin: .1rem 0 0; font-size: var(--t-xs); color: var(--muted-ink); }
.gb-item__pin { justify-self: end; white-space: nowrap; }

/* Le mot d'un invité, tel qu'il l'a écrit : ses retours à la ligne gardés, jamais interprétés. */
.gb-item__text {
    margin: .7rem 0 0;
    padding-left: .9rem;
    border-left: 3px solid var(--line-strong);
    white-space: pre-line;
    overflow-wrap: anywhere;
}
.gb-item__player { display: block; width: 100%; margin-top: .7rem; }
video.gb-item__player { max-height: 60vh; background: #000; border-radius: var(--r-sm); }
.gb-item__cut { margin: .4rem 0 0; font-size: var(--t-xs); color: var(--ink-2); }

.gb-item__actions { display: flex; flex-wrap: wrap; align-items: center; gap: .4rem 1rem; margin-top: .6rem; }
.gb-item__actions > form { margin: 0; }
label.gb-item__screen { display: inline-flex; align-items: center; gap: .55rem; min-height: 44px; margin: 0; font-weight: 600; }
.gb-item__screen input { margin: 0; }

.gb-item__more { margin-top: .2rem; }
.gb-item__more > summary {
    display: flex;
    align-items: center;
    gap: .5rem;
    min-height: 44px;
    cursor: pointer;
    list-style: none;
    font-size: var(--t-sm);
    font-weight: 600;
    color: var(--ink-2);
}
.gb-item__more > summary::-webkit-details-marker { display: none; }
/* Le même signe que les replis de la console : ce qui s'ouvre se voit. */
.gb-item__more > summary::after { content: "+"; color: var(--ember-text); font-size: 1.1rem; line-height: 1; }
.gb-item__more[open] > summary::after { content: "\2212"; }
.gb-item__more > summary:hover { color: var(--ember-text); }
.gb-item__more > summary:focus-visible { outline: 2px solid var(--focus-line); outline-offset: 2px; border-radius: var(--r-sm); }
.gb-item__tools { display: grid; gap: .9rem; padding: .2rem 0 .3rem; }
.gb-cut { margin: 0; }
.gb-cut__fields { border: 0; padding: 0; margin: 0; min-inline-size: 0; }
.gb-cut__fields legend { padding: 0; font-size: var(--t-sm); }
.gb-cut__preview { margin: .6rem 0; }
.gb-pin { display: flex; flex-wrap: wrap; gap: .5rem; }
.gb-pin > form { margin: 0; }

.gb-hidden { margin-top: 1.4rem; }

.gb-render__state { font-weight: 600; margin: 0 0 .5rem; }
.gb-create { margin-top: 1.2rem; }
.gb-create .choices { margin-top: .4rem; }

/* ---------- L'achat sans compte (D-187) ----------
   Sur téléphone, dans l'ordre où l'on s'engage (2026-10-05) : le titre et le prix, les champs, ce qu'on achète, les
   cases et le bouton, puis les trois temps qui suivent. Le résumé passait avant le formulaire : le premier champ était
   à 1 140 px du haut d'un téléphone. Sur un écran large, les champs et le bouton à gauche, le résumé et la suite à
   droite, qui restent en vue. Le formulaire est la grille ; .checkout__aside ne fait boîte que sur un écran large. */
.checkout {
    display: grid;
    gap: 1rem;
    width: min(100%, 60rem);
    margin-inline: auto;
}
.checkout__head h1 { margin-bottom: .3rem; }
.checkout__head .intro-price { margin-bottom: .6rem; }
.checkout__notes:empty { display: none; }
.checkout__notes .note { margin: 0; }
.checkout__notes .note + .note { margin-top: .6rem; }
.checkout__body { display: grid; gap: 1rem; }
.checkout__aside { display: contents; }
.checkout__fields { order: 1; margin-block: 0; }
.checkout__summary { order: 2; margin-block: 0; }
.checkout__confirm { order: 3; margin-block: 0; }
.checkout__next { order: 4; padding-inline: .2rem; }
.checkout__offer { margin: 0 0 .3rem; font-size: var(--t-xl); }
.checkout__price { margin: 0 0 .5rem; font-weight: 650; }
/* Un intertitre en caractères d'interface : la police de titre, à cette taille, se lit mal. */
.checkout__next-title { margin: 0 0 .4rem; font-family: var(--font-ui); font-size: var(--t-sm); font-weight: 650; color: var(--ink); }
.checkout__steps { margin: 0; padding-left: 1.3rem; display: grid; gap: .35rem; font-size: var(--t-sm); color: var(--ink-2); }
.checkout__consent { display: flex; gap: .55rem; align-items: flex-start; font-weight: 400; }
.checkout__consent input { flex: none; margin-top: .25rem; }
.checkout__actions { display: grid; gap: .6rem; }
@media (min-width: 56rem) {
    /* La seconde rangée prend ce qui reste : le résumé, plus haut que les champs, ne les écarte pas du bouton. */
    .checkout__body {
        grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
        grid-template-rows: auto 1fr;
        align-items: start;
        column-gap: 1.6rem;
    }
    .checkout__fields { grid-column: 1; grid-row: 1; }
    .checkout__confirm { grid-column: 1; grid-row: 2; }
    .checkout__aside { display: grid; gap: 1rem; align-content: start; grid-column: 2; grid-row: 1 / span 2; }
}

/* La page de retour et la correction d'une adresse (D-187) : une carte, et le lien de renvoi sous sa phrase. */
.checkout-return__resend { margin-top: 1rem; }
.checkout-return__address { font-weight: 650; overflow-wrap: anywhere; }
