/*
-- LAYOUT
-- CONTENT
-- FORMS
-- COMPONENTS
-- TOPBAR
-- SIDEBAR
-- SPECIFIC CONTENT
-- UTILITIES
*/

/*
 * Pont Bootstrap ↔ design system : les variables ci-dessous consomment les
 * tokens --sp-* de tokens.css, dérivés de designsystem/spicto/.
 */
:root {
    /* Fond de page : bg.default (#FAF9F5) sous 992px, bg.cream (#F5F3EB) au-dessus
       (cf. le bloc @media après ce :root). */
    --bs-body-bg: var(--sp-color-bg-default);
    /* Échelle typo DS en px, la racine rem reste à 14px (--font-size-root) :
       les espacements rem ne bougent pas. */
    --bs-body-font-size: var(--sp-font-size-body);
    --bs-body-font-weight: var(--sp-font-weight-body);
    --bs-body-line-height: var(--sp-font-leading-normal);
    --bs-heading-color: var(--sp-color-text-default);
    /* BROWN_BODER_LIGHT : le filet entre deux transactions (retour client d'octobre) */
    --sp-color-brown-border-light: #EEE9DD;
    --font-size-xxs: 5px;   /* hors échelle DS, conservé (phase 5) */
    --font-size-xs: 10px;   /* hors échelle DS, conservé (phase 5) */
    --font-size-s: var(--sp-font-size-12);
    --font-size-lg: var(--sp-font-size-16);

    --contrast-font-family: var(--sp-font-family-label);
    --bs-body-font-family: var(--sp-font-family-base);
    --heading-font-family: var(--sp-font-family-base);
    --font-size-root: 14px;
    --text-muted: var(--sp-color-text-muted);
    --text-muted-rgb: var(--sp-color-grey-600-rgb);

    --bs-primary: var(--sp-color-action-primary);
    --bs-primary-rgb: var(--sp-color-ink-800-rgb);
    --bs-secondary: var(--sp-color-grey-300);
    --bs-success: var(--sp-color-feedback-success);
    --bs-success-rgb: var(--sp-color-green-700-rgb);
    --bs-danger: var(--sp-color-feedback-danger);
    --bs-danger-rgb: var(--sp-color-red-600-rgb);
    --bs-light-bg-subtle: var(--sp-color-bg-grey);
    /* Sans ces deux-là, `text-dark` et `bg-light` servent #212529 / #f8f9fa :
       deux gris froids hors palette, à côté de l'ink des textes voisins. */
    --bs-dark: var(--sp-color-text-default);
    --bs-dark-rgb: var(--sp-color-ink-800-rgb);
    --bs-light: var(--sp-color-bg-grey);
    --bs-light-rgb: var(--sp-color-grey-100-rgb);

    /* Le texte courant : sans ce remap, Bootstrap sert son #212529 froid,
       à côté de l'ink que portent les titres tokenisés. */
    --bs-body-color: var(--sp-color-text-default);
    --bs-body-color-rgb: var(--sp-color-ink-800-rgb);

    --bs-link-color: var(--sp-color-text-default);
    --bs-link-color-rgb: var(--sp-color-ink-800-rgb);
    --bs-link-hover-color: var(--sp-color-text-brown);
    --bs-link-hover-color-rgb: var(--sp-color-brown-700-rgb);

    --danger: var(--sp-color-feedback-danger);
    --danger-light: color-mix(in srgb, var(--sp-color-feedback-danger) 14%, transparent);
    --warning: var(--sp-color-feedback-warning);
    --warning-light: color-mix(in srgb, var(--sp-color-feedback-warning) 12%, var(--sp-color-cream-0));
    --success: var(--sp-color-feedback-success);
    --success-light: color-mix(in srgb, var(--sp-color-feedback-success) 10%, var(--sp-color-cream-0));
    /* Le bleu d'aplat ne porte jamais de texte : ces deux-là en sont la version écrite. */
    --info: var(--sp-color-feedback-info-text);
    --info-light: color-mix(in srgb, var(--sp-color-feedback-info) 10%, var(--sp-color-cream-0));
    --light: var(--sp-color-bg-grey);
    --dark-grey: var(--sp-color-text-default);

    --bs-border-radius-sm: var(--sp-radius-xs);
    --bs-border-radius: var(--sp-radius-sm);
    /* Rayon des surfaces de saisie : 8px par défaut, 12px dans l'espace connecté
       (fiche input). Défini une fois, consommé par toutes ces surfaces. */
    --field-radius: var(--sp-radius-sm);
    --bs-border-color: var(--sp-color-border-default);
    /* Fond des champs désactivés / en lecture seule (l'Organisateur verrouillé d'un club) : sans
       ce remap, le #E9ECEF froid de Bootstrap. */
    --bs-secondary-bg: var(--sp-color-bg-grey);

    /* Calendar (fiche calendar) : la sélection se lit à l'orange, la plage en pêche.
       primary = accent.selected (cercle début/fin), non action.primary qui est l'ink.
       secondary reste le filet chaud des bordures ; range porte la bande de plage. */
    --flatpickr-primary: var(--sp-color-accent-selected);
    --flatpickr-secondary: var(--sp-color-border-cream);
    --flatpickr-range: var(--sp-color-accent-soft);
    --flatpickr-on-primary: var(--sp-color-text-inverse);
    --flatpickr-on-range: var(--sp-color-text-default);
}

/* Le fond de page change de crème avec la largeur (DESIGN, « Le fond de page change de crème
   avec la largeur » ; DESIGNAPP, « Le fond de page de l'app suit la règle du tronc »).
   Sous 992px la page EST la feuille : bg.default, le crème le plus clair, ne teinte pas ce
   qu'on lit. À partir de 992px — le seuil où col-lg-* passe à deux colonnes, donc où du vide
   apparaît autour des colonnes — la page devient un SOL : bg.cream rend au blanc des cartes
   son statut de surface (1,05:1 → 1,11:1).
   Conséquence assumée : bg.default cesse d'être « le fond de page » tout court, c'est la
   surface claire posée dessus dès qu'on est en deux colonnes. Les blocs qui le portent
   (récapitulatif d'étape repliée, aperçu sous la carte) ne bougent pas — c'est la page qui
   bouge sous eux. */
@media (min-width: 992px) {
    :root {
        --bs-body-bg: var(--sp-color-bg-cream);
    }
}

/*
 * Fond de page crème (bg.default) mais surfaces blanches (bg.surface) : Bootstrap
 * fait dériver le fond des champs, cartes, modales… de --bs-body-bg ; on rétablit
 * ici le blanc plein voulu par le DS pour chaque surface.
 */
.form-control,
.form-control:focus,
.form-select {
    background-color: var(--sp-color-bg-surface);
}

.form-floating > .form-control:focus ~ label::after,
.form-floating > .form-control:not(:placeholder-shown) ~ label::after,
.form-floating > .form-select ~ label::after {
    background-color: var(--sp-color-bg-surface);
}

.form-check-input {
    --bs-form-check-bg: var(--sp-color-bg-surface);
}

/* Base de la carte : gouttière space.6, rayon lg, fond blanc — les valeurs de la fiche card.
   ELLE DOIT RESTER AVANT LES VARIANTS (.card-section, .card-nested, .card-dark…). Ces variants
   redéclarent les mêmes variables --bs-card-* à spécificité égale : posée APRÈS eux, cette base
   les écrasait silencieusement — l'ombre de .card-section et le rayon de .card-nested étaient
   inertes, règles valides et jamais appliquées. Ne pas redéclarer .card plus bas dans ce
   fichier : c'est ainsi que le défaut est né. */
.card {
    --bs-card-spacer-y: var(--sp-space-6);
    --bs-card-spacer-x: var(--sp-space-6);
    --bs-card-bg: var(--sp-color-bg-surface);
    --bs-card-border-width: 0;
    --bs-card-border-radius: var(--sp-radius-lg);
    --bs-card-box-shadow: var(--sp-shadow-none);
    box-shadow: var(--bs-card-box-shadow);
    /* Filet chaud, pas le noir translucide de Bootstrap : « pas de gris froid » vaut aussi pour
       les bordures (DESIGN). Il ne s'affiche que là où la carte porte .border — l'ombre OU le
       filet, jamais les deux (fiche card). */
    --bs-card-border-color: var(--sp-color-border-default);
}

/* Crème, pas blanc (fiche dialog) : une modale porte des champs, et un champ blanc sur du
   blanc n'a plus que son filet pour exister. C'est aussi une page entière sur mobile. */
.modal {
    --bs-modal-bg: var(--sp-color-bg-default);
}

.offcanvas {
    --bs-offcanvas-bg: var(--sp-color-bg-surface);
}

.dropdown-menu {
    --bs-dropdown-bg: var(--sp-color-bg-surface);
}

.accordion {
    --bs-accordion-bg: var(--sp-color-bg-surface);
}

.list-group {
    --bs-list-group-bg: var(--sp-color-bg-surface);
}

.popover {
    --bs-popover-bg: var(--sp-color-bg-surface);
}

.pagination {
    --bs-pagination-bg: var(--sp-color-bg-surface);
}

/* LAYOUT */

.site-banner a {
    color: inherit;
    text-decoration: underline;
}

.container,
.container-fluid,
.container-lg {
    --bs-gutter-x: 2.5rem;
}

/* container custom */

@media (min-width: 1400px) {
    .container.container-custom {
        max-width: 1215px;
    }
}

/* CONTENT */

/* Les utilitaires d'espacement de Bootstrap se calculent en rem sur une racine
   à 14px (héritée de la migration) : ils rendent 3,5 / 7 / 14 / 21 / 42px, alors
   que la maquette est dessinée sur la grille du DS. On les recale sur les valeurs
   que Bootstrap vise lui-même à 16px, qui y tombent toutes. */
.g-2{ --bs-gutter-x: 8px !important; --bs-gutter-y: 8px !important; }
.g-3{ --bs-gutter-x: 16px !important; --bs-gutter-y: 16px !important; }
.g-4{ --bs-gutter-x: 24px !important; --bs-gutter-y: 24px !important; }
.gap-1{ gap: 4px !important; }
.gap-2{ gap: 8px !important; }
.gap-3{ gap: 16px !important; }
.gap-4{ gap: 24px !important; }
.m-1{ margin: 4px !important; }
.mb-1{ margin-bottom: 4px !important; }
.mb-2{ margin-bottom: 8px !important; }
.mb-3{ margin-bottom: 16px !important; }
.mb-4{ margin-bottom: 24px !important; }
.mb-5{ margin-bottom: 48px !important; }
.me-1{ margin-right: 4px !important; }
.me-2{ margin-right: 8px !important; }
.ms-1{ margin-left: 4px !important; }
.ms-2{ margin-left: 8px !important; }
.ms-3{ margin-left: 16px !important; }
.ms-4{ margin-left: 24px !important; }
.mt-1{ margin-top: 4px !important; }
.mt-2{ margin-top: 8px !important; }
.mt-3{ margin-top: 16px !important; }
.mt-4{ margin-top: 24px !important; }
.mt-5{ margin-top: 48px !important; }
.mx-4{ margin-right: 24px !important; margin-left: 24px !important; }
.my-2{ margin-top: 8px !important; margin-bottom: 8px !important; }
.my-3{ margin-top: 16px !important; margin-bottom: 16px !important; }
.my-4{ margin-top: 24px !important; margin-bottom: 24px !important; }
.my-5{ margin-top: 48px !important; margin-bottom: 48px !important; }
.p-2{ padding: 8px !important; }
.p-3{ padding: 16px !important; }
.p-4{ padding: 24px !important; }
.ps-3{ padding-left: 16px !important; }
.pt-4{ padding-top: 24px !important; }
.py-1{ padding-top: 4px !important; padding-bottom: 4px !important; }
.py-3{ padding-top: 16px !important; padding-bottom: 16px !important; }
.py-4{ padding-top: 24px !important; padding-bottom: 24px !important; }
.py-5{ padding-top: 48px !important; padding-bottom: 48px !important; }

/* Les variantes responsives, dans des media queries posées APRÈS les règles de base : chargées
   après Bootstrap, celles-ci battent à égalité ses propres variantes — `mb-4 mb-lg-0` gardait
   ses 24px en desktop, `my-3 my-xl-auto` ses 16px. Toutes celles qu'emploient les gabarits sont
   donc redéclarées ici, même quand leur valeur ne change pas (0, auto). */
@media (min-width: 576px) {
    .gx-sm-4{ --bs-gutter-x: 24px !important; }
    .my-sm-4{ margin-top: 24px !important; margin-bottom: 24px !important; }
    .my-sm-auto{ margin-top: auto !important; margin-bottom: auto !important; }
    .px-sm-4{ padding-right: 24px !important; padding-left: 24px !important; }
}

@media (min-width: 992px) {
    .mb-lg-0{ margin-bottom: 0 !important; }
    .ms-lg-auto{ margin-left: auto !important; }
    .mt-lg-0{ margin-top: 0 !important; }
    .py-lg-4{ padding-top: 24px !important; padding-bottom: 24px !important; }
}

@media (min-width: 1200px) {
    .mx-xl-auto{ margin-right: auto !important; margin-left: auto !important; }
    .my-xl-auto{ margin-top: auto !important; margin-bottom: auto !important; }
}

/* Même cause pour la gouttière de grille : 21px donnait des colonnes à 10,5px. */
.row{ --bs-gutter-x: 24px; }

/* … sans écraser une grille sans gouttière : chargée après Bootstrap, la règle ci-dessus battait
   `.gx-0` à spécificité égale, et la rangée débordait de 12px de l'écran (connexion, contact,
   onboarding sous 576px, où le conteneur n'a pas de marge). Les `gx-sm-4` qui suivent ces
   rangées gardent leur !important et reprennent la main dès 576px. */
.row.gx-0{ --bs-gutter-x: 0; }

/* Typo */

html{
    font-size: var(--font-size-root);
    /* La place de la barre de défilement est toujours réservée : sans elle, burger et panier
       glissaient de 15px entre une page qui défile et une page qui ne défile pas (DESIGNAPP) */
    scrollbar-gutter: stable;
}

/* Bootstrap compense la barre qu'il retire en verrouillant le défilement (menu, modale) ; la
   place étant déjà réservée, cette compensation décalerait la page de 15px à l'ouverture */
body[style*="overflow: hidden"]{
    padding-right: 0 !important;
}

/* L'interlettrage suit la taille (DESIGN.md, Typography). Le corps et les libellés de 14 à 16px
   sont serrés d'office ; les titres de 20px et plus, les méta de 12 et 13px portent le leur. */
body {
    font-family: var(--sp-font-family-sans);
    font-size: var(--sp-font-size-body);
    letter-spacing: var(--sp-font-tracking-tight);
}

h1, .h1, h2, .h2, h3, .h3, h4, .h4, h5, .h5, h6, .h6 {
    font-family: var(--sp-font-family-sans);
    font-weight: var(--sp-font-weight-title);
    letter-spacing: var(--sp-font-tracking-tighter);
}

h4, .h4, h5, .h5, h6, .h6 {
    letter-spacing: var(--sp-font-tracking-tight);
}

h1, .h1{
    font-size: var(--sp-font-size-h1);
}

/* Un champ, un bouton, une liste n'héritent pas de l'interlettrage de la page : ils repartent
   à zéro, et le texte qu'ils portent se desserre sans raison. */
button, input, select, textarea, optgroup{
    letter-spacing: inherit;
}

/* La petite taille de Bootstrap (.875em) tombait hors de l'échelle : 13,125px */
small, .small{
    font-size: var(--sp-font-size-meta);
    letter-spacing: var(--sp-font-tracking-meta);
}

/* Registre dense des espaces pro : cran h2 de l'échelle DS pour le titre de page.
   Ce repli de layout ne vaut QUE pour les h1 qui n'ont pas déjà leur règle de titre : un
   `.page-title` porte la sienne (plus bas), et ce sélecteur, plus spécifique, la couvrait —
   l'écran des paramètres affichait donc 28px là où le DS demande h2.dense (24px). */
.photographer-layout h1:not(.page-title),
.club-layout h1:not(.page-title){
    font-size: var(--sp-font-size-h2);
    margin-bottom: 24px;
}

/* L'accroche porte sa graisse elle-même : c'est la CLASSE qui dit le rôle. Posée sur un `p` —
   la page de connexion a déjà son `h1` ailleurs —, elle retombait sinon sur la graisse de corps,
   500 au lieu du semibold que la maquette lui donne. */
.h1-xl{
    font-size: var(--sp-font-size-h1);
    font-weight: var(--sp-font-weight-title);
    line-height: 48px;
}

h2, .h2{
    font-size: var(--sp-font-size-h2);
}

h3, .h3{
    font-size: var(--sp-font-size-h3);
}

.photographer-layout h3,
.club-layout h3,
.photographer-layout .h3,
.club-layout .h3{
    margin-bottom: 16px;
}

/* Parcours de dépôt sur desktop (DESIGNAPP, « Cotes du parcours de dépôt ») : contenu 1130,
   colonnes de 454 / 628 à 48px. Le partage reste celui de la grille ; c'est la gouttière qui
   change. Les largeurs comptent la gouttière de la rangée (1130 + 48). */
/* La création d'évènement (Figma CREATE_EVENT) a la même grille, colonnes inversées : le
   formulaire (628) à gauche, l'aperçu (454) à droite. Elle ne reprend que la grille — les
   règles `.tunnel-grid` de la carte d'évènement ne valent pas pour son aperçu. */
@media (min-width: 992px) {
    /* !important : l'utilitaire `.g-4` posé sur la rangée l'est aussi (recalage des espacements) ;
       sans lui, la gouttière retombait à 24px et les deux colonnes s'élargissaient d'autant. */
    .tunnel-grid,
    .create-grid{
        --bs-gutter-x: 48px !important;
    }

    .tunnel-grid > .col-lg-5,
    .create-grid > .col-lg-5{ width: calc(502 / 1178 * 100%); }
    .tunnel-grid > .col-lg-7,
    .create-grid > .col-lg-7{ width: calc(676 / 1178 * 100%); }

    /* Création et modification d'évènement : gouttière divisée par deux (retour client d'octobre). */
    .create-grid{
        --bs-gutter-x: 24px !important;
    }

    .create-grid > .col-lg-5{ width: calc(490 / 1154 * 100%); }
    .create-grid > .col-lg-7{ width: calc(664 / 1154 * 100%); }
}

@media (min-width: 1200px) {
    .tunnel-shell{
        max-width: calc(var(--sp-layout-content-tunnel) + var(--bs-gutter-x));
    }
}

/* Tableau de bord sur grand écran (DESIGNAPP, maquette DASHBOARD) : 1280px, colonnes de
   394 / 320 / 518 à space.6. Les largeurs comptent la gouttière de la rangée (1280 + 24). */
@media (min-width: 1400px) {
    #photographer-dashboard,
    #club-dashboard{
        max-width: calc(var(--sp-layout-content-wide) + var(--bs-gutter-x));
    }

    .dashboard-grid{
        --bs-gutter-x: var(--sp-space-6);
        --bs-gutter-y: var(--sp-space-6);
    }

    .dashboard-grid > .col-lg-4:nth-child(1){ width: calc(418 / 1304 * 100%); }
    .dashboard-grid > .col-lg-4:nth-child(2){ width: calc(344 / 1304 * 100%); }
    .dashboard-grid > .col-lg-4:nth-child(3){ width: calc(542 / 1304 * 100%); }

    .dashboard-grid > .col-lg-4 > .mb-4{
        margin-bottom: var(--sp-space-6) !important;
    }
}

/* Les quatre chiffres de « Mes photos » (maquette DASHBOARD) : grille 2x2 à 16px, valeur en
   20/24 — la taille du titre de la carte, pas celle d'un display. Un chiffre de rapport se
   compare à ses trois voisins, il n'a pas à crier plus fort que ce qu'il nomme. */
.stat-grid{
    --bs-gutter-x: var(--sp-space-4);
    --bs-gutter-y: var(--sp-space-4);
}

.stat-grid .stat-block-value{
    font-size: var(--sp-font-size-h3);
    line-height: 24px;
}

.stat-grid .stat-block-label{
    line-height: 16px;
}

/* Le PIED D'UN BLOC (DESIGNAPP, « Le pied d'un bloc est un bandeau, pas un bouton ») : 35px,
   creux crème, libellé centré en 15/18 semibold. Il ferme la lecture de ce qui est au-dessus —
   une carte du tableau de bord, une journée de la frise — sans lui disputer l'attention. Le
   crème clair du bouton neutre ordinaire, posé sur du blanc, ne se voyait pas assez pour qu'on
   le prenne pour une action. */
#photographer-dashboard .card-section .btn-neutral,
#club-dashboard .card-section .btn-neutral,
.btn-neutral.timeline-more{   /* les deux classes : `.btn-neutral` est déclaré plus bas */
    --bs-btn-bg: var(--sp-color-bg-sunken);
    --bs-btn-border-color: var(--sp-color-bg-sunken);
    --bs-btn-hover-bg: var(--sp-color-bg-sunken-strong);
    --bs-btn-hover-border-color: var(--sp-color-bg-sunken-strong);
    /* Une hauteur imposée ne centre rien : sans cette boîte flex, le libellé se pose sur la
       première ligne et laisse le vide sous lui. C'est la même construction que `.btn-tunnel`. */
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 35px;
    padding-top: 0;
    padding-bottom: 0;
    border-radius: var(--sp-radius-md);
    font-size: var(--sp-font-size-body);
    font-weight: var(--sp-font-weight-title);
    line-height: 18px;
}

/* Sur la carte Blog, crème elle-même, le bouton passe au blanc (retour client) : en crème il
   disparaissait dans sa carte. */
#photographer-dashboard .card-section.card-sunken .btn-neutral,
#club-dashboard .card-section.card-sunken .btn-neutral{
    --bs-btn-bg: #FFFFFF;
    --bs-btn-border-color: #FFFFFF;
    --bs-btn-hover-bg: #FFFFFF;
    --bs-btn-hover-border-color: #FFFFFF;
}

#photographer-dashboard h3,
#club-dashboard h3,
#photographer-dashboard .h3,
#club-dashboard .h3{
    font-size: var(--sp-font-size-h3);
    margin-bottom: 16px;
}

h4, .h4, h5, .h5{
    font-size: var(--sp-font-size-h4);
}

h6, .h6{
    font-size: var(--sp-font-size-label);
}

/* La phrase qui suit l'accroche d'une page d'entrée */
.lead-xl{
    font-size: var(--sp-font-size-24);
    font-weight: var(--sp-font-weight-prose);
    line-height: 29px;
    letter-spacing: var(--sp-font-tracking-tighter);
}

.text-muted {
    color: var(--text-muted)!important;
}

.text-muted a{
    --bs-link-color-rgb: var(--text-muted-rgb);
}

sup{
    font-size: .4em;
    top: -1em;
}

/* `family.label` (Anuphan) est un choix de FONTE, rien de plus : il n'emporte ni capitales ni
   interlettrage ouvert (DESIGN.md, Typography). Un style nommé « label » accumule sinon ce
   qu'on associe machinalement à l'idée d'étiquette — uppercase, un demi-pixel de tracking —
   puis se pose sur des phrases entières. La casse suit la règle générale, et le seul
   interlettrage du système est tracking.tight, sur les titres et les boutons. */
.label-text{
    font-size: var(--sp-font-size-label);
    font-family: var(--sp-font-family-label);
    font-weight: var(--sp-font-weight-body);
}

@media screen and (min-width: 992px) {
    /* L'accroche d'une page d'entrée et sa phrase (DESIGN.md, size.pitch). Le sélecteur ne
       demande PAS la balise : sur la page de connexion l'accroche est un `p`, l'écran ayant
       déjà son `h1` ailleurs — elle y restait à 40px pendant que l'onboarding, lui, montait
       bien à 64. La classe dit le rôle, la balise dit la structure du document. */
    .h1-xl,
    h1.h1-xl,
    .h1.h1-xl{
        font-size: var(--sp-font-size-pitch);
        line-height: 77px;
        letter-spacing: var(--sp-font-tracking-pitch);
    }

    .lead-xl{
        font-size: var(--sp-font-size-pitch-phrase);
        line-height: 39px;
    }

    h1, .h1{
        margin-bottom: 24px;
    }

    h2, .h2{
        font-size: var(--sp-font-size-h2-dense);
    }
}

a:hover {
    text-decoration: none;
}

hr {
    color: var(--sp-color-border-default);
}

/* TABLES */

th{
    font-weight: 400;
    color: var(--bs-secondary-color)!important;
}

.table>:not(caption)>*>* {
    padding: 1rem 1.25rem;
}

table tbody > tr:last-child > td {
    border-bottom: none;
}

/* FORMS */

/* Form Control */

.form-control,.form-select {
    padding: 8px 12px;
}

.input-group-text {
    background-color: var(--light);
    border-color: var(--sp-color-border-cream);
    border-right: none;
}

.input-group-text + .form-control{
    border-left: none;
}

/* Interligne de l'UI, pas celui de la prose : sans ça ils héritent de leading.normal. */
.form-label{ line-height: 18px; }
.offcanvas-footer small{ line-height: 16px; }

/* Champ plat : filet chaud au repos, bordure orange + anneau de focus (DS input/select) */
.form-control:focus, .form-select:focus {
    border-color: var(--sp-color-border-focus);
    box-shadow: var(--sp-shadow-ring);
}

.input-group .form-select:focus{
    border-color: var(--sp-color-border-cream);
}

.form-control,
.form-select{
    --bs-border-color: var(--sp-color-border-cream);
    --bs-body-color: var(--sp-color-text-default);
    border: 1px solid var(--bs-border-color);
    color: var(--bs-body-color);
    border-radius: var(--sp-radius-sm);
}

/* Tom Select peint son propre #343a40 et sa feuille passe après la nôtre :
   il faut un sélecteur plus spécifique, pas seulement plus tardif. */
.ts-wrapper .ts-control,
.ts-wrapper .ts-control input,
.ts-wrapper .ts-dropdown,
.ts-wrapper .clear-button {
    color: var(--sp-color-text-default);
}

.focus .ts-control {
    box-shadow: none!important;
}

::-webkit-input-placeholder { color: var(--sp-color-text-muted) } /* Chrome, Safari, Edge */
:-ms-input-placeholder { color: var(--sp-color-text-muted) }      /* Internet Explorer 10-11 */
::placeholder { color: var(--sp-color-text-muted) }

.form-floating > label {
    color: var(--sp-color-text-muted);
}

.form-floating>.form-control:focus~label:after,
.form-floating>.form-control:not(:placeholder-shown)~label:after,
.form-floating>.form-select~label:after {
    content: normal;
}

/* La règle ci-dessus, plus spécifique, effaçait l'astérisque d'un champ requis dès qu'il était
   rempli ou focalisé ; la maquette le garde (« Adresse * » rempli). */
.form-floating>.form-control:focus~label.required:not(.form-check-label):not(:has(.required-mark)):after,
.form-floating>.form-control:not(:placeholder-shown)~label.required:not(.form-check-label):not(:has(.required-mark)):after {
    content: "*";
}

/* Le champ autorempli reprend la surface d'un champ — bg.surface, le blanc plein —, pas le fond
   de la page : c'est la même restauration que .form-control plus haut. Il lisait --bs-body-bg,
   qui n'est plus une seule teinte depuis que la page passe au crème à 992px ; un champ autorempli
   y serait devenu crème sur desktop, et il était déjà crème au lieu de blanc sur mobile. */
input:-internal-autofill-selected {
    background-color: var(--sp-color-bg-surface) !important;
}

input:-webkit-autofill,
input:-webkit-autofill:hover,
input:-webkit-autofill:focus,
input:-webkit-autofill:active {
    -webkit-box-shadow: 0 0 0 1000px var(--sp-color-bg-surface) inset !important;
    box-shadow: 0 0 0 1000px var(--sp-color-bg-surface) inset !important;
    -webkit-text-fill-color: var(--sp-color-text-default) !important;
    caret-color: var(--sp-color-text-default);
}

.input-group .form-select{
    background-color: var(--light);
    padding: 7px 34px 7px 12px;
}

/* Prevent iOS zoom on input focus (requires font-size >= 16px) */
@media (max-width: 767px) {
    .form-control,
    .form-select,
    .ts-control input {
        font-size: 16px !important;
    }
}

/* Datepicker - Flatpickr Override */

.flatpickr-calendar {
    -webkit-box-shadow: 1px 0 0 var(--flatpickr-secondary), -1px 0 0 var(--flatpickr-secondary), 0 1px 0 var(--flatpickr-secondary), 0 -1px 0 var(--flatpickr-secondary), 0 3px 13px rgba(0,0,0,0.08)!important;
    box-shadow: 1px 0 0 var(--flatpickr-secondary), -1px 0 0 var(--flatpickr-secondary), 0 1px 0 var(--flatpickr-secondary), 0 -1px 0 var(--flatpickr-secondary), 0 3px 13px rgba(0,0,0,0.08)!important;
}

.flatpickr-calendar.multiMonth .flatpickr-days .dayContainer:nth-child(n+2) .flatpickr-day.inRange:nth-child(7n+1) {
    -webkit-box-shadow: -2px 0 0 var(--flatpickr-secondary), 5px 0 0 var(--flatpickr-secondary)!important;
    box-shadow: -2px 0 0 var(--flatpickr-secondary), 5px 0 0 var(--flatpickr-secondary)!important;
}

.flatpickr-calendar.hasTime .flatpickr-time {
    border-top: 1px solid var(--flatpickr-secondary)!important;
}

.flatpickr-calendar.arrowTop:before {
    border-bottom-color: var(--flatpickr-secondary)!important;
}

.flatpickr-calendar.arrowBottom:before {
    border-top-color: var(--flatpickr-secondary)!important;
}

.dayContainer + .dayContainer {
    -webkit-box-shadow: -1px 0 0 var(--flatpickr-secondary)!important;
    box-shadow: -1px 0 0 var(--flatpickr-secondary)!important;
}

/* Jours entre début et fin : bande pêche, texte ink (fiche calendar) */
.flatpickr-day.inRange,
.flatpickr-day.prevMonthDay.inRange,
.flatpickr-day.nextMonthDay.inRange,
.flatpickr-day.today.inRange,
.flatpickr-day.prevMonthDay.today.inRange,
.flatpickr-day.nextMonthDay.today.inRange {
    background: var(--flatpickr-range)!important;
    border-color: var(--flatpickr-range)!important;
    color: var(--flatpickr-on-range)!important;
}

/* Survol : teinte pêche légère (accent.softer), pas la couleur de plage pleine */
.flatpickr-day:hover,
.flatpickr-day.prevMonthDay:hover,
.flatpickr-day.nextMonthDay:hover,
.flatpickr-day:focus,
.flatpickr-day.prevMonthDay:focus,
.flatpickr-day.nextMonthDay:focus {
    background: var(--sp-color-accent-softer)!important;
    border-color: var(--sp-color-accent-softer)!important;
    color: var(--flatpickr-on-range)!important;
}

.flatpickr-day {
    border: none!important;
}

.flatpickr-day.today {
    background-color: var(--sp-color-border-default)!important;
}

/* Calendar posé dans le panneau de filtres (fiche calendar, maquette CASE_DATE) : rendu
   inline, grille pleine largeur en rangées de 44px, résumé « début → fin » au-dessus. */
.calendar {
    display: flex;
    flex-direction: column;
    gap: var(--sp-space-4);
}

/* Résumé 16/24 à 24px du titre et de son filet, qui court d'un bord à l'autre du panneau */
.calendar-summary {
    display: flex;
    align-items: center;
    margin: 0 calc(-1 * var(--sp-space-6));
    /* le filet compte dans les 24px du bas, comme sur la maquette (rangée de 72px) */
    padding: var(--sp-space-2) var(--sp-space-6) calc(var(--sp-space-6) - 1px);
    border-bottom: 1px solid var(--sp-color-border-on-white);
    font-size: var(--sp-font-size-h4);
    line-height: 24px;
    color: var(--sp-color-text-default);
}

/* Flèche de 24px à 16px des dates ; l'écart cède avant que deux dates longues ne passent à
   la ligne (« 30 Septembre 2026 → 31 Décembre 2026 ») */
.calendar-summary-arrow {
    display: inline-flex;
    flex: 0 1 56px;
    justify-content: center;
    min-width: 24px;
    color: var(--sp-color-text-default);
}

.calendar-summary > span:not(.calendar-summary-arrow) {
    flex: 0 0 auto;
    white-space: nowrap;
}

.calendar-summary-arrow svg {
    width: 24px;
    height: 24px;
}

/* L'ancre de flatpickr est vide : hors du flux, sans quoi elle coûte une gouttière */
.calendar > .flatpickr-input {
    display: none;
}

.calendar .flatpickr-calendar.inline {
    top: 0;
    width: 100%;
    min-width: calc(7 * var(--sp-control-icon-button));
    max-width: none;
    margin: 0;
    border-radius: 0;
    background: transparent;
    box-shadow: none!important;
}

.calendar .flatpickr-rContainer,
.calendar .flatpickr-days,
.calendar .dayContainer,
.calendar .flatpickr-weekdays,
.calendar .flatpickr-weekdaycontainer {
    width: 100%;
    min-width: 0;
    max-width: none;
    letter-spacing: var(--sp-font-tracking-tight);
}

/* Le mois : un libellé 16/24 bold ferré à gauche, ses deux flèches au-dessus des deux
   dernières colonnes */
.calendar .flatpickr-months {
    position: relative;
    align-items: center;
    height: 24px;
    margin-bottom: var(--sp-space-2);
}

.calendar .flatpickr-months .flatpickr-month {
    height: 24px;
    overflow: visible;
    color: var(--sp-color-text-default);
}

.calendar .flatpickr-current-month {
    position: static;
    display: flex;
    align-items: center;
    width: auto;
    height: 24px;
    padding: 0;
    font-size: var(--sp-font-size-h4);
    font-weight: var(--sp-font-weight-bold);
    line-height: 24px;
    text-align: left;
    text-transform: capitalize;
    color: var(--sp-color-text-default);
}

.calendar .flatpickr-current-month .cur-month {
    margin: 0;
    font-weight: inherit;
}

.calendar .flatpickr-current-month input.cur-year {
    height: 24px;
    padding: 0 0 0 var(--sp-space-1);
    font-weight: inherit;
    line-height: 24px;
}

/* L'année n'est pas un champ (retour client) : ni flèches, ni curseur, ni saisie */
.calendar .flatpickr-current-month .numInputWrapper span.arrowUp,
.calendar .flatpickr-current-month .numInputWrapper span.arrowDown {
    display: none;
}

.calendar .flatpickr-current-month .numInputWrapper,
.calendar .flatpickr-current-month input.cur-year {
    pointer-events: none;
}

.calendar .flatpickr-current-month .numInputWrapper:hover {
    background: transparent;
}

.calendar .flatpickr-months .flatpickr-prev-month.flatpickr-prev-month,
.calendar .flatpickr-months .flatpickr-next-month.flatpickr-next-month {
    top: 50%;
    left: auto;
    display: flex;
    align-items: center;
    justify-content: center;
    width: var(--sp-control-icon-button);
    height: var(--sp-control-icon-button);
    padding: 0;
    transform: translateY(-50%);
    color: var(--sp-color-text-brown);
    fill: currentColor;
}

.calendar .flatpickr-months .flatpickr-prev-month.flatpickr-prev-month {
    right: calc(100% / 14 * 3 - var(--sp-control-icon-button) / 2);
}

.calendar .flatpickr-months .flatpickr-next-month.flatpickr-next-month {
    right: calc(100% / 14 - var(--sp-control-icon-button) / 2);
}

/* En-têtes de jours 12/16 dans une rangée de 44px, à 6px de la grille comme les rangées
   entre elles */
.calendar .flatpickr-weekdays {
    height: var(--sp-control-icon-button);
    margin-bottom: 6px;
}

.calendar span.flatpickr-weekday {
    font-size: var(--sp-font-size-12);
    font-weight: var(--sp-font-weight-body);
    line-height: 16px;
    text-transform: capitalize;
    color: var(--sp-color-text-muted);
}

.calendar .dayContainer {
    justify-content: flex-start;
    row-gap: 6px;
}

/* La case prend 1/7 de la largeur : pastilles et survol sont donc PEINTS en cercle de 44px
   centré (radial-gradient), jamais obtenus par le rayon d'une case qui n'est plus carrée */
.calendar .flatpickr-day {
    flex-basis: 14.2857143%;
    width: 14.2857143%;
    max-width: none;
    height: var(--sp-control-icon-button);
    margin: 0;
    font-size: var(--sp-font-size-label);
    font-weight: var(--sp-font-weight-body);
    line-height: var(--sp-control-icon-button);
    color: var(--sp-color-text-default);
    border-radius: 0!important;
}

/* flatpickr décale d'1px les jours d'une plage : le pas de 50px n'en veut pas */
.calendar .rangeMode .flatpickr-day {
    margin-top: 0;
}

/* Seuls les jours du mois : les cases d'avant restent vides, celles d'après ne comptent pas
   (une dernière rangée vide ne s'affiche pas) */
.calendar .flatpickr-day.prevMonthDay {
    visibility: hidden;
}

.calendar .flatpickr-day.nextMonthDay {
    display: none;
}

.calendar .flatpickr-day.today {
    background: radial-gradient(circle closest-side, var(--sp-color-border-default) calc(100% - 0.5px), transparent)!important;
}

.calendar .flatpickr-day:hover,
.calendar .flatpickr-day:focus {
    background: radial-gradient(circle closest-side, var(--sp-color-accent-softer) calc(100% - 0.5px), transparent)!important;
}

/* Desktop : panneau de 382px (maquette), grille élargie de 8px par côté = colonnes de 50px ;
   le mois reste ferré sur le résumé */
@media (min-width: 992px) {
    .filter-panel:has(.calendar) {
        width: 382px;
        min-width: 0;
    }

    .calendar .flatpickr-calendar.inline {
        width: calc(100% + var(--sp-space-4));
        margin: 0 calc(-1 * var(--sp-space-2));
    }

    .calendar .flatpickr-months {
        padding: 0 var(--sp-space-2);
    }
}

/* Le corps du panneau Dates ne défile pas : le mois tient en entier (fiche calendar) */
.calendar.filter-panel-body {
    overflow: visible;
}

.calendar .flatpickr-day.inRange {
    background: var(--sp-color-accent-soft)!important;
    font-weight: var(--sp-font-weight-title);
    color: var(--sp-color-text-default)!important;
    box-shadow: none!important;
}

/* (0,4,0) : le thème flatpickr, plus bas, arrondit ses extrémités à 50px en (0,3,0) — un
   rayon qui rognerait la demi-bande */
.calendar .dayContainer .flatpickr-day.selected,
.calendar .dayContainer .flatpickr-day.startRange,
.calendar .dayContainer .flatpickr-day.endRange {
    background: radial-gradient(circle closest-side, var(--sp-color-accent-selected) calc(100% - 0.5px), transparent)!important;
    font-weight: var(--sp-font-weight-title);
    color: var(--sp-color-text-inverse)!important;
    border-radius: 0!important;
    box-shadow: none!important;
}

/* La bande passe DERRIÈRE les pastilles d'extrémité : une demi-bande côté plage, sauf au
   bord de la semaine où elle n'aurait rien à rejoindre */
.calendar .dayContainer:has(.endRange) .flatpickr-day.startRange:not(.endRange):not(:nth-child(7n)) {
    background:
        radial-gradient(circle closest-side, var(--sp-color-accent-selected) calc(100% - 0.5px), transparent),
        linear-gradient(90deg, transparent 50%, var(--sp-color-accent-soft) 50%)!important;
}

.calendar .dayContainer:has(.startRange) .flatpickr-day.endRange:not(.startRange):not(:nth-child(7n+1)) {
    background:
        radial-gradient(circle closest-side, var(--sp-color-accent-selected) calc(100% - 0.5px), transparent),
        linear-gradient(90deg, var(--sp-color-accent-soft) 50%, transparent 50%)!important;
}

/* Le thème flatpickr plus haut trace sa bande par des pseudo-éléments : sans objet ici */
.calendar .flatpickr-day.startRange::after,
.calendar .flatpickr-day.endRange::after,
.calendar .flatpickr-day.selected::after,
.calendar .flatpickr-day.startRange + .endRange::before {
    content: none!important;
}

.flatpickr-day.selected,
.flatpickr-day.startRange,
.flatpickr-day.endRange,
.flatpickr-day.selected.inRange,
.flatpickr-day.startRange.inRange,
.flatpickr-day.endRange.inRange,
.flatpickr-day.selected:focus,
.flatpickr-day.startRange:focus,
.flatpickr-day.endRange:focus,
.flatpickr-day.selected:hover,
.flatpickr-day.startRange:hover,
.flatpickr-day.endRange:hover,
.flatpickr-day.selected.prevMonthDay,
.flatpickr-day.startRange.prevMonthDay,
.flatpickr-day.endRange.prevMonthDay,
.flatpickr-day.selected.nextMonthDay,
.flatpickr-day.startRange.nextMonthDay,
.flatpickr-day.endRange.nextMonthDay {
    background: var(--flatpickr-primary)!important;
    -webkit-box-shadow: none!important;
    box-shadow: none!important;
    color: var(--flatpickr-on-primary)!important;
    border-color: var(--flatpickr-primary)!important;
}

.flatpickr-day.selected.startRange,
.flatpickr-day.startRange.startRange,
.flatpickr-day.endRange.startRange {
    border-radius: var(--sp-radius-full) !important;
}

.flatpickr-day.selected.endRange,
.flatpickr-day.startRange.endRange,
.flatpickr-day.endRange.endRange {
    border-radius: var(--sp-radius-full) !important;
}

.flatpickr-day.selected.startRange + .endRange:not(:nth-child(7n+1)),
.flatpickr-day.startRange.startRange + .endRange:not(:nth-child(7n+1)),
.flatpickr-day.endRange.startRange + .endRange:not(:nth-child(7n+1)) {
    box-shadow: none!important;
}

.flatpickr-day.selected.startRange + .endRange:not(:nth-child(7n+1)):before,
.flatpickr-day.startRange.startRange + .endRange:not(:nth-child(7n+1)):before,
.flatpickr-day.endRange.startRange + .endRange:not(:nth-child(7n+1)):before {
    content: "";
    position: absolute;
    top: 0;
    left: -5px;
    width: 100%;
    height: 100%;
    background: var(--flatpickr-range);
    z-index: -1;
    border-radius: 0 var(--sp-radius-full) var(--sp-radius-full) 0;
}

.flatpickr-day.selected.startRange + .endRange:not(:nth-child(7n+1)):after,
.flatpickr-day.startRange.startRange + .endRange:not(:nth-child(7n+1)):after,
.flatpickr-day.endRange.startRange + .endRange:not(:nth-child(7n+1)):after {
    content: normal!important;
}

.flatpickr-day.selected.startRange.endRange,
.flatpickr-day.startRange.startRange.endRange,
.flatpickr-day.endRange.startRange.endRange {
    border-radius: var(--sp-radius-full) !important;
}
.flatpickr-day.inRange {
    position: relative;
    color: var(--flatpickr-on-range)!important;
    border-radius: 0!important;
    -webkit-box-shadow: -5px 0 0 var(--flatpickr-range), 5px 0 0 var(--flatpickr-range)!important;
    box-shadow: -5px 0 0 var(--flatpickr-range), 5px 0 0 var(--flatpickr-range)!important;
}

/* La demi-case pêche qui relie le cercle de début à la bande (et fin, à gauche) */
.flatpickr-day.startRange:after {
    content: "";
    position: absolute;
    top: 0;
    right: 0;
    width: 50%;
    height: 100%;
    background: var(--flatpickr-range);
    z-index: -1;
    border-top-right-radius: 0;
    border-bottom-right-radius: 0;
}

.flatpickr-day.endRange:after {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    width: 50%;
    height: 100%;
    background: var(--flatpickr-range);
    z-index: -1;
    border-top-left-radius: 0;
    border-bottom-left-radius: 0;
}

.flatpickr-day.week.selected {
    border-radius: 0!important;
    -webkit-box-shadow: -5px 0 0 var(--flatpickr-primary), 5px 0 0 var(--flatpickr-primary)!important;
    box-shadow: -5px 0 0 var(--flatpickr-primary), 5px 0 0 var(--flatpickr-primary)!important;
}

.flatpickr-weekwrapper .flatpickr-weeks {
    -webkit-box-shadow: 1px 0 0 var(--flatpickr-secondary)!important;
    box-shadow: 1px 0 0 var(--flatpickr-secondary)!important;
}

/* Form Check */

/* Case et libellé à 8px, 4px sous la ligne : en rem, sur la racine de 14px, ils rendaient
   6,3 et 4,9px (piège du pas de 14, cf. CLAUDE.md). */
.form-check {
    display: flex;
    align-items: center;
    gap: var(--sp-space-2);
    margin-bottom: var(--sp-space-1);
}

/* Le libellé d'un ENGAGEMENT (CGU, politique de confidentialité) descend à size.meta : c'est une
   phrase juridique qu'on lit une fois avant de valider, pas l'option qu'on est venu choisir — à la
   taille du corps, deux de ces phrases pèsent plus lourd que le geste qu'elles autorisent (fiche
   checkbox). Ce qui descend est la TAILLE, pas le registre : le libellé et son lien gardent leur
   couleur, un engagement estompé étant une case cochée sans savoir à quoi l'on s'engage.

   La case ne suit pas : la règle du type ci-dessous la fixe à 18px, hors de l'`em` de Bootstrap,
   et sa cible ne dépend pas de la longueur de ce qu'elle fait accepter.

   La règle suit le RÔLE, pas le balisage : un engagement se rend tantôt en case-et-libellé,
   tantôt en ligne d'option (libellé à gauche, contrôle à droite). C'est la même chose qu'on fait
   accepter, donc un seul jeu de valeurs — sans quoi le produit fait accepter ses conditions de
   deux façons selon l'écran. */
.form-check-consent .form-check-label,
.option-row-consent .option-row-name{
    font-size: var(--sp-font-size-meta);
}

/* Grammaire DS des contrôles : filet chaud au repos, coché = orange, anneau de focus */
.form-check-input {
    border: var(--sp-border-width-strong) solid var(--sp-color-border-cream);
    margin: 0;
}

/* Case à cocher : 18px, rayon radius.xs (fiche checkbox). Bootstrap la dimensionne en `em`
   et arrondit en `.25em` : la case suivrait donc la taille du texte à côté d'elle, et son
   rayon avec. Le sélecteur vise le type — le radio partage cette classe et garde son
   cercle de 20px. */
.form-check-input[type="checkbox"] {
    width: 18px;
    height: 18px;
    border-radius: var(--sp-radius-xs);
}

.form-check-input:checked {
    background-color: var(--sp-color-accent-selected);
    border-color: var(--sp-color-accent-selected);
}

.form-check-input:focus {
    box-shadow: var(--sp-shadow-ring);
    border-color: var(--sp-color-border-cream);
}

.form-check-input:checked:focus {
    border-color: var(--sp-color-accent-selected);
}

/* Form Switch */

.form-switch {
    padding-left: 3.5em;
}

/* Switch DS : piste chaude au repos, orange activé, bouton blanc dans tous les états.
   Un switch est un input[type=checkbox] : la règle de la case à cocher ci-dessus l'atteint
   donc aussi. Sa piste reprend ici sa forme de pill (fiche switch), que le rayon de la case
   lui avait ôtée. */
.form-switch .form-check-input {
    width: 36px;
    margin-left: -3.5em;
    height: 20px;
    border-radius: var(--sp-radius-full);
    background-color: var(--sp-color-border-cream);
    border-color: var(--sp-color-border-cream);
    --bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23ffffff'/%3e%3c/svg%3e");
}

/* Switch SANS libellé visible : son titre de section le nomme (fiche switch). Bootstrap réserve
   3,5em de padding pour un texte qui n'est plus dans le flux — la piste flotterait alors à gauche
   d'une boîte vide, décollée du bord qu'elle doit longer. */
.form-switch-bare {
    padding-left: 0;
}

.form-switch-bare .form-check-input {
    margin-left: 0;
}

.form-switch .form-check-input:checked {
    background-color: var(--sp-color-accent-selected);
    border-color: var(--sp-color-accent-selected);
}

/* Bootstrap repeint le bouton en bleu (#86b7fe) au focus, et sa règle est plus spécifique
   que celle du repos : le bouton est blanc dans tous les états (fiche switch), et le DS ne
   connaît pas ce bleu. Le focus se dit par son anneau, qui est orange. */
.form-switch .form-check-input:focus {
    --bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23ffffff'/%3e%3c/svg%3e");
}

/* Astérisque de champ requis en orange (DS input : required.mark) */
/* Marque « champ requis » écrite dans le libellé, pour les champs où le ::after de
   `label.required` ci-dessous ne survit pas (form-floating le remet à `content: normal`).
   Même orange, même écart : c'est la même marque, posée autrement. */
.field-required {
    margin-left: 0.25em;
    color: var(--sp-color-accent-selected);
}

/* Pas sur le libellé d'un CHOIX (chips de sport, radios) : la marque vaut pour le champ, et
   chaque option la répétait (revue, sept. 2026). */
label.required:not(.form-check-label):after {
    content: "*";
    margin-left: 0.25em;
    color: var(--sp-color-accent-selected);
}

/* Libellé qui porte déjà sa marque écrite (`.required-mark`, champs flottants) : sans cela, un
   champ vide affichait « Lieu de l'évènement * * » — le ::after n'est effacé qu'une fois le
   libellé remonté. */
label.required:not(.form-check-label):has(.required-mark):after {
    content: none;
}

/* Panneau de localisation (DESIGNAPP) : recherche avec loupe, puis Slider de rayon. */
.filter-location-search {
    display: flex;
    flex-direction: column;
    gap: var(--sp-space-2);
    margin-bottom: var(--sp-space-6);
}

.filter-location-label {
    font-weight: var(--sp-font-weight-title);
    color: var(--sp-color-text-default);
}

/* La loupe se pose dans le champ ; le dropdown de suggestions se rend dans ce parent,
   d'où position: relative. */
.filter-location-field {
    position: relative;
    display: block;
}

.filter-location-icon {
    position: absolute;
    top: 50%;
    left: var(--sp-space-3);
    transform: translateY(-50%);
    color: var(--sp-color-text-muted);
    pointer-events: none;
}

/* Un champ qui cherche est toujours un pill (fiche input, variant search) : la forme dit
   qu'on y tape pour trouver, pas pour renseigner un formulaire. Vaut pour tout champ de
   recherche — type=search (faq, blog) et le champ de localisation (type=text). */
.form-control[type="search"] {
    border-radius: var(--sp-radius-full);
}

.filter-location-field .form-control {
    border-radius: var(--sp-radius-full);
    padding-left: calc(var(--sp-space-3) + 18px + var(--sp-space-2));
}

/* Slider (fiche slider) : libellé + valeur au-dessus, piste bicolore, poignée blanche à
   liseré orange, bornes en dessous. La portion parcourue (orange) et le reste (pêche) se
   tracent d'un dégradé calé sur --slider-progress, que le contrôleur met à jour. */
.slider {
    display: flex;
    flex-direction: column;
    gap: var(--sp-space-2);
}

.slider-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
}

.slider-label {
    color: var(--sp-color-text-default);
}

.slider-value {
    font-weight: var(--sp-font-weight-title);
    color: var(--sp-color-text-default);
}

.slider-input {
    -webkit-appearance: none;
    appearance: none;
    width: 100%;
    height: 8px;
    border-radius: var(--sp-radius-full);
    background: linear-gradient(
        to right,
        var(--sp-color-accent-selected) 0%,
        var(--sp-color-accent-selected) var(--slider-progress, 0%),
        var(--sp-color-accent-soft) var(--slider-progress, 0%),
        var(--sp-color-accent-soft) 100%
    );
    cursor: pointer;
}

/* La poignée : blanc plein, sans bordure, détachée de la piste par une ombre portée
   (fiche slider). Répétée pour chaque moteur — les pseudo-éléments de curseur ne se
   groupent pas dans un même sélecteur. */
.slider-input::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: 22px;
    height: 22px;
    border-radius: var(--sp-radius-full);
    background: var(--sp-color-bg-surface);
    border: 0;
    box-shadow: var(--sp-shadow-knob);
    cursor: pointer;
}

.slider-input::-moz-range-thumb {
    width: 22px;
    height: 22px;
    border-radius: var(--sp-radius-full);
    background: var(--sp-color-bg-surface);
    border: 0;
    box-shadow: var(--sp-shadow-knob);
    cursor: pointer;
}

/* Firefox trace sa propre piste : on la neutralise, le dégradé du background suffit */
.slider-input::-moz-range-track {
    height: 8px;
    border-radius: var(--sp-radius-full);
    background: transparent;
}

.slider-input:focus-visible {
    outline: none;
}

.slider-input:focus-visible::-webkit-slider-thumb {
    box-shadow: var(--sp-shadow-ring);
}

.slider-input:focus-visible::-moz-range-thumb {
    box-shadow: var(--sp-shadow-ring);
}

.slider-bounds {
    display: flex;
    justify-content: space-between;
    font-size: var(--sp-font-size-meta);
    color: var(--sp-color-text-muted);
}

/* Search-form */

.search-bar-desktop-wrapper,
.search-bar-mobile-wrapper{
    display: flex;
    flex-grow: 1;
}

/* L'emplacement mobile reste vide jusqu'à ce que `search-placement` y pose le champ : sans
   réserve, onglets et chips s'affichent 44px trop haut puis sautent au chargement du JS. */
.search-bar-mobile-wrapper{
    min-height: 44px;
}

/* SearchBar DS : traitement liquid glass, un seul par vue
   (designsystem/spicto/app/components/search-bar.md) */
.search-bar{
    background: var(--sp-glass-search-tint);
    backdrop-filter: blur(var(--sp-glass-blur));
    -webkit-backdrop-filter: blur(var(--sp-glass-blur));
    border: var(--sp-glass-search-border);
    box-shadow: var(--sp-glass-search-shadow);
    border-radius: var(--sp-radius-full);
    min-height: 44px;
}

.search-bar:focus-within{
    box-shadow: var(--sp-shadow-ring), var(--sp-glass-search-shadow);
}

/* Sous 992px, la barre porte le verre — donc un `backdrop-filter`, donc un CONTEXTE
   D'EMPILEMENT. Son panneau de résultats a beau être en z-index 1000, il est enfermé dedans :
   tout ce qui suit dans la page (onglets, chips, cartes du rail) lui passait devant, et le
   panneau se lisait comme transparent. C'est la barre qu'il faut élever, pas lui — un élément
   ne sort pas du contexte de son parent.

   Le défaut ne se voyait pas avant : le panneau était purement et simplement masqué sous
   992px, puisque la recherche mobile se faisait ailleurs, dans un panneau plein écran.

   Sur desktop le verre tombe (fiche search-bar), il n'y a plus de contexte d'empilement, et
   la règle n'a plus lieu d'être. */
@media (max-width: 991.98px) {
    .search-bar{
        z-index: 20;
    }
}

/* Desktop : la barre repose sur un fond de page plein, pas sur une photo — le verre n'a
   rien pour le porter. On prend la surface pleine des filtres (bg.surface + shadow.sm) et
   on plafonne la largeur à 500px (fiche search-bar). */
@media (min-width: 992px) {
    .search-bar{
        background: var(--sp-color-bg-surface);
        backdrop-filter: none;
        -webkit-backdrop-filter: none;
        border: none;
        box-shadow: var(--sp-shadow-sm);
        max-width: 500px;
    }

    .search-bar:focus-within{
        box-shadow: var(--sp-shadow-ring);
    }
}

.search-bar .form-control,
.search-bar .input-group-text{
    border-radius: var(--sp-radius-full);
    background-color: transparent;
    border: none;
}

.search-bar .input-group-text{
    color: var(--sp-color-text-caption);
    padding-left: 1rem;
    padding-right: 0;
    display: flex;
    align-items: center;
}

.search-bar .form-control{
    padding-left: 0.75rem;
    padding-top: 12px;
    padding-bottom: 12px;
    font-size: var(--sp-font-size-label);
    color: var(--sp-color-text-default);
}

/* Le placeholder suit la règle de l'Input : text.muted est le seul ton qui tienne l'AA sur les
   deux fonds que cette barre connaît — le verre sur photo, et la surface pleine du desktop
   (fiche search-bar). L'icône, elle, reste en caption : c'est un pictogramme, pas du texte. */
.search-bar .form-control::placeholder{
    color: var(--sp-color-text-muted);
}

.search-bar .form-control:focus {
    box-shadow: none;
    background-color: transparent;
    border: none;
}

.search-bar .ts-control,
.search-bar .ts-wrapper.focus .ts-control{
    background: transparent;
    border: none;
    box-shadow: none;
}

.search-bar .ts-control{
    padding: 12px 16px!important;
}

.search-bar .ts-control input {
    font-size: 14px;
    line-height: 15px !important;
}

/* L'option choisie ne se dessine pas dans la barre (retour client : « l'évènement sélectionné
   flotte quelques secondes ») : TomSelect la rend en item le temps que la page change, et sur
   mobile ce temps se voit. On navigue, on n'affiche rien. */
.search-bar .ts-control > .item{
    display: none;
}

/* Panneau de résultats de la SearchBar (fiche search-bar) : une surface flottante NUE —
   bg.surface, radius.lg, shadow.pop, et pas de filet (l'ombre ou le filet, jamais les deux).
   Ni titre ni pied d'actions : ce n'est pas un Dropdown, qui règle quelque chose et se valide ;
   celui-ci ne fait que montrer ce qu'on a écrit. */
.search-bar .ts-dropdown{
    background: var(--sp-color-bg-surface);
    border: none;
    border-radius: var(--sp-radius-lg);
    box-shadow: var(--sp-shadow-pop);
    margin-top: var(--sp-space-2);
    overflow: hidden;
}

/* Les lignes sont des ListItem, en UNE colonne : la grille de tuiles à deux ou trois colonnes
   faisait de la liste un catalogue et perdait l'ordre de pertinence, que le regard suit de haut
   en bas. La gouttière est horizontale seulement — une ligne de liste court d'un bord à l'autre
   de sa surface, c'est son filet qui la sépare de la suivante, pas du vide. */
.search-bar .ts-dropdown .ts-dropdown-content{
    padding: 0 var(--sp-space-4);
    /* Le plafond suit l'écran, pas un nombre de pixels : les 200px de TomSelect étaient
       calibrés sur des lignes compactes et ne montraient plus que deux ListItem, quand la
       requête en rend cinq (fiche search-bar). 60vh les laisse tous voir sur desktop et borne
       le panneau à ce que le mobile peut céder. */
    max-height: 60vh;
}

.search-bar .ts-dropdown .option{
    max-width: none;
    padding: 0;
    background: transparent;
}

/* Le filet de la dernière ligne ne sépare plus rien : chaque option étant un conteneur à part,
   `.list-item:last-child` est vrai partout et le filet tombait sous la dernière (fiche
   list-item : « la dernière n'en porte pas, elle ne sépare plus rien »). */
.search-bar .ts-dropdown .option:last-child .list-item,
.search-bar .ts-dropdown .option:has(+ .no-more-results) .list-item{
    border-bottom: 0;
}

/* Survol et parcours au clavier : le crème le plus clair du système, celui qui marque la ligne
   sans la découper. Il se pose sur la ligne entière, gouttière comprise. */
.search-bar .ts-dropdown .option.active,
.search-bar .ts-dropdown .option:hover{
    background: var(--sp-color-bg-default);
    margin: 0 calc(-1 * var(--sp-space-4));
    padding: 0 var(--sp-space-4);
}

.search-bar .ts-dropdown .option.no-more-results{
    max-width: none;
    padding: var(--sp-space-4) 0;
    color: var(--sp-color-text-muted);
    font-size: var(--sp-font-size-meta);
}

/* « Aucun résultat pour « … » » (fiche search-bar) : il attend les suggestions, et se tait quand
   elles répondent — il se lirait au-dessus de leurs lignes. */
.search-bar .ts-dropdown .no-results{
    max-width: none;
    padding: var(--sp-space-4) 0;
}

.search-bar .ts-dropdown[data-suggestions-pending] .no-results,
.search-bar .ts-dropdown:has(.search-suggestions) .no-results{
    display: none;
}

/* La fin de pagination ne dit rien que la liste ne montre déjà */
.search-bar .ts-dropdown .no-more-results{
    display: none;
}

/* Sans ligne d'évènement au-dessus, le filet des suggestions ne sépare plus rien */
.search-bar .ts-dropdown:not(:has(.option)) .search-suggestions{
    border-top: 0;
}

.search-empty-title{
    margin: 0;
    font-size: var(--sp-font-size-h4);
    font-weight: var(--sp-font-weight-title);
    line-height: 19px;
    letter-spacing: var(--sp-font-tracking-tight);
    color: var(--sp-color-text-default);
}

.search-empty-text{
    margin: var(--sp-space-1) 0 0;
    font-size: var(--sp-font-size-meta);
    font-weight: var(--sp-font-weight-body);
    line-height: 16px;
    letter-spacing: var(--sp-font-tracking-meta);
    color: var(--sp-color-text-brown);
}

/* Ce que la ligne a retrouvé se marque en graisse, jamais en surligné (fiche search-bar).
   (0,4,0) : la feuille de TomSelect, chargée après celle-ci, pose le jaune en (0,3,0). */
.search-bar .ts-dropdown [data-selectable] .highlight{
    background: none;
    border-radius: 0;
    color: inherit;
    font-weight: var(--sp-font-weight-title);
}

/*legend {*/
/*    font-family: var(--heading-font-family), sans-serif;*/
/*    font-size: 1.1rem !important;*/
/*    font-weight: 600;*/
/*    padding: 0;*/
/*    margin-bottom: 1rem;*/
/*}*/

/*fieldset {*/
/*    padding-top: .5rem;*/
/*    padding-bottom: .5rem;*/
/*}*/

/*fieldset:not(:last-child) {*/
/*    border-bottom: 1px solid var(--light);*/
/*    margin-bottom: .5rem;*/
/*}*/

/* Search suggestions (évènements, lieux, photographes, sports) */

/* Les raccourcis qui prolongent les résultats : ils ne sont pas des lignes de liste — ils ne
   désignent pas un évènement mais une VUE filtrée. D'où la pilule, et le filet chaud qui les
   sépare des résultats au-dessus. Tokens du DS de bout en bout : le bloc portait des rem hors
   échelle, un gris Bootstrap et `--light`.

   La gouttière horizontale est celle de la liste d'options (`.ts-dropdown-content`) : depuis que
   le panneau se lit groupé par type, les groupes doivent s'aligner sur les lignes au-dessus
   d'eux, sinon deux marges gauches se répondent dans la même surface. */
.search-suggestions {
    border-top: 1px solid var(--sp-color-border-default);
    padding: var(--sp-space-4);
}

.search-suggestions-section:not(:last-child) {
    margin-bottom: var(--sp-space-4);
}

/* Un en-tête de groupe, pas une étiquette en capitales : `family.label` est un choix de fonte
   et n'emporte ni majuscules ni interlettrage (DESIGN.md, « Typography »). */
.search-suggestions-title {
    font-size: var(--sp-font-size-meta);
    font-weight: var(--sp-font-weight-title);
    line-height: 16px;
    letter-spacing: var(--sp-font-tracking-meta);
    color: var(--sp-color-text-brown);
    margin-bottom: var(--sp-space-2);
}

.search-suggestions-list {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-space-2);
}

.search-suggestions-item {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-space-2);
    padding: var(--sp-space-2) var(--sp-space-3);
    border-radius: var(--sp-radius-full);
    background-color: var(--sp-color-bg-cream);
    color: var(--sp-color-text-default);
    text-decoration: none;
    font-size: var(--sp-font-size-label);
    font-weight: var(--sp-font-weight-body);
    line-height: 17px;
    transition: background-color var(--sp-duration-fast) var(--sp-easing-standard);
}

/* Au survol, la surface se creuse d'un cran — elle ne prend ni l'ink ni l'orange : ces
   raccourcis mènent quelque part, ils ne sont ni une action ni un état réglé. */
.search-suggestions-item:hover {
    background-color: var(--sp-color-bg-sunken);
    color: var(--sp-color-text-default);
    text-decoration: none;
}

/* En-tête du groupe « Évènements » : il coiffe la liste d'options du champ, qui n'est pas dans
   `.search-suggestions` et ne reçoit donc pas sa gouttière. Il la reprend ici pour s'aligner
   sur les lignes qu'il annonce. */
.search-suggestions-title--options {
    padding: var(--sp-space-4) var(--sp-space-4) 0;
    margin-bottom: 0;
}

/* Évènement et photographe désignent une ENTITÉ, pas une vue filtrée : ils prennent une ligne,
   en une colonne, comme partout où l'app liste des résultats (fiche list-item). */
.search-suggestions-list--rows {
    flex-direction: column;
    flex-wrap: nowrap;
    gap: 0;
}

.search-suggestions-row {
    display: flex;
    align-items: center;
    gap: var(--sp-space-3);
    padding: var(--sp-space-2);
    margin: 0 calc(-1 * var(--sp-space-2));
    border-radius: var(--sp-radius-md);
    color: var(--sp-color-text-default);
    text-decoration: none;
    transition: background-color var(--sp-duration-fast) var(--sp-easing-standard);
}

.search-suggestions-row:hover {
    background-color: var(--sp-color-bg-default);
    color: var(--sp-color-text-default);
    text-decoration: none;
}

/* Les rôles de texte sont ceux du ListItem ; ils s'empilent, la vignette reste centrée. */
.search-suggestions-row-body {
    display: flex;
    flex-direction: column;
}

/* Event title Tom Select suggestions */
.event-suggestion-option {
    display: flex;
    align-items: center;
    gap: .5rem;
    padding: .35rem .5rem;
}

/* Liste d'options d'un formulaire (DESIGNAPP, « La même anatomie sert les options d'un
   formulaire ») : libellé à gauche, Radio aligné à droite, filet entre les options.

   Ce n'est plus une carte par option : une carte par choix pose chacun sur sa propre surface,
   et l'œil compare alors des surfaces au lieu de comparer des offres. C'est le groupe entier
   qui a une carte, pas ses membres. */
.option-list{
    border: 0;
    padding: 0;
    margin: 0;
    min-width: 0;   /* un fieldset ne rétrécit pas sans ça */
}

.option-row{
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--sp-space-4);
    padding: var(--sp-space-4) 0;
    cursor: pointer;
}

/* Le filet coiffe la ligne au lieu de la souligner : la dernière n'en porte donc aucun, sans
   avoir à la désigner. Même construction que la liste de filtres. */
.option-row + .option-row{
    border-top: 1px solid var(--sp-color-border-default);
}

.option-row:first-of-type{ padding-top: 0; }
.option-row:last-of-type{ padding-bottom: 0; }

.option-row-label{
    display: flex;
    flex-direction: column;
    gap: var(--sp-space-1);
    min-width: 0;
}

/* Trois lignes au plus : le nom, la valeur en gras, ce que l'option fait (DESIGNAPP).

   Le nom et la valeur sont à `size.body` : elles se lisent d'un bloc — l'une nomme, l'autre
   chiffre —, et c'est la GRAISSE qui les départage, pas l'échelle. Les deux lisaient
   `font.size.16`, une primitive qu'un composant n'a pas le droit de lire, et à cette taille le
   nom d'une option pesait autant que le sous-titre d'un bloc dans une liste qu'on parcourt
   justement pour comparer. */
.option-row-name{
    font-size: var(--sp-font-size-body);
    font-weight: var(--sp-font-weight-body);
    color: var(--sp-color-text-default);
}

.option-row-value{
    font-size: var(--sp-font-size-body);
    color: var(--sp-color-text-default);
}

.option-row-value strong{
    font-weight: var(--sp-font-weight-bold);
}

.option-row-help{
    font-size: var(--sp-font-size-label);
    color: var(--sp-color-text-muted);
}

/* Le contrôle garde sa cible tactile et ne se déforme pas quand le libellé s'allonge */
.option-row .form-check-input{
    flex-shrink: 0;
    margin: 0;
}

/* Radio variant `segmented` (fiche radio) : le même choix exclusif, rendu en boutons alignés,
   quand les options sont courtes et comparables — une gamme de prix.

   Au repos : aplat crème, sans filet, libellé ink. Deux aplats plutôt qu'un plein et un vide :
   les options non choisies ressembleraient sinon à des trous. Le libellé ne s'estompe pas — un
   prix qu'on n'a pas choisi est exactement aussi cliquable que celui qu'on a choisi.

   Le libellé est centré SUR LES DEUX AXES. La hauteur est fixe (48px) alors que la mise en page
   d'un .btn repose sur ses marges internes : sans ce centrage, le texte pend au bord haut du
   cadre, et rien dans le style ne le signale (fiche radio). */
.btn-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: 48px;
    font-size: var(--sp-font-size-16);
    font-weight: var(--sp-font-weight-bold);
    --bs-btn-bg: var(--sp-color-bg-cream);
    --bs-btn-border-color: var(--sp-color-bg-cream);
    --bs-btn-color: var(--sp-color-text-default);
    --bs-btn-hover-bg: var(--sp-color-bg-sunken);
    --bs-btn-hover-border-color: var(--sp-color-bg-sunken);
    --bs-btn-hover-color: var(--sp-color-text-default);
    --bs-btn-border-radius: var(--sp-radius-lg);
}

/* Sélectionné : aplat ink. Sans cercle à cocher, seul un remplissage dit « c'est celui-là »
   d'un bout à l'autre de la rangée — et l'ink, pas l'orange, parce qu'on est dans le parcours
   de dépôt (DESIGNAPP, « Dans le dépôt, la sélection est ink »). */
.btn-check:checked + .btn-toggle {
    --bs-btn-bg: var(--sp-color-action-primary);
    --bs-btn-border-color: var(--sp-color-action-primary);
    --bs-btn-color: var(--sp-color-text-inverse);
    --bs-btn-active-bg: var(--sp-color-action-primary);
    --bs-btn-active-border-color: var(--sp-color-action-primary);
    --bs-btn-active-color: var(--sp-color-text-inverse);
    --bs-btn-hover-bg: var(--sp-color-action-primary);
    --bs-btn-hover-border-color: var(--sp-color-action-primary);
    --bs-btn-hover-color: var(--sp-color-text-inverse);
}

/* Sélection ink dans le parcours de dépôt, et là seulement (DESIGNAPP). Cinq écrans de
   décisions constelleraient la carte d'accents orange, et le seul orange qui compte — celui
   qui dépose — ne se distinguerait plus. La portée est la carte : un panneau de filtres ouvert
   depuis cet écran garde l'orange, il n'est pas dans le parcours. */
.upload-flow .form-check-input[type="radio"]:not([role="switch"]):checked {
    background-color: var(--sp-color-action-primary);
    border-color: var(--sp-color-action-primary);
}

.upload-flow .form-check-input[type="radio"]:not([role="switch"]):checked:focus {
    border-color: var(--sp-color-action-primary);
}

/* Photo-upload form*/

/* Dropzone (designsystem/spicto/app/components/dropzone.md).

   Blanche, pas grise : les vignettes qui s'y afficheront ensuite ne doivent pas être posées
   sur une couleur. Le POINTILLÉ est ce qui la désigne — c'est le seul signe que l'interface
   n'a pas à expliquer —, en filet chaud et non dans le gris froid de Bootstrap.

   Rayon 2xl (24px) : c'est un bloc posé DANS une carte, et il prend donc le rayon au-dessus
   d'elle (DESIGN, « Un bloc posé dans une carte prend le rayon au-dessus d'elle »). */
.custom-dropzone-wrapper{
    display: flex;
    align-items: center;
    justify-content: center;
    border: 2px dashed var(--sp-color-border-cream);
    /* Un cran SOUS la carte imbriquée qui la porte, laquelle est à `xl` (fiche dropzone) : elle
       était à égalité avec elle, et deux surfaces concentriques à rayons identiques ne se lisent
       plus comme emboîtées mais comme mal alignées. Sa grande taille n'y change rien — ce n'est
       pas la surface qui choisit son coin, c'est son rang. */
    border-radius: var(--sp-radius-lg);
    background-color: var(--sp-color-bg-surface);
    padding: var(--sp-space-12) var(--sp-space-8);
    min-height: 280px;
    cursor: pointer;
    transition: border-color var(--sp-duration-base) var(--sp-easing-standard),
                background-color var(--sp-duration-base) var(--sp-easing-standard);
    text-align: center;
    position: relative;
}

.custom-dropzone-wrapper:hover,
.custom-dropzone-wrapper:focus-within{
    border-color: var(--sp-color-border-focus);
    background-color: var(--sp-color-bg-default);
}

/* La contrainte principale de la zone : petite pour ne pas disputer la phrase d'appel, mais en
   graisse de titre — c'est un chiffre qui fait échouer un dépôt quand on le manque (fiche
   dropzone). Elle garde text.default : ce n'est pas de la méta au sens du registre, et la taille
   n'emporte pas la mise en retrait (tronc, « size.meta est une taille, pas un registre »). */
.dropzone-limit{
    font-size: var(--sp-font-size-meta);
    font-weight: var(--sp-font-weight-title);
    color: var(--sp-color-text-default);
}

/* La mention légale qui ferme la carte : la seule ligne du bloc qui accompagne vraiment sans
   rien demander, d'où le muted (fiche dropzone). Elle ne descend pas à size.12 pour autant —
   une phrase qui engage l'acheteur prendrait l'air d'un pied de page qu'on ne lit pas. */
.dropzone-legal{
    font-size: var(--sp-font-size-meta);
    font-weight: var(--sp-font-weight-body);
}

/* L'amorce descend à la même taille que la contrainte ci-dessus, mais pas pour la même raison :
   elle redit le geste que le pointillé annonce déjà. C'est la COULEUR qui départage les deux
   petites lignes — celle qu'il faut lire garde l'ink, celle qui accompagne prend le muted. */
.dropzone-prompt{
    font-size: var(--sp-font-size-meta);
}

/* Les règles SOUS la zone, en deux colonnes de faits — sans puces : ce ne sont pas des étapes
   à suivre (fiche dropzone). Sur mobile la seconde colonne passe dessous. */
/* Les règles sont des FAITS, courts et nombreux : à size.meta, les six tiennent en deux colonnes
   sans que la liste devienne le sujet de la carte (fiche dropzone). Elles gardent text.default —
   ce sont elles qui disent ce que le contrôle refuse, la taille ne les met pas en retrait. */
.dropzone-rules{
    display: grid;
    grid-template-columns: 1fr;
    column-gap: var(--sp-space-8);
    row-gap: var(--sp-space-2);
    list-style: none;
    padding: 0;
    margin: 0;
    font-size: var(--sp-font-size-meta);
}

@media (min-width: 768px) {
    .dropzone-rules{
        grid-template-columns: 1fr 1fr;
    }
}

.custom-dropzone-wrapper .dropzone-content{
    pointer-events: none;
}

.custom-dropzone-input{
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    opacity: 0;
    cursor: pointer;
}

/* Photographer & Club Form*/

/* Espaces pro : même grammaire de champ que le reste de l'app (DS input) ;
   l'ancien traitement gris plein sans bordure est abandonné. */
.photographer-layout .input-group-text,
.club-layout .input-group-text {
    background-color: var(--sp-color-bg-surface);
    border-color: var(--sp-color-border-cream);
}

.photographer-layout .form-floating>.form-control,
.photographer-layout .form-floating>.form-select,
.photographer-layout .form-select,
.photographer-layout .form-control{
    height: calc(52px + calc(var(--bs-border-width) * 2));
    min-height: calc(52px + calc(var(--bs-border-width) * 2));
}

.club-layout .form-floating>.form-control,
.club-layout .form-floating>.form-select,
.club-layout .form-select,
.club-layout .form-control{
    height: calc(52px + calc(var(--bs-border-width) * 2));
    min-height: calc(52px + calc(var(--bs-border-width) * 2));
}

/* LE COIN DU CHAMP SUIT LA ZONE : radius.sm (8px) dehors, radius.md (12px) dans l'espace
   connecté — la MÊME densité que le bouton, et pour la même raison (fiche input). Les deux
   doivent bouger ensemble : un formulaire dont les champs gardent le coin d'accueil sous des
   boutons resserrés se lit comme deux jeux de contrôles empruntés à deux écrans.

   `:where()` n'apporte AUCUNE spécificité : cette règle pèse donc autant que `.form-control`
   seul. C'est délibéré, et c'est ce qui protège les champs non concernés — tous ceux qui
   portent déjà une autre forme sont posés par des règles plus spécifiques (0,2,0), qui gagnent
   quoi qu'il arrive et sans dépendre de l'ordre du fichier :
   - .form-control[type="search"]        le champ de recherche, en pilule ;
   - .search-bar .form-control           la barre de recherche globale, en pilule ;
   - .filter-location-field .form-control le filtre de lieu, en pilule.
   Elle gagne en revanche sur le défaut de Bootstrap, qui pèse pareil mais est chargé avant.

   Ne sont pas visés du tout : .form-check-input (case, radio), .form-switch, les ChoicePill et
   le Slider — ils ne portent pas ces classes. La densité vaut pour la SURFACE OÙ L'ON SAISIT,
   pas pour tout ce qui vit dans un formulaire. */
:where(.club-layout, .photographer-layout){
    --field-radius: var(--sp-radius-md);
}

/* Les surfaces de saisie consomment cette valeur — y compris celles qui TIENNENT LIEU de champ
   sans en porter la classe : la zone qui affiche le fichier retenu, le conteneur qui dessine le
   champ à la place du select qu'il enveloppe. Écrite sur la seule classe des champs, la règle
   les oubliait, et elles restaient au coin d'accueil au milieu de vrais champs resserrés — 4px
   d'écart sur deux bords voisins, que l'œil relève aussitôt (fiche input, « ce qui tient lieu de
   champ suit la règle du champ »).

   Le préfixe est `--field-` et non `--sp-` : ce n'est pas un token du DS mais un véhicule
   d'implémentation, et les deux ne doivent pas se confondre dans la feuille. */
.form-control,
.form-select,
.cover-picker-name{
    border-radius: var(--field-radius);
}

/* PANNEAU DE SUGGESTIONS d'un champ (adresse, ville). C'est le panneau de la SearchBar, pas un
   Dropdown : il ne règle rien, il montre ce qu'on a écrit — donc ni titre ni pied d'actions
   (fiche input, « un champ qui suggère ouvre le panneau de la recherche »).

   Surface flottante NUE : `bg.surface`, `radius.lg`, `shadow.pop` — l'ombre des surfaces qui
   s'ouvrent —, et SANS filet : l'ombre ou le filet, jamais les deux (fiche card). Il pend à
   `space.2` du champ, comme toute surface qui s'ouvre, au lieu de lui être collé.

   Ces règles vivent ici et non dans le contrôleur Stimulus, qui les posait en `style.cssText`
   avec des couleurs en dur (#dee2e6, #f8f9fa) : un panneau stylé en JavaScript échappe aux
   tokens, donc au thème, et personne ne le trouve en cherchant dans la feuille. */
/* L'ancre du panneau : c'est le conteneur du champ qui le porte. */
.places-anchor{
    position: relative;
}

.places-suggestions{
    position: absolute;
    top: calc(100% + var(--sp-space-2));
    left: 0;
    right: 0;
    z-index: 1050;
    display: none;
    max-height: 60vh;
    overflow-y: auto;
    background-color: var(--sp-color-bg-surface);
    border-radius: var(--sp-radius-lg);
    box-shadow: var(--sp-shadow-pop);
}

.places-suggestions.is-open{
    display: block;
}

.places-suggestion{
    display: flex;
    align-items: center;
    gap: var(--sp-space-3);
    padding: var(--sp-space-3) var(--sp-space-4);
    cursor: pointer;
    color: var(--sp-color-text-default);
}

/* Le glyphe d'une installation référencée ne doit pas se laisser écraser par un nom long. */
.places-suggestion-icon{
    display: inline-flex;
    flex: 0 0 auto;
    color: var(--sp-color-text-brown);
}

/* En-tête de GROUPE, pas titre de panneau : il dit de quelle nature sont les lignes qui suivent
   — une installation référencée ou une adresse (fiche search-bar). Même traitement que les
   suggestions de la recherche globale, et il n'apparaît que si les deux groupes coexistent. */
.places-suggestions-title{
    padding: var(--sp-space-3) var(--sp-space-4) var(--sp-space-1);
    font-size: var(--sp-font-size-meta);
    font-weight: var(--sp-font-weight-title);
    color: var(--sp-color-text-brown);
}

/* Survol et parcours au clavier sont le MÊME état : la ligne visée. Les distinguer ferait deux
   surlignages pour une seule notion, et le clavier hériterait du plus discret. */
.places-suggestion:hover,
.places-suggestion.is-active{
    background-color: var(--sp-color-bg-cream);
}

.places-suggestion:first-child{
    border-top-left-radius: var(--sp-radius-lg);
    border-top-right-radius: var(--sp-radius-lg);
}

.places-suggestion:last-child{
    border-bottom-left-radius: var(--sp-radius-lg);
    border-bottom-right-radius: var(--sp-radius-lg);
}

/* EN-TÊTE DE GROUPE : il mène la liste. Le navigateur le rend en gris, donc plus pâle que les
   options qu'il coiffe — hiérarchie exactement inversée, alors que c'est lui qu'on balaie pour
   se repérer sur cent options. Il reprend le ton du texte et se distingue par la GRAISSE, pas
   par la couleur : deux gris disent deux niveaux d'importance, une graisse dit deux natures —
   un titre et ses entrées (fiche select). */
.form-select optgroup{
    color: var(--sp-color-text-default);
    font-weight: var(--sp-font-weight-title);
}

/* Les options sont les ENFANTS du groupe : elles héritent de sa graisse, et sans ce retour
   explicite la liste devient uniformément grasse — la distinction qu'on vient de créer
   disparaîtrait (fiche select, « les options héritent de leur optgroup »). */
.form-select optgroup option{
    font-weight: var(--sp-font-weight-body);
}

/* Un textarea grandit sur plusieurs lignes : il ne prend pas la hauteur fixe des champs d'une
   ligne, mais garde le même filet, le même rayon et le même fond blanc (attribut `rows` pour la
   hauteur de départ). */
.photographer-layout textarea.form-control,
.club-layout textarea.form-control{
    height: auto;
    min-height: calc(52px + calc(var(--bs-border-width) * 2));
    padding-top: var(--sp-space-3);
    padding-bottom: var(--sp-space-3);
}

/* Sélecteur de couverture : un champ qui porte le nom du fichier (mêmes filet, rayon, fond que les
   inputs texte) et le bouton ink « Choisir un fichier » à sa droite. Le sélecteur natif est masqué
   dans le bouton. */
.cover-picker {
    display: flex;
    align-items: stretch;
    gap: var(--sp-space-3);
}

.cover-picker-name {
    flex: 1 1 auto;
    display: flex;
    align-items: center;
    min-width: 0;
    min-height: calc(52px + calc(var(--bs-border-width) * 2));
    padding: 0 var(--sp-space-4);
    background-color: var(--sp-color-bg-surface);
    border: var(--bs-border-width) solid var(--sp-color-border-cream);
    color: var(--sp-color-text-muted);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.cover-picker-btn {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
}

/* `text.muted`, pas `bg.grey` : un token de SURFACE employé comme couleur de texte donnait un
   placeholder invisible (un gris de fond sur du blanc, ~1:1) sans qu'aucune règle n'ait l'air
   violée — les deux se ressemblent dans le code, jamais à l'écran (fiche input). */
.photographer-layout .form-control::placeholder,
.club-layout .form-control::placeholder{
    color: var(--sp-color-text-muted);
    opacity: 1;
}

/* DANS un label flottant, le placeholder doit rester TRANSPARENT : c'est le libellé flottant qui
   tient sa place au repos. La règle de placeholder visible ci-dessus le rendait lisible, et libellé
   flottant + placeholder se superposaient sur un champ vide (fiche input). Le placeholder reparaît
   au focus, quand le libellé remonte. */
.photographer-layout .form-floating > .form-control::placeholder,
.club-layout .form-floating > .form-control::placeholder{
    color: transparent;
}

/* Champ DATE (`.is-datefield`) : exception au repos ci-dessus. Le sélecteur (flatpickr) affiche
   toujours un gabarit « jj/mm/aaaa », le libellé ne peut donc pas lui servir de placeholder. On
   flotte le libellé en permanence et on garde le gabarit lisible dessous. Les valeurs de flottement
   sont celles de Bootstrap ; le champ réserve la place en haut pour le libellé remonté. */
.form-floating.is-datefield > label {
    opacity: .65;
    transform: scale(.85) translateY(-.5rem) translateX(.15rem);
}

.form-floating.is-datefield > .form-control {
    padding-top: 1.625rem;
    padding-bottom: .625rem;
}

.photographer-layout .form-floating.is-datefield > .form-control::placeholder,
.club-layout .form-floating.is-datefield > .form-control::placeholder {
    color: var(--sp-color-text-muted);
}

/* LE FOND DU CHAMP NE CHANGE PAS AU FOCUS (fiche input). Ces mêmes sélecteurs teintaient le
   champ actif en bg.grey dans l'espace connecté — donc dans tous les formulaires du produit.
   Deux torts : le doublon (la bordure orange et l'anneau disent déjà où l'on est, et il n'y a
   qu'un champ focalisé par écran) et surtout l'inversion de sens — un neutre clair sous un
   contrôle dit le REPOS dans ce système (bg.control), si bien que le champ prenait l'aspect de
   ce qu'on ne touche pas au moment où l'on y écrit. La règle est supprimée, pas neutralisée :
   .form-control garde son bg.surface posé plus haut, focus compris.

   Elle emportait aussi la SearchBar au passage : .search-bar .form-control:focus pose un fond
   transparent (le verre porte le sien) à spécificité égale mais PLUS HAUT dans le fichier — une
   barre de recherche rencontrée dans l'espace connecté repassait donc au gris. */

.photographer-layout .form-control[type=file],
.club-layout .form-control[type=file]{
    line-height: 34px;
}

/* Vich Image Preview - limit size for responsive */
.photographer-layout .vich-image img,
.club-layout .vich-image img {
    max-width: 300px;
    max-height: 200px;
    width: auto;
    height: auto;
    object-fit: contain;
    border-radius: var(--bs-border-radius);
}

@media (max-width: 575px) {
    .photographer-layout .vich-image img,
    .club-layout .vich-image img {
        max-width: 100%;
        max-height: 150px;
    }
}

/* COMPONENTS */

/* Accordion */

.accordion {
    --bs-accordion-active-bg: transparent;
    --bs-accordion-active-color: var(--bs-primary);
    --bs-accordion-btn-focus-box-shadow: none;
}

.accordion-button {
    font-size: 16px;
    font-weight: 600;
}

/* Alert */

.alert{
    border: none;
}

.alert-success{
    background-color: var(--success-light);
    color: var(--success);
}

.alert-success.border{
    border-color: rgba(54, 168, 102, 0.22)!important;
}

.alert-info{
    background-color: var(--info-light);
    color: var(--info);
}

.alert-light{
    background-color: var(--light);
    color: var(--dark-grey);
}

.alert-warning{
    background-color: var(--warning-light);
    color: var(--warning);
}

.alert-danger{
    background-color: var(--danger-light);
    color: var(--danger);
}

/* Badges */

/* Badge : le libellé s'écrit comme il se lit — Inter, méta 13px, graisse de corps,
   sans capitales ni interlettrage (fiche badge) */
.badge {
    --bs-badge-font-size: var(--sp-font-size-meta);
    /* Padding vertical serré : le badge reste compact (fiche badge) */
    --bs-badge-padding-y: var(--sp-space-1);
    --bs-badge-padding-x: var(--sp-space-2);
    --bs-badge-font-weight: var(--sp-font-weight-body);
    --bs-badge-border-radius: var(--sp-radius-sm);
    font-family: var(--sp-font-family-base), sans-serif;
    line-height: 1;
}

.badge-success{
    background-color: var(--success-light);
    color: var(--success);
}

.badge-info{
    background-color: var(--info-light);
    color: var(--info);
}

/* Ton neutral du DS : fond crème, texte ink */
/* Ton « neutral » de la fiche badge : creux crème (bg.sunken, #EFE9DD), texte ink. Pas
   bg.cream (#F5F3EB), trop proche du fond de page pour que l'étiquette se détache. */
.badge-light{
    background-color: var(--sp-color-bg-sunken);
    color: var(--sp-color-text-default);
}

/* Ton live du DS : orange, évènement en direct / du jour */
.badge-live{
    background-color: var(--sp-color-accent-selected);
    color: var(--sp-color-text-inverse);
}

/* Ton verre du DS : compteurs et méta posés sur photo. Verre CLAIR (DESIGNAPP, « verre
   dépoli ») : 7 % de blanc sur la photo floutée derrière, ombre large, halo intérieur ; son
   liseré lumineux est posé plus bas, avec la lentille. */
.badge-glass{
    display: inline-flex;
    align-items: center;
    gap: 5px;
    background-color: var(--sp-glass-overlay-bg);
    color: var(--sp-color-text-inverse);
    border: 0;
    box-shadow: var(--sp-glass-overlay-shadow);
    backdrop-filter: blur(var(--sp-glass-overlay-blur));
    -webkit-backdrop-filter: blur(var(--sp-glass-overlay-blur));
}

/* Ton dark du DS : méta sur fond clair */
.badge-dark{
    background-color: var(--sp-color-bg-dark);
    color: var(--sp-color-text-inverse);
}

/* Ton count du DS : pastille ronde blanche, chiffre ink (panier, cloche) */
.badge-count{
    --bs-badge-border-radius: var(--sp-radius-full);
    min-width: 18px;
    height: 18px;
    --bs-badge-padding-y: 0;
    --bs-badge-padding-x: 5px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background-color: var(--sp-color-bg-surface);
    color: var(--sp-color-text-default);
    font-size: var(--sp-font-size-12);
    font-weight: var(--sp-font-weight-bold);
    letter-spacing: var(--sp-font-tracking-tight);
}

/* SportBadge : glyphe de sport sur carré arrondi teinté
   (designsystem/spicto/app/components/sport-badge.md) */
.sport-badge{
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    border-radius: 28%;
    background-color: var(--sp-color-accent-soft);
    color: var(--sp-color-accent-selected);
}

.sport-badge svg{
    display: block;
}

.sport-badge-round{
    border-radius: var(--sp-radius-full);
}

.sport-badge-cream{
    background-color: var(--sp-color-bg-cream);
    color: var(--sp-color-text-brown);
}

.sport-badge-ink{
    background-color: var(--sp-color-bg-dark);
    color: var(--sp-color-text-inverse);
}

.sport-badge-green{
    background-color: color-mix(in srgb, var(--sp-color-feedback-success) 12%, var(--sp-color-cream-0));
    color: var(--sp-color-feedback-success);
}

.sport-badge-blue{
    background-color: color-mix(in srgb, var(--sp-color-feedback-info) 12%, var(--sp-color-cream-0));
    color: var(--sp-color-feedback-info);
}

.sport-badge-sm{ width: 18px; height: 18px; }
.sport-badge-sm svg{ width: 10px; height: 10px; }
.sport-badge-md{ width: 40px; height: 40px; }
.sport-badge-md svg{ width: 18px; height: 18px; }
.sport-badge-lg{ width: 64px; height: 64px; }
.sport-badge-lg svg{ width: 24px; height: 24px; }
.sport-badge-fill{ width: 100%; height: 100%; }
.sport-badge-fill svg{ width: 33%; height: 33%; }

/* En-tête de section (DESIGNAPP) : titre h3 + icône à gauche, « Voir tout » ink à droite */
.sec-header{
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: var(--sp-space-3);
}

.sec-header-title{
    display: flex;
    align-items: center;
    gap: var(--sp-space-2);
    font-size: var(--sp-font-size-h3);
    font-weight: var(--sp-font-weight-title);
}

/* Dans un en-tête, l'espacement appartient au `.sec-header`, jamais au titre : posée sur un
   enfant de flex, une marge de titre rallongerait la ligne d'en-tête d'autant. Deux classes
   parce que `.photographer-layout h3` (0,1,1) impose encore sa marge de 16px aux h3 des espaces
   pro. Hors en-tête (checkout), le titre garde ses utilitaires de marge. */
.sec-header .sec-header-title{
    margin: 0;
}

/* Le titre d'un bloc DANS une carte, et non d'une section : size.h4 (fiche dropzone). Il ne
   coiffe pas une part de l'écran mais un contenu à l'intérieur d'une carte — à size.h3 il
   pèserait autant que le titre de l'étape qui l'englobe. Ce n'est pas le mésusage que le tronc
   nomme trois fois : on ne rétrécit pas ici pour gagner de la place, mais parce que le bloc ne
   réclame pas le rang qu'il prenait. */
.sec-header-title-sub{
    font-size: var(--sp-font-size-h4);
}

/* Décompte : le pendant du lien « Voir tout », quand la section montre tout */
/* Le décompte d'une section, et l'identification d'une carte de parcours (« Grind Séries ·
   Dépôt 4 ») : même rendu, deux rôles. Les deux accompagnent sans porter (DESIGNAPP). */
.sec-header-count,
.sec-header-context{
    font-size: var(--sp-font-size-label);
    font-weight: var(--sp-font-weight-body);
    color: var(--sp-color-text-muted);
}

/* La phrase qui CADRE une section, sous l'en-tête et avant le premier champ : elle instruit,
   elle conditionne ou elle rassure. Ce n'est pas de la méta — le décompte accompagne le titre,
   celle-ci cadre ce qui vient après —, donc jamais muted : estomper reviendrait à parier qu'on
   la lira quand même. C'est la TAILLE qui la range sous le titre, pas la couleur (DESIGNAPP, et
   tronc « size.meta est une taille, pas un registre »). La mention fine d'un champ garde son
   muted, elle. */
.sec-note{
    font-size: var(--sp-font-size-meta);
    letter-spacing: var(--sp-font-tracking-meta);
    color: var(--sp-color-text-default);
}

/* CHAMPS FACULTATIFS : un champ ne se dessine pas tant qu'on ne l'a pas demandé (DESIGNAPP).
   Les propositions en tête, les champs ouverts dessous — la liste du haut rétrécit pendant que
   celle du bas grandit, donc le point d'ajout ne bouge pas d'un ajout à l'autre. */
.field-offers{
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--sp-space-1);
}

/* La proposition. Gouttière horizontale nulle : sans surface, il n'y a rien dont se retirer, et
   le glyphe s'aligne ainsi sur le bord du texte qui la surmonte plutôt que de flotter à droite. */
.field-offer{
    display: inline-flex;
    align-items: center;
    gap: var(--sp-space-2);
    padding-left: 0;
    padding-right: 0;
}

/* `hidden` doit gagner sur le `display` que ces deux règles posent : à spécificité égale, c'est
   la dernière déclarée qui l'emporterait, et la proposition cachée resterait visible. */
.field-offer[hidden],
.field-item[hidden]{
    display: none;
}

/* La gouttière est portée par les items, pas par un conteneur : la liste des champs ouverts est
   vide au premier passage, et un margin sur le conteneur y laisserait un blanc sans contenu. */
.field-item{
    margin-top: var(--sp-space-3);
}

.field-row{
    display: flex;
    align-items: center;
    gap: var(--sp-space-2);
}

/* Le champ prend la largeur ; `min-width: 0` l'autorise à se réduire — sans lui, la largeur
   minimale de l'input pousserait la croix hors de la carte sur une laize étroite. */
.field-row > .form-floating{
    flex: 1 1 auto;
    min-width: 0;
}

/* Croix de retrait : IconButton variant ghost — icône seule, sans fond, pour une action de
   liste. La cible 44px vient de .btn-circle ; la couleur est celle du ghost (text.default). */
.field-row-remove{
    color: var(--sp-color-text-default);
}

/* En-tête d'une carte de parcours : le seul en-tête suivi d'un filet. Il sépare l'identité de
   la carte, qui ne change pas d'une étape à l'autre, du contenu de l'étape, qui change à chaque
   écran (DESIGNAPP). Un en-tête de section ordinaire n'en porte pas. */
.sec-header--flow{
    padding-bottom: var(--sp-space-4);
    border-bottom: 1px solid var(--sp-color-border-default);
    margin-bottom: var(--sp-space-4);
}

.sec-header-link{
    font-size: var(--sp-font-size-label);
    font-weight: var(--sp-font-weight-title);
    color: var(--sp-color-text-default);
    text-decoration: none;
}

/* Rail Live (DESIGNAPP, carrousel) : les cartes mises en avant défilent
   horizontalement, la suivante déborde du bord ; pastilles indicatrices.
   `.pro-rail` est la même piste : elle partage la mécanique et ne garde en propre que les
   largeurs de tuile (voir « Spicto Pro : le rail des avantages » plus bas). */
.event-rail{
    display: flex;
    /* Hauteurs égales : les tuiles côte à côte s'étirent sur la plus haute (fiche
       event-card-highlighted). C'est le défaut flex, rendu explicite. */
    align-items: stretch;
    gap: var(--sp-space-3);
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scrollbar-width: none;
    padding-bottom: var(--sp-space-1);
}

.event-rail::-webkit-scrollbar{
    display: none;
}

/* Mobile : une carte presque pleine largeur, 10% de la suivante coupée net.
   Elle est atténuée : elle s'annonce sans se donner (fiche event-rail). */
@media (max-width: 991.98px) {
    .event-rail > *{
        flex: 0 0 calc((100% - var(--sp-space-3)) / 1.1);
    }

    .event-rail > *:not(.is-current){
        opacity: .5;
        transition: opacity var(--sp-duration-base) var(--sp-easing-standard);
    }

    /* Sous le seuil (1 carte) : pas de piste, la carte prend toute la largeur */
    .event-rail-section[data-items="1"] .event-rail > *{
        flex-basis: 100%;
        opacity: 1;
    }

    /* Plus de plafond mobile : le rail montre tous les évènements du Live (retour client,
       sept. 2026) ; « Voir tout » ouvre la grille compacte. */
}

/* Desktop : trois cartes, puis 50% de la quatrième, à pleine opacité */
@media (min-width: 992px) {
    .event-rail > *{
        flex: 0 0 calc((100% - 3 * var(--sp-space-3)) / 3.5);
    }

    /* Sous le seuil (≤ 3 cartes), aucune surcharge : les cartes gardent la largeur
       qu'elles auraient eue dans la piste et s'alignent à gauche, le reste de la ligne
       demeure vide. Une carte n'a pas de raison de grossir parce qu'elle est seule
       (fiche event-rail) — les étaler donnait une tuile de 1215px de large à une carte
       seule. Sur mobile la règle ne s'applique pas : la carte y occupe déjà presque
       toute la largeur. */
}

@media (prefers-reduced-motion: reduce) {
    .event-rail > *:not(.is-current){
        transition: none;
    }
}

/* EventCardHighlighted DS : plein cadre 3:2, scrim bas-vers-haut, texte blanc
   (designsystem/spicto/app/components/event-card-highlighted.md) */
.event-highlighted{
    position: relative;
    /* Colonne flex, haut et bas répartis : le badge/compteur et le bloc de texte occupent
       deux zones séparées de la tuile — ils ne se chevauchent jamais, quel que soit le
       contenu (fiche event-card-highlighted, règle « aucun chevauchement »). */
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    /* 3:2 TENU au redimensionnement : le cadre ne s'étire pas pour faire de la place, c'est
       le contenu qui s'y adapte (titre borné à deux lignes). Une tuile qui grandit avec son
       texte casse la rangée — ses voisines s'alignent sur la plus haute et cessent d'être au
       format. Le plancher de 248px est la seule dérogation, et seulement vers le bas (fiche
       event-card-highlighted). */
    aspect-ratio: 3 / 2;
    min-height: 248px;
    /* Le plancher ne joue que vers le BAS (fiche event-card-highlighted, « la seule
       dérogation au ratio, et elle ne joue que vers le bas »). Sans cette borne il joue aussi
       vers la droite : dans une colonne plus étroite que 372px, `aspect-ratio` recalcule la
       LARGEUR depuis les 248px du plancher, la tuile déborde de son conteneur et la page part
       en défilement horizontal. En piste (`event-rail`) le débord ne se voyait pas — les
       cartes y ont une base flex explicite. Il apparaît partout où la tuile est un bloc
       ordinaire : la grille de gestion, celle de « Récent ». */
    max-width: 100%;
    border-radius: var(--sp-radius-xl);
    overflow: hidden;
    scroll-snap-align: start;
    background-color: var(--sp-color-bg-dark);
    text-decoration: none;
    transition: box-shadow var(--sp-duration-fast) var(--sp-easing-standard);
}

/* L'ombre seule : la tuile ne se déplace pas. Elle porte une photographie plein cadre, et
   déplacer la surface déplace l'image — sur une grille, le moindre passage de souris ferait
   sautiller la vignette qu'on est en train de lire (tronc DESIGN.md, Motion). */
.event-highlighted:hover{
    box-shadow: var(--sp-shadow-md);
}

.event-highlighted:focus-visible{
    outline: none;
    box-shadow: var(--sp-shadow-ring);
}

@media (prefers-reduced-motion: reduce) {
    .event-highlighted{
        transition: none;
    }
}

.event-highlighted-cover{
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    z-index: 0;
}

/* La photo n'est plus assombrie en entier (retour client) : seul le scrim porte le texte. Le
   compact du Live garde son voile, qu'il n'était pas demandé de changer. */
.event-highlighted-short .event-highlighted-cover{
    filter: brightness(.62) saturate(.9);
}

/* Le haut (badge de date + compteur) est un enfant en flux, ancré en haut de la colonne :
   il ne recouvre plus le scrim, la répartition space-between les sépare. */
.event-highlighted-top{
    position: relative;
    z-index: 1;
    padding: var(--sp-space-3);
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: var(--sp-space-2);
}

/* Le badge d'échéance et le compteur partagent une ligne, ils doivent donc partager une
   hauteur. Le ton verre porte un liseré d'1px, les tons pleins n'en ont pas : sans cette
   bordure transparente, le `danger` est 2px plus court que le compteur d'en face — et l'écart
   se voit d'une carte à l'autre, puisque dans son autre ton le même badge s'aligne au pixel.
   `:not(.badge-glass)` pour ne pas effacer le liseré du verre, qui lui est structurel. */
.event-highlighted-top .badge:not(.badge-glass){
    border: 1px solid transparent;
    /* Et le même décollement que le verre d'en face : c'est la photo dessous qui l'exige, pas
       la matière du badge (cf. `glass.overlay.lift`). */
    box-shadow: var(--sp-glass-overlay-lift);
}

/* Variant short : la même tuile, en dense. Quatre écarts, pas un de plus
   (fiche event-card-highlighted, variant `short`). */

/* 1. aucune hauteur imposée : ni 4:3, ni plancher 248px, le texte donne la hauteur */
.event-highlighted-short{
    aspect-ratio: auto;
    min-height: auto;
}

/* 2. le titre est clampé à 1 seule ligne (au lieu de 2) : la densité prime */
.event-highlighted-short .event-highlighted-title{
    -webkit-line-clamp: 1;
    line-clamp: 1;
}

/* La ligne d'en-tête (sport + badge) respire au-dessus du bloc titre/méta : un espace
   l'en sépare, elle ne lui est pas collée (fiche event-card-highlighted, variant short). */
.event-highlighted-short .event-highlighted-sport-line{
    margin-bottom: var(--sp-space-2);
}

/* 3. le badge de date quitte le haut (désormais vide) pour la ligne du sport, en vis-à-vis */
.event-highlighted-short .event-highlighted-top{
    display: none;
}

/* Le scrim est un enfant en flux, ancré en bas de la colonne (fiche event-card-highlighted).
   Le dégradé est porté par la carte entière (::after), pas par ce bloc. */
.event-highlighted-scrim{
    position: relative;
    z-index: 1;
    padding: var(--sp-space-4);
    display: flex;
    flex-direction: column;
    gap: 2px;
    color: var(--sp-color-text-inverse);
}

/* Dégradé de la maquette (retour client) sur toute la carte, au-dessus de la photo et sous le
   texte : #5D5D5D à 0 % en haut, #2E2E2E à 34 % au milieu, noir plein en bas. */
.event-highlighted::after{
    content: "";
    position: absolute;
    inset: 0;
    z-index: 0;
    background: linear-gradient(to bottom, rgba(93, 93, 93, 0) 0%, rgba(46, 46, 46, .34) 50%, #000 100%);
    pointer-events: none;
}

/* Le compact du Live garde son voile et son dégradé court, qu'il n'était pas demandé de changer. */
.event-highlighted-short::after{
    display: none;
}

.event-highlighted-short .event-highlighted-scrim{
    background: linear-gradient(to top, var(--sp-color-overlay-scrim), transparent);
}

/* Variant header (fiche event-card-highlighted, variant `header`) : coiffe la page
   évènement. Comme short — hauteur libre, scrim relatif —, mais pleine largeur, une hauteur
   minimale pour que la photo respire, et les actions de page dans les coins hauts. Ce n'est
   pas un lien : c'est un <section>, il ne défile pas plus qu'une autre section (plus de
   sticky). */
.event-highlighted-header{
    /* flex colonne, texte poussé en bas : les actions (absolues) restent en haut, le scrim
       descend au ras du bord bas, son dégradé couvre alors toute la moitié basse sans laisser
       de photo nue en dessous. */
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    aspect-ratio: auto;
    min-height: 248px;
}

.event-highlighted-header .event-highlighted-scrim{
    position: relative;
    /* le dégradé démarre plus haut pour couvrir généreusement, et laisse la place aux
       actions au-dessus du texte */
    padding-top: var(--sp-space-16);
}

/* Exception assumée au space.4 des cartes photo (fiche card, fiche event-card-highlighted) :
   le header qui coiffe VRAIMENT la page publique de l'évènement — et lui seul, via --page —
   ouvre sa gouttière de scrim à space.6 (24px). Sur son propre écran plein cadre il porte son
   titre en display (h1/40px), qu'un scrim à 16px lirait à l'étroit. Les reprises du même chrome
   (aside de dépôt, aperçu de création, en --labelled) gardent le space.4. Le haut garde sa
   réserve (space.16) pour dégager les actions de coin — seuls les trois autres côtés à 24px. */
.event-highlighted-header--page .event-highlighted-scrim{
    padding: var(--sp-space-16) var(--sp-space-6) var(--sp-space-6);
}

/* Actions de page dans les coins hauts, sur le scrim : retour à gauche, menu/partage à
   droite. IconButton clairs sur la photo sombre. */
.event-highlighted-header .event-highlighted-actions{
    position: absolute;
    top: var(--sp-space-4);
    left: var(--sp-space-4);
    right: var(--sp-space-4);
    z-index: 2;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-space-2);
}

/* Deux retours, deux formes (fiche event-card-highlighted) : le DISQUE revient d'un cran, le
   LIBELLÉ à côté quitte le parcours pour un endroit nommé. Ils se distinguent par la forme, pas
   par la couleur — l'un est un disque sans mot, l'autre un mot sans disque. */
.event-back{
    display: inline-flex;
    align-items: center;
    gap: var(--sp-space-3);
    min-width: 0;
}

/* Une MÉTA, pas un titre (fiche event-card-highlighted) : le libellé partage la surface avec le
   nom de l'évènement, qui est le sujet de la carte, et un chemin de retour ne pèse pas autant que
   ce sur quoi on travaille. Il gardait `font.size.16` — une PRIMITIVE, que le DS interdit à un
   composant de lire — en graisse de titre ; il passe à size.meta / weight.body. Le blanc plein ne
   suit pas la descente : c'est la taille qui le range, pas la couleur, et il doit rester lisible
   sur la photo. */
.event-back-label{
    color: var(--sp-color-text-inverse);
    font-size: var(--sp-font-size-meta);
    font-weight: var(--sp-font-weight-body);
    text-decoration: none;
    /* Le libellé cède avant la carte : sur une colonne étroite il se tronque plutôt que de
       pousser le badge de date hors du cadre. */
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.event-back-label:hover{
    color: var(--sp-color-text-inverse);
    text-decoration: underline;
}

/* Scrim HAUT, et seulement quand une action de coin porte un libellé (fiche
   event-card-highlighted). Un disque verre se suffit à lui-même ; une phrase posée sur la photo
   n'a rien sous elle, et sa lisibilité dépendrait du cliché. Symétrique de celui du bas, borné
   à la hauteur de la ligne d'actions : assombrir plus mangerait la photo par les deux bouts. */
.event-highlighted-header--labelled::before{
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: calc(var(--sp-control-icon-button) + var(--sp-space-8));
    z-index: 1;
    background: linear-gradient(to bottom, var(--sp-color-overlay-scrim), transparent);
    pointer-events: none;
}

/* Ligne du sport : en short, le sport et le badge de date s'y font face (space-between) ;
   en version pleine, le sport y est seul, donc calé à gauche (fiche event-card-highlighted). */
.event-highlighted-sport-line{
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-space-2);
}

.event-highlighted-sport{
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: var(--sp-font-size-12);
    font-weight: var(--sp-font-weight-title);
}

.event-highlighted-title{
    /* Blanc explicite : le scrim le donne par héritage au span du composant, mais un <h1>
       (variant header) a sa couleur de base et casserait l'héritage. Tout le texte du
       scrim est blanc (fiche event-card-highlighted). */
    color: var(--sp-color-text-inverse);
    font-size: var(--sp-font-size-h3);
    font-weight: var(--sp-font-weight-title);
    letter-spacing: var(--sp-font-tracking-tight);
    margin: 0;
    /* 2 lignes maximum, tronqué proprement par une ellipsis (fiche event-card-highlighted) :
       borne le bloc de texte et le tient à distance des superpositions du haut. */
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    overflow: hidden;
}

/* Header : la page de l'évènement montre son titre en entier — pas de troncature sur
   sa propre page (le clamp 2 lignes ne vaut que pour les tuiles en liste/rail). */
.event-highlighted-header .event-highlighted-title{
    display: block;
    -webkit-line-clamp: none;
    line-clamp: none;
    overflow: visible;
}

/* Display de page (h1, 40px) réservé au titre qui EST le hero : le <h1> de la vraie page
   évènement, unique titre de document de l'écran. Le même chrome header est réutilisé en aside
   de dépôt et en aperçu de création, mais avec un <p> — pas un second h1 —, et ce titre-là
   reste à l'échelle carte (h3, règle de base). Le poids `weight.title` (Semibold 600) et Inter
   sont déjà hérités de la base : seule la taille change ici.

   Et seulement sur DESKTOP (mobile-first, fiche event-card-highlighted) : sur mobile la card
   prend toute la largeur et 40px sur la photo écraserait le scrim et casserait sur plusieurs
   lignes. Sous 992px, aucune règle ici — le titre retombe sur l'échelle de base (h3, 20px). */
@media (min-width: 992px) {
    .event-highlighted-header h1.event-highlighted-title{
        font-size: var(--sp-font-size-h1);
    }
}

.event-highlighted-meta{
    font-size: var(--sp-font-size-meta);
    font-weight: var(--sp-font-weight-body);
}

/* Header : « aujourd'hui » remplace la date et passe à l'orange de marque (fiche
   event-card-highlighted, variant header). */
/* Variant `manage` : l'état temporel n'est plus un badge de coin, il s'écrit dans la méta entre
   le lieu et la date, dans la couleur de son état (fiche event-card-highlighted). Un badge
   signale une exception ; sur « Mes évènements » toutes les tuiles en portent un, et ce qui est
   partout ne signale plus rien.

   Seul endroit du système où plusieurs couleurs se posent sur un scrim : la méta n'y dit plus
   une date mais un STATUT, qu'on veut balayer sans lire. Les trois tons y tiennent l'AA — il n'y
   a pas de quatrième ton parce que `feedback.warning` n'a pas de variante lisible sur ce sol
   (cf. tronc) ; l'échéance parle donc le rouge de l'expiration, dont elle est le prélude. */
.event-highlighted-when{
    font-weight: var(--sp-font-weight-title);
}

.event-highlighted-when--now{
    color: var(--sp-color-accent-selected);
}

/* Le vert clair, pas le vert-sarcelle de feedback.success : celui-ci disparaît sur un scrim.
   Le rôle est emprunté — il ne dit pas une réussite, il dit ce qui est encore devant. */
.event-highlighted-when--future{
    color: var(--sp-color-feedback-success-fill);
}

/* La variante claire du rouge, pas `feedback.danger` : sur un scrim, red.600 tombe à 2,59:1 et
   passe pour du brun (cf. tronc, délégation selon la surface). */
.event-highlighted-when--danger{
    color: var(--sp-color-feedback-danger-on-dark);
}

/* La plage se dit avec la flèche du système, comme le résumé « début → fin » du Calendar
   (fiche calendar) : le tiret est écarté des contenus, et deux dates accolées se liraient
   comme deux évènements. L'inline-flex n'est là que pour aligner le glyphe sur la ligne de
   texte, sans nudge en dur. */
.event-highlighted-range{
    display: inline-flex;
    align-items: center;
    gap: var(--sp-space-1);
}

/* --- EventRail : commandes et repères (fiche event-rail) -------------------
   Les sélecteurs passent par .event-rail-section : ils l'emportent sur .btn-circle
   sans dépendre de l'ordre du fichier. Chaque commande ne sert qu'un support :
   les pastilles le doigt, les chevrons la souris — jamais les deux ensemble. */

.event-rail-viewport{
    position: relative;
}

/* Pastilles : mobile seulement, à 14px sous la carte dont les 4px de la piste (maquette) */
.event-rail-section .rail-dots{
    display: flex;
    gap: 6px;
    justify-content: center;
    padding-top: 10px;
}

.rail-dot{
    width: var(--sp-carousel-dot);
    height: var(--sp-carousel-dot);
    border-radius: var(--sp-radius-full);
    background-color: var(--sp-color-border-cream);
}

.rail-dot.active{
    background-color: var(--sp-color-accent-selected);
}

/* Chevrons : desktop seulement */
.event-rail-section .rail-control{
    display: none;
}

@media (min-width: 992px) {
    .event-rail-section .rail-dots{
        display: none;
    }

    .event-rail-section .rail-control:not(.d-none){
        display: inline-flex;
        position: absolute;
        top: 50%;
        transform: translateY(-50%);
        z-index: 3;
        box-shadow: var(--sp-shadow-md);
    }

    /* Une commande ne se dérobe pas sous le doigt : pas de press ici */
    .event-rail-section .rail-control:not(:disabled):active{
        transform: translateY(-50%);
    }

    /* La piste court désormais jusqu'aux bords de la Card : les chevrons se calent dans
       la gouttière rendue à la piste, et gardent la place qu'ils occupaient (12px du bord
       de la Card) — sans ce report, ils sortiraient de la Card. */
    .event-rail-section .rail-control-prev{
        left: var(--sp-space-3);
    }

    .event-rail-section .rail-control-next{
        right: var(--sp-space-3);
    }
}

/* Pastilles indicatrices du rail : active orange, inactives filet chaud */
/* Avatar DS (designsystem/spicto/app/components/avatar.md) : rond, photo cover,
   repli en initiales crème/brun, jamais d'anneau orange décoratif */
.avatar{
    display: inline-flex;
    flex-shrink: 0;
    border-radius: var(--sp-radius-full);
    overflow: hidden;
}

/* xs : la seule taille qui se pose DANS une ligne de texte (fiche avatar) */
.avatar-xs{ width: var(--sp-avatar-xs); height: var(--sp-avatar-xs); }
.avatar-sm{ width: var(--sp-avatar-sm); height: var(--sp-avatar-sm); }
.avatar-md{ width: var(--sp-avatar-md); height: var(--sp-avatar-md); }
/* lg et xl : la personne est le sujet de la surface (Card variant `photo`). Le même rôle à
   deux dispositions — lg quand le portrait est AU-DESSUS du nom et partage sa hauteur, xl
   quand il est À CÔTÉ et que la hauteur se libère (fiche avatar). */
.avatar-lg{ width: var(--sp-avatar-lg); height: var(--sp-avatar-lg); }
.avatar-xl{ width: var(--sp-avatar-xl); height: var(--sp-avatar-xl); }

/* Ce qui garantit le cercle en rangée souple est déjà là : `flex-shrink: 0` sur `.avatar`
   l'empêche d'être comprimé, et sa hauteur EXPLICITE l'empêche d'être étiré (l'étirement
   transverse d'un flex ne s'applique qu'à une taille `auto`). Rien à ajouter — surtout pas un
   `align-self` global, qui toucherait tous les avatars du produit pour un cas de carte. */

/* La photo remplit le cercle sans être ni étirée ni coupée au bord : cover, centrée. */
.avatar-img{
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center;
}

.avatar-fallback{
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    background-color: var(--sp-color-bg-cream);
    color: var(--sp-color-text-brown);
    font-size: var(--sp-font-size-12);
    font-weight: var(--sp-font-weight-title);
    line-height: 15px;
    letter-spacing: var(--sp-font-tracking-tight);
}

/* Portrait par défaut (fiche avatar, variant `default`) : le glyphe de personne sur l'un des
   quatre tons décoratifs fermés du DS. Ce sont exactement les tons de SportBadge moins le pêche —
   l'orange reste l'accent d'action, et le pêche est déjà ce que porte un évènement sans photo. */
.avatar-default{
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
}

/* Le glyphe se dimensionne en proportion du cercle : les cinq tailles d'avatar le traversent. */
.avatar-default svg{
    width: 55%;
    height: 55%;
}

.avatar-default--cream{
    background-color: var(--sp-color-bg-cream);
    color: var(--sp-color-text-brown);
}

.avatar-default--ink{
    background-color: var(--sp-color-bg-dark);
    color: var(--sp-color-text-inverse);
}

.avatar-default--green{
    background-color: color-mix(in srgb, var(--sp-color-feedback-success) 12%, var(--sp-color-cream-0));
    color: var(--sp-color-feedback-success);
}

.avatar-default--blue{
    background-color: color-mix(in srgb, var(--sp-color-feedback-info) 12%, var(--sp-color-cream-0));
    color: var(--sp-color-feedback-info);
}

/* ListItem DS (designsystem/spicto/app/components/list-item.md) : rôles de texte
   de la ligne de liste canonique ; la pastille de sport chevauche le coin
   haut-droit de la vignette */
.list-item-title{
    font-size: var(--sp-font-size-16);
    font-weight: var(--sp-font-weight-title);
    color: var(--sp-color-text-default);
}

.list-item-detail{
    font-size: var(--sp-font-size-meta);
    font-weight: var(--sp-font-weight-body);
    color: var(--sp-color-text-default);
}

.list-item-accent{
    color: var(--sp-color-accent-selected);
}

/* Un rail posé DANS une carte : la carte lui rend sa gouttière horizontale, pour que la tuile
   qui déborde soit coupée par le bord de la carte et non arrêtée 24px avant — c'est la coupe au
   bord qui dit que ça continue. La gouttière n'est pas supprimée, elle change de porteur (fiche
   card, et event-rail « Posé sur une Card »). */
.event-rail-section--in-card{
    margin-left: calc(-1 * var(--sp-space-6));
    margin-right: calc(-1 * var(--sp-space-6));
}

.event-rail-section--in-card .event-rail{
    padding-left: var(--sp-space-6);
    padding-right: var(--sp-space-6);
    scroll-padding-left: var(--sp-space-6);
}

/* Les trois montants d'un assujetti sur une seule ligne, séparés comme de la méta : HT et TVA
   accompagnent, seul le TTC est le montant (DESIGN, « Nombres et méta »). */
.vat-amounts{
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: var(--sp-space-2);
    font-size: var(--sp-font-size-meta);
    color: var(--sp-color-text-muted);
}

/* Le montant qu'on paie sort du registre secondaire : HT et TVA accompagnent, lui porte
   (DESIGN, « size.meta est une taille, pas un registre » — le muted ne se déduit pas de la
   taille, et une somme à débiter ne s'estompe pas). */
.vat-amounts-total{
    font-size: var(--sp-font-size-body);
    color: var(--sp-color-text-default);
}

/* Le total d'une sélection pour un assujetti : le TTC y prend la taille du chiffre de la section. */
.vat-amounts--figure{
    justify-content: flex-end;
}

.vat-amounts--figure .vat-amounts-total{
    font-size: var(--sp-font-size-figure);
    font-weight: var(--sp-font-weight-bold) !important;
    white-space: nowrap;
}

/* En mobile, la ligne des montants passe sous le décompte pour rester entière. */
@media (max-width: 575.98px) {
    .section-header-figure:has(.vat-amounts--figure){
        flex-wrap: wrap;
    }

    .vat-amounts--figure{
        flex-wrap: nowrap;
        width: 100%;
    }

    .vat-amounts--figure .vat-amounts-total{
        font-size: 18px;
    }
}

/* Une tuile qui porte l'action de l'écran : l'action se pose À CÔTÉ du lien, superposée à la
   tuile — la tuile EST un lien, et un bouton dans un lien n'est ni valide ni atteignable
   (fiche event-card-highlighted). Elle occupe la place du compteur, jamais celle du texte. */
.event-highlighted-wrap{
    position: relative;
    height: 100%;
}

.event-highlighted-action{
    position: absolute;
    top: var(--sp-space-3);
    right: var(--sp-space-3);
    z-index: 2;
}

/* Variant `manage` (fiche event-card-highlighted) : sur un écran de gestion, les actions
   descendent en barre au pied. Le coin haut droit tient UNE action ; ici il y en a jusqu'à
   trois, et trois boutons empilés dans un coin recouvriraient la photographie qui sert
   justement à reconnaître sa propre sortie parmi trente.

   Elle se range dans la GOUTTIÈRE DE CARTE (space.4) sur ses trois côtés, et l'occupe
   entièrement : le premier bouton commence exactement sous le titre, le dernier finit sous la
   fin de la méta. Sport, titre, méta et actions forment une seule colonne — un retrait propre,
   fût-il de 4px, se lirait comme un défaut de montage (fiche event-card-highlighted). */
.event-highlighted-action--bar{
    top: auto;
    left: var(--sp-space-4);
    right: var(--sp-space-4);
    bottom: var(--sp-space-4);
    display: flex;
    align-items: center;
    /* Plus large que la gouttière interne d'un bouton : deux commandes, pas un contrôle
       segmenté (fiche). */
    gap: var(--sp-space-3);
}

/* « Aucun chevauchement » (fiche) : c'est le TEXTE qui remonte pour laisser la barre, jamais
   l'action qui descend sur lui. La réserve vaut la hauteur d'un bouton `sm` (36px : gouttière
   verticale, filet et hauteur de ligne — aucun token ne la porte) plus la gouttière de carte
   au-dessus et en dessous. */
.event-highlighted-manage .event-highlighted-scrim{
    padding-bottom: calc(var(--sp-space-4) * 2 + 36px);
}

/* Le bouton qui déborde (« Modifier », « 923 photos publiées ») prend la place disponible ;
   celui qui dépose garde sa largeur — c'est lui qu'on vise, il ne doit pas se déplacer d'une
   tuile à l'autre selon la longueur du voisin. */
.event-highlighted-action--bar .btn{
    min-width: 0;
}

.event-highlighted-action--bar .btn-grow{
    flex: 1 1 auto;
}

/* Deux chemins vers la même fin : un filet portant le mot « ou ». Sans lui, les deux cartes se
   lisent comme deux étapes à suivre l'une après l'autre (DESIGNAPP). */
.path-separator{
    display: flex;
    align-items: center;
    gap: var(--sp-space-4);
    color: var(--sp-color-text-brown);
}

.path-separator::before,
.path-separator::after{
    content: "";
    flex: 1;
    border-top: 1px solid var(--sp-color-border-default);
}

/* Champ qui cherche : toujours un pill, loupe de tête (fiche input, variant `search`).
   Distinct de la SearchBar globale, qui ajoute au pill son traitement liquid glass. */
.input-search{
    position: relative;
    display: flex;
    align-items: center;
}

.input-search .form-control{
    padding-left: var(--sp-space-10);
    padding-right: var(--sp-space-10);
    border-radius: var(--sp-radius-full);
    border-color: var(--sp-color-border-cream);
    min-height: 44px;
}

.input-search-icon,
.input-search-clear{
    position: absolute;
    display: inline-flex;
    align-items: center;
    color: var(--sp-color-text-muted);
}

.input-search-icon{
    left: var(--sp-space-4);
    pointer-events: none;
}

.input-search-clear{
    right: var(--sp-space-4);
    color: var(--sp-color-text-default);
}

/* Le champ « dossard » de la frise d'un évènement : un champ qui cherche (fiche input, variant
   `search`), posé dans le panneau de sa chip. Il prend toute la largeur du panneau. */
.event-bib-search .input-search{
    width: 100%;
}

/* Ligne d'évènement dont le dépôt n'est pas encore ouvert : montrée inerte plutôt que cachée
   — la cacher pousse à créer un doublon (DESIGNAPP, « Choisir un évènement »). L'estompe dit
   l'indisponibilité, la mention en dit la DATE : la couleur seule ne porte jamais l'info. */
.list-item--disabled{
    opacity: .55;
}

/* L'action de ligne fournie par l'écran s'aligne en haut à droite, comme l'IconButton du
   composant (fiche list-item). */
.list-item-action-btn{
    align-self: flex-start;
    flex-shrink: 0;
}

.list-item-note{
    align-self: flex-start;
    flex-shrink: 0;
    font-size: var(--sp-font-size-meta);
    color: var(--sp-color-text-muted);
}

.list-item-action-btn .list-item-action-label{
    margin-right: var(--sp-space-2);
}

/* Sur un téléphone, l'action de ligne ne doit pas manger le titre, qui s'écrivait lettre par
   lettre dans ce qui lui restait : « Publier des photos » se réduit à son « + », la mention
   « Dépôt possible à partir du … » passe sous le texte, alignée sur lui. */
@media (max-width: 575.98px){
    .list-item-action-btn{
        width: 32px;
        padding-left: 0;
        padding-right: 0;
        justify-content: center;
    }

    .list-item-action-btn .list-item-action-label{
        display: none;
    }

    .list-item:has(> .list-item-note){
        flex-wrap: wrap;
        row-gap: var(--sp-space-1);
    }

    .list-item-note{
        order: 3;
        flex-basis: 100%;
        padding-left: calc(72px + var(--sp-space-4));
    }
}

/* Variant `agenda` : le sport écrit en toutes lettres au-dessus du titre, précédé de son
   glyphe. Rôle de méta (13px/600), pas une taille inventée — dans une frise, chaque ligne est
   isolée et le sport est ce qui distingue deux évènements (fiche list-item). */
.list-item-sport{
    display: flex;
    align-items: center;
    gap: var(--sp-space-2);
    font-size: var(--sp-font-size-meta);
    font-weight: var(--sp-font-weight-title);
    color: var(--sp-color-text-default);
}

.list-item-meta{
    font-size: var(--sp-font-size-meta);
    font-weight: var(--sp-font-weight-title);
    color: var(--sp-color-text-default);
}

.list-item-thumb{
    position: relative;
    border-radius: var(--sp-radius-md);
}

.list-item-thumb .ratio,
.list-item-thumb .thumbnail-wrapper{
    border-radius: var(--sp-radius-md);
    overflow: hidden;
}

.list-item-thumb > .sport-badge:not(.sport-badge-fill){
    position: absolute;
    top: -6px;
    right: -6px;
    z-index: 2;
}

/* Sections sur desktop : le contenu (hors en-tête) est posé sur une Card ; sur mobile
   il court à même le fond (DESIGNAPP, « Sections sur desktop ») */
@media (min-width: 992px) {
    .section-surface{
        background-color: var(--sp-color-bg-surface);
        border-radius: var(--sp-radius-lg);
        box-shadow: var(--sp-shadow-sm);
        padding: var(--sp-space-6);   /* la gouttière de la Card (fiche card) */
    }

    /* Une Card qui porte un rail ne borne pas sa piste (fiche event-rail) : la gouttière
       passe à la piste elle-même. L'item qui déborde est alors coupé par le bord de la
       Card, et non arrêté 24px avant — c'est la coupe au bord qui dit que ça continue.
       La gouttière défile avec la piste : après navigation, c'est l'item de gauche qui
       est coupé au bord, sans qu'aucune valeur ait à changer.

       Les deux classes portent le même élément : ce sélecteur l'emporte par sa
       spécificité (0,2,0) et non par sa place dans le fichier — l'ordre seul avait déjà
       rendu muettes les commandes du rail. */
    .section-surface.event-rail-section{
        padding-left: 0;
        padding-right: 0;
    }

    .event-rail-section .event-rail{
        padding-left: var(--sp-space-6);
        padding-right: var(--sp-space-6);
        /* sans quoi le calage ramène la première carte au bord et mange la gouttière */
        scroll-padding-left: var(--sp-space-6);
    }
}

/* Grille de ListItem : 1 colonne sur mobile, 3 à parts égales sur desktop,
   gouttière space.3 dans les deux sens (fiche list-item) */
.list-item-grid{
    --bs-gutter-x: var(--sp-space-3);
    --bs-gutter-y: var(--sp-space-3);
}

/* ListItem : la ligne de liste canonique (fiche list-item). Vignette 72px, bloc de
   texte centré et aéré, action de fin de ligne alignée en haut. Le séparateur court sur
   la largeur du bloc de texte ; sur le dernier item, sur toute la largeur. */
.list-item{
    position: relative;
    display: flex;
    align-items: center;
    gap: var(--sp-space-4);
    padding-top: var(--sp-space-4);
    padding-bottom: var(--sp-space-4);
}

.list-item .list-item-thumb{
    width: 72px;
    height: 72px;
    flex-shrink: 0;
}

.list-item-body{
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 5px;   /* interligne confortable entre les rôles (fiche list-item) */
}

.list-item:not(:last-child)::after{
    content: '';
    position: absolute;
    bottom: 0;
    left: calc(72px + var(--sp-space-4));
    right: 0;
    border-bottom: 1px solid var(--sp-color-border-default);
}

.list-item:last-child{
    border-bottom: 1px solid var(--sp-color-border-default);
}

/* Grille (desktop) : le filet sépare les rangées, la dernière n'en porte donc pas —
   il ne séparerait plus rien (fiche list-item).

   Le filet passe sous l'item de la rangée suivante plutôt qu'au-dessus de celui de la
   rangée précédente : la dernière rangée n'est pas désignable en CSS — un ad-slot
   pleine ligne décale les rangées, et le défilement infini la déplace à chaque page —
   là où la première rangée, elle, est toujours les trois premiers items. On retire donc
   le filet de tous, et on le rend à tout ce qui n'est pas la première rangée. */
@media (min-width: 992px) {
    /* Les deux filets de la liste verticale sont neutralisés : lequel s'affiche dépend
       de la place de l'item dans sa colonne, or la modale d'abonnement y traîne comme
       frère — un même item porte donc le ::after ou le border-bottom selon qu'on lui
       passe showSubscription. En grille, le filet appartient à la rangée, pas à ça. */
    .list-item-grid > .col .list-item{
        border-bottom: 0;
    }

    .list-item-grid > .col .list-item::after{
        content: none;
    }

    /* Rendu à toute rangée sauf la première, au-dessus de l'item, aligné après la
       vignette comme dans la liste verticale. */
    .list-item-grid > .col:not(:nth-child(-n+3)) .list-item::after{
        content: '';
        position: absolute;
        top: 0;
        bottom: auto;
        left: calc(72px + var(--sp-space-4));
        right: 0;
        border-top: 1px solid var(--sp-color-border-default);
        border-bottom: 0;
    }
}

.list-item .list-item-action{
    position: relative;
    z-index: 2;
    align-self: flex-start;
    color: var(--sp-color-text-default);
}

/* AdSlot : l'annonce seule, sans cadre ni libellé (retour client du 27/10). La hauteur reste
   réservée d'avance — un emplacement qui grandit au chargement pousse la page sous le doigt —
   et l'emplacement disparaît quand Google n'a rien à servir, plutôt que de laisser un trou. */
.ad-slot{
    display: flex;
    flex-direction: column;
    justify-content: center;
    /* Surtout PAS `align-items: center` : l'annonce est un enfant direct, et centrée elle se
       réduirait à sa largeur de contenu — donc à zéro tant qu'AdSense n'a pas répondu, ce qui
       l'empêche de choisir un format. */
    align-items: stretch;
    min-height: 100px;
    text-align: center;
}

.ad-slot:has(> ins[data-ad-status="unfilled"]){
    display: none;
}

/* PhotoGallery DS (designsystem/spicto/app/components/photo-gallery.md) :
   tuiles carrées, coins radius.md, gap 16px issu de l'échelle */
.photo-gallery{
    --bs-gutter-x: var(--sp-space-4);
    --bs-gutter-y: var(--sp-space-4);
}

.photo-gallery .ratio-1x1{
    border-radius: var(--sp-radius-md);
    overflow: hidden;
}

.photo-gallery a{
    display: block;
    border-radius: var(--sp-radius-md);
}

.photo-gallery a:focus-visible{
    outline: none;
    box-shadow: var(--sp-shadow-ring);
}

/* Tuile « +N » : photo réelle sous voile sombre, nombre restant en blanc */
.photo-gallery-more-overlay{
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    background-color: var(--sp-color-overlay-scrim);
    color: var(--sp-color-text-inverse);
    font-size: var(--sp-font-size-h3);
    font-weight: var(--sp-font-weight-title);
    border-radius: var(--sp-radius-md);
}

/* Timeline DS (designsystem/spicto/app/components/timeline.md) : frise verticale des journées
   d'un évènement. Rail continu chaud, un nœud par journée (pastille + en-tête + grille), nœud
   courant en orange, nœud « + » final pour les photos à venir. */
/* Page évènement desktop (DESIGNAPP, maquette GALLERY DESKTOP) : contenu de 1000px, et la frise
   — comme les deux blocs de l'écran « sans photos » — sur un panneau clair au rayon 24, sans
   ombre : sur le crème soutenu du fond desktop, c'est la surface claire qui détache la galerie.
   Sur mobile, aucune règle : le contenu reste sur le fond, pleine largeur — la photo est la
   vedette, une carte la rognerait. */
@media (min-width: 992px) {
    .event-page > .container-lg{
        max-width: calc(var(--sp-layout-content-event) + var(--bs-gutter-x));
    }

    .event-section-card{
        background-color: var(--sp-color-bg-default);
        border-radius: var(--sp-radius-2xl);
        padding: var(--sp-space-5) var(--sp-space-6) var(--sp-space-6);
    }

    .event-page .event-highlighted-header--page{
        min-height: 289px;
        border-radius: var(--sp-radius-2xl);
    }
}

/* Zone AU REPOS — à ne pas confondre avec une zone EN ATTENTE (DESIGNAPP, zone
   « Téléchargements » du dépôt). Le pointillé du produit dit qu'un contenu VIENDRA là : une
   journée de frise qui recevra ses photos, un album qu'on va créer. Ici rien n'est en route et
   rien n'est promis — la zone garde seulement la place de ce qui viendra SI l'on dépose. D'où le
   filet continu, aucun aplat (le fond de la page traverse), et la hauteur qui réserve
   l'emplacement des cartes de transfert.

   Le texte est en text.brown et non en text.muted : ce gris-là est calculé pour le blanc, et la
   zone est posée sur le crème de la page (DESIGNAPP, « Bordures et séparateurs : c'est le SOL »).
   Même raison pour le filet, chaud lui aussi. */
.idle-panel{
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 145px;
    padding: var(--sp-space-4) var(--sp-space-6) 11px;
    border: var(--sp-border-width-default) solid var(--sp-color-border-cream);
    border-radius: var(--sp-radius-xl);
    text-align: center;
}

/* Elle réserve la place d'une carte de transfert : elle en prend la forme, et son mot en prend
   le rang (16/19 semibold, maquette). */
.idle-panel-text{
    font-size: var(--sp-font-size-16);
    font-weight: var(--sp-font-weight-title);
    line-height: 19px;
    color: var(--sp-color-text-brown);
}

/* État « sans photos » d'un évènement (DESIGNAPP, « Un évènement sans photos »). Encart d'attente
   en pointillé chaud (border.cream), texte muted centré : le pointillé dit l'attente, une surface
   pleine dirait un contenu — même langage que la journée `awaiting` de la frise. */
.event-empty-panel,
.timeline-awaiting{
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 220px;
    padding: var(--sp-space-6);
    border: 1px dashed var(--sp-color-border-cream);
    border-radius: var(--sp-radius-lg);
    text-align: center;
}

.event-empty-panel-text{
    color: var(--sp-color-text-muted);
}

/* Le lien de sortie d'un encart filtré (« Voir tout ») se lit dans la couleur du message : il
   n'est pas une action de plus, c'est la fin de la phrase (fiche timeline). « Me prévenir » de
   l'encart d'une combinaison de filtres vide suit la même règle (retour client). */
.timeline-awaiting a,
.event-empty-panel-text a{
    color: inherit;
    text-decoration: underline;
}

/* Carte d'un photographe inscrit : filet chaud, radius, pas d'ombre (surface posée sur la
   colonne). La carte de l'utilisateur courant se réchauffe en crème et porte le badge « Moi ». */
.event-photographer-card{
    position: relative;
    padding: var(--sp-space-3);
    border: 1px solid var(--sp-color-border-default);
    border-radius: var(--sp-radius-lg);
    background-color: var(--sp-color-bg-surface);
}

.event-photographer-card--me{
    background-color: var(--sp-color-bg-cream);
}

/* Badge « Moi » : pastille ink au coin haut droit, au-dessus du lien étiré de la carte
   (stretched-link de ProfileListItem, z-index 1) — sinon il passerait dessous et deviendrait
   cliquable comme le reste de la carte. */
.event-photographer-me{
    position: absolute;
    top: var(--sp-space-3);
    right: var(--sp-space-3);
    z-index: 2;
    padding: 2px var(--sp-space-2);
    border-radius: var(--sp-radius-full);
    background-color: var(--sp-color-bg-dark);
    color: var(--sp-color-text-inverse);
    font-size: var(--sp-font-size-meta);
    font-weight: var(--sp-font-weight-title);
}

.timeline{
    list-style: none;
    margin: 0;
    padding: 0;
}

/* Le repère vertical d'un nœud est sa LIGNE D'EN-TÊTE, pas une ligne de texte. La date y est
   centrée ; dès que la ligne porte plus haut qu'elle — le compteur (24px), « Me prévenir »
   (34px) —, la date descend, et une pastille calée sur une ligne de 21 restait en haut :
   jusqu'à 6,5px d'écart sur une journée vide. La pastille et le rail partent donc de la
   hauteur de la rangée, que chaque état déclare. */
.timeline-item{
    position: relative;
    display: grid;
    grid-template-columns: 16px 1fr;
    gap: var(--sp-space-4);
    padding-bottom: var(--sp-space-8);
    --timeline-header-h: 1lh;
}

.timeline-item:has(.timeline-count){
    --timeline-header-h: 24px;
}

.timeline-item:has(.timeline-notify){
    --timeline-header-h: 34px;
}

.timeline-item:last-child{
    padding-bottom: 0;
}

/* Le rail : un filet chaud continu, tracé depuis la pastille jusqu'au nœud suivant. Il passe
   derrière les pastilles (z-index) et ne descend pas sous le dernier nœud. */
.timeline-marker{
    position: relative;
    display: flex;
    justify-content: center;
}

.timeline-item:not(:last-child) .timeline-marker::before{
    content: "";
    position: absolute;
    left: 50%;
    /* Part du centre de la pastille — donc du milieu de la ligne d'en-tête — et rejoint
       exactement celui de la pastille suivante. Plus haut, le filet dépasserait au-dessus. */
    top: var(--sp-space-2);
    top: calc(var(--timeline-header-h) / 2);
    height: calc(100% + var(--sp-space-8));
    width: 1px;
    transform: translateX(-50%);
    background-color: var(--sp-color-border-default);
}

.timeline-dot{
    position: relative;
    z-index: 1;
    /* 7×7 et rien ne la déforme : rapport 1:1, et elle ne s'écrase pas dans la colonne flex
       du marqueur (fiche timeline). */
    width: 7px;
    height: 7px;
    aspect-ratio: 1;
    flex: 0 0 auto;
    /* Centrée sur la ligne d'EN-TÊTE de son nœud, pas sur une ligne de texte : c'est la
       rangée qui porte la date, et la date s'y centre (fiche timeline). La première
       déclaration n'est qu'un repli. */
    margin-top: var(--sp-space-2);
    margin-top: calc((var(--timeline-header-h) - 7px) / 2);
    border-radius: var(--sp-radius-full);
    background-color: var(--sp-color-text-caption);
}

/* Variant `agenda` : l'en-tête n'est plus une ligne de texte mais une LIGNE DE CONTRÔLES — un
   badge de date, et parfois l'action du jour. Sa hauteur est donc celle du bouton, imposée à
   tous les nœuds : sans quoi le nœud qui porte l'action serait plus haut que les autres et
   ses voisins auraient chacun un centre différent. Un repère unique, d'où découlent la
   pastille et le rail (fiche timeline). */
.timeline--agenda{
    --timeline-agenda-header: 36px;
}

.timeline--agenda .timeline-header{
    min-height: var(--timeline-agenda-header);
}

.timeline--agenda .timeline-dot{
    margin-top: calc((var(--timeline-agenda-header) - 7px) / 2);
}

.timeline--agenda .timeline-item:not(:last-child) .timeline-marker::before{
    top: calc(var(--timeline-agenda-header) / 2);
}

/* Un nœud ne porte qu'un évènement : le filet de ListItem n'y sépare rien, et c'est le rail
   qui jalonne (fiche list-item, variant `agenda`). */
.timeline--agenda .list-item{
    border-bottom: 0;
}

/* Nœud courant : pastille orange de marque, seule couleur d'accent de la frise */
.timeline-item--current .timeline-dot{
    background-color: var(--sp-color-accent-selected);
}

/* Nœud de fin : glyphe NU de 12×12 — ni cercle, ni liseré, ni fond. Ce n'est pas une pastille
   de journée, il ne doit pas s'y ressembler (fiche timeline). Son centre tombe au même endroit
   que celui des pastilles, pour que le rail le rejoigne exactement. */
.timeline-end-glyph{
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 12px;
    height: 12px;
    flex: 0 0 auto;
    color: var(--sp-color-border-cream);
    margin-top: var(--sp-space-1);
    margin-top: calc((1lh - 12px) / 2);
}

/* En-tête de nœud : la date à gauche, à droite le compteur (variant default) ou l'action que
   la date appelle (variant agenda). Alignement centré, parce que ce qui se fait face n'est pas
   du texte mais des objets — un badge, un bouton (fiche timeline). */
.timeline-header{
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-space-2);
}

.timeline-label{
    font-weight: var(--sp-font-weight-title);
    color: var(--sp-color-text-default);
}

/* Le nom d'évènement d'un profil mène à sa page : il garde l'allure du libellé. */
.timeline-label-link{
    color: inherit;
    text-decoration: none;
}

.timeline-label-link:hover{
    text-decoration: underline;
}

/* Le compteur est un Badge ton neutral : taille, couleur, rayon et padding viennent de lui
   (fiche timeline). Ne restent ici que sa tenue dans la ligne d'en-tête. */
.timeline-count{
    flex-shrink: 0;
    white-space: nowrap;
}

.timeline-count-total{
    color: var(--sp-color-text-muted);
    font-weight: var(--sp-font-weight-body);
}

.timeline-meta{
    margin-top: 2px;
    font-size: var(--sp-font-size-meta);
    color: var(--sp-color-text-muted);
}

.timeline-gallery{
    margin-top: var(--sp-space-3);
}

.timeline-end-text{
    font-size: var(--sp-font-size-label);
    line-height: 17px;
    color: var(--sp-color-text-brown);
}

/* « Me prévenir » d'une journée en attente : 12/15 semibold à -0,02em (maquette GALLERY) */
.btn.timeline-notify{
    font-size: var(--sp-font-size-12);
    font-weight: var(--sp-font-weight-title);
    line-height: 15px;
}

/* Journée en attente : le pointillé dit l'attente ; une surface pleine dirait un contenu
   (fiche timeline, état `awaiting`). */
/* La frise ne se fait pas un encart à elle : c'est le même que la galerie vide (fiche timeline,
   « C'est le MÊME encart »). Seule sa place dans le nœud lui appartient. */
.timeline-awaiting{
    margin-top: var(--sp-space-3);
}

/* Ton danger du DS : aplat rouge, texte blanc (alerte forte). Le rouge est celui des surfaces
   sombres (`feedback.danger.on-dark`, #F5494A) et non `feedback.danger` : ce badge se pose sur
   une PHOTOGRAPHIE, où le rouge foncé passe pour du brun et cesse d'alerter (fiche badge). La
   dérogation AA qui va avec est assumée et tracée dans la fiche. */
.badge-danger{
    background-color: var(--sp-color-feedback-danger-on-dark);
    color: var(--sp-color-text-inverse);
}

/* Panneau de filtres : Sheet sur mobile, Dropdown sur desktop (fiches sheet.md et
   dropdown.md). Même markup des deux côtés — même contenu, même fonction, autre surface.

   Base = mobile : le panneau monte du bas, sur un voile. */
.filter-anchor {
    position: relative;
}

.filter-veil {
    position: fixed;
    inset: 0;
    background-color: var(--sp-color-overlay-veil);
    z-index: 1045;
    animation: filter-veil-in var(--sp-duration-base) var(--sp-easing-standard);
}

/* Le panneau se déploie depuis le bord bas : le geste dit d'où il vient et par où il
   repartira (fiche sheet, « Mouvement »). Le voile se fond en même temps. */
@keyframes filter-veil-in {
    from { opacity: 0; }
    to   { opacity: 1; }
}

@keyframes filter-sheet-up {
    from { transform: translateY(100%); }
    to   { transform: translateY(0); }
}

.filter-panel {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 1046;
    display: flex;
    flex-direction: column;
    gap: var(--sp-space-4);
    /* jamais tout l'écran : la bande qui dépasse dit qu'on peut refermer (fiche sheet) */
    max-height: 85vh;
    padding: var(--sp-space-6);
    background-color: var(--sp-color-bg-surface);
    /* le panneau sort du bord bas : rien à arrondir de ce côté */
    border-radius: var(--sp-radius-lg) var(--sp-radius-lg) 0 0;
    box-shadow: var(--sp-shadow-pop);
    animation: filter-sheet-up var(--sp-duration-base) var(--sp-easing-standard);
}

/* L'information est dans la position finale, pas dans le trajet (fiche sheet) */
@media (prefers-reduced-motion: reduce) {
    .filter-panel,
    .filter-veil {
        animation: none;
    }
}

.filter-panel-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-space-3);
}

/* Deux classes : `.photographer-layout h3` (0,1,1) imposait sa marge de 16px au titre dans les
   espaces pro, et le titre remontait de 8px au-dessus de la croix. Sans effet sur le front, où
   la marge est déjà nulle. */
.filter-panel-head .filter-panel-title {
    margin: 0;
    font-size: var(--sp-font-size-h3);
    font-weight: var(--sp-font-weight-title);
    letter-spacing: var(--sp-font-tracking-tighter);
    color: var(--sp-color-text-default);
}

/* La croix se cale sur la colonne des CONTRÔLES, pas sur sa propre cible tactile. Le disque de
   44px l'emporte à droite du panneau, mais le glyphe y est centré : il s'arrêtait 15px avant les
   radios et les cases, que la maquette aligne pourtant sur le même bord. La marge négative rend
   au glyphe le bord du contenu et laisse la cible tactile déborder dans la gouttière, où elle ne
   gêne rien. */
.filter-panel-close {
    color: var(--sp-color-text-default);
    margin-right: calc((var(--sp-control-icon-button) - 14px) / -2);
}

.filter-panel-form {
    display: flex;
    flex-direction: column;
    min-height: 0;   /* sans quoi le corps refuse de défiler */
    /* Pas d'espace entre la liste et le filet du pied (retour client) : la dernière rangée
       s'arrête sur le filet, et la liste qui défile passe dessous sans laisser de blanc. */
    gap: 0;
}

/* Le corps défile, le pied non : une validation qu'il faut aller chercher en bas de trente
   lignes ne se trouve pas (fiches dropdown et sheet) */
.filter-panel-body {
    overflow-y: auto;
    min-height: 0;
}

/* Le pied (Figma 1532:4764) : son filet court sur TOUTE la largeur du panneau — il déborde
   donc la gouttière —, ses boutons font 42px au rayon lg, à 10px l'un de l'autre */
.filter-panel-foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    margin: 0 calc(-1 * var(--sp-space-6)) calc(-1 * var(--sp-space-6));
    padding: var(--sp-space-6);
    border-top: 1px solid var(--sp-color-border-control);
}

/* Rien à retirer : le bouton s'éteint en gris (Figma : DDD sur 757575) */
.filter-panel-foot .btn-neutral:disabled {
    --bs-btn-disabled-bg: var(--sp-color-grey-200);
    --bs-btn-disabled-border-color: var(--sp-color-grey-200);
    --bs-btn-disabled-color: var(--sp-color-text-muted);
    opacity: 1;
}

.filter-panel-foot .btn {
    flex: 1;
    min-height: 42px;
    padding-top: 0;
    padding-bottom: 0;
    border-radius: var(--sp-radius-lg);
    font-size: var(--sp-font-size-body);
    font-weight: var(--sp-font-weight-title);
}

/* Sur mobile le panneau est crème comme la page (Figma « Bottom_card » : FAF9F5), sans
   poignée : la maquette n'en a pas, la croix et le voile suffisent à refermer */
@media (max-width: 991.98px) {
    .filter-panel {
        background-color: var(--sp-color-bg-default);
    }
}

/* Trois panneaux restent BLANCS, et c'est ce qu'ils portent qui le décide : une ligne-carte
   (Photographes, Dossard) ou un calendrier (Dates) est une SURFACE posée sur la feuille, et une
   surface a besoin d'un sol plus clair qu'elle pour se lire. Cochée, une ligne-carte passe en
   `bg.sunken` : sur le crème de la feuille elle donnait 1,02:1 — le panneau entier se lisait
   comme un aplat. Les panneaux qui n'alignent que des rangées gardent le crème (maquette). */
.filter-panel--white {
    background-color: var(--sp-color-bg-surface);
}

@media (min-width: 992px) {
    /* Desktop : le panneau pend sous la barre d'onglets et ne bloque rien — pas de voile,
       la page reste lisible et cliquable (fiche dropdown).

       Il se mesure sur la barre, non sur sa chip : c'est ce qui aligne son bord droit sur
       celui du contenu. Ancré à la chip, il aurait fallu deviner la distance qui l'en
       sépare — le CSS ne la connaît pas, et une largeur fixe aurait débordé du conteneur
       sur les écrans étroits, jusqu'à pousser la page. */
    .tab-bar-block {
        position: relative;
    }

    .filter-anchor {
        position: static;
    }

    /* Page évènement : la barre de chips n'est pas une .tab-bar-block. Elle sert elle-même
       de contexte au dropdown (sans quoi l'absolu se cale sur le viewport — coin bas droit).
       Ses chips sont à gauche : on cale donc le panneau à gauche, non à droite comme la home. */
    .photo-filter-bar {
        position: relative;
    }

    .photo-filter-bar .filter-panel {
        left: 0;
        right: auto;
    }

    .filter-panel {
        position: absolute;
        top: calc(100% + var(--sp-space-2));
        left: auto;
        right: 0;
        bottom: auto;
        /* Largeur de son contenu, avec le plancher du variant « filters » : réglé sur son
           seul contenu il n'occupait que 39% de la place et serrait ses colonnes ; poussé
           à 100%, il était trop large (fiche dropdown, « Largeur »).
           Le plancher ne vaut que pour un panneau de filtres — c'est .filter-panel qui le
           porte, pas une règle de dropdown. */
        width: max-content;
        min-width: 600px;
        /* borné par la barre, donc par le conteneur : jamais de débord, jamais de scroll */
        max-width: 100%;
        max-height: none;
        border-radius: var(--sp-radius-lg);
        /* le Dropdown ne monte de nulle part : il est déjà chez lui, sous sa barre */
        animation: none;
        transform: none;
    }

    .filter-panel-foot .btn {
        flex: 0 0 auto;
    }

    /* Déclencheur isolé dans une carte : le panneau s'aligne sur SON bord gauche, et sort donc
       visiblement de la chip qui l'a ouvert. L'ancre redevient le repère (position: relative),
       au lieu de la barre pleine largeur des filtres de la home — là-bas c'est l'alignement à
       droite qui garde le panneau dans le conteneur (fiche dropdown). */
    .filter-anchor--start {
        position: relative;
    }

    .filter-anchor--start .filter-panel {
        left: 0;
        right: auto;
        /* Le plancher de 600px vaut pour une liste d'options parcourue du regard, pas pour un
           calendrier, qui a sa propre largeur (fiche dropdown, « Largeur »). */
        min-width: 0;
        max-width: min(600px, calc(100vw - var(--sp-space-8)));
    }

    /* Pendant de --start pour une chip posée à DROITE de sa ligne (ex. « Trier par » de la page
       évènement, calé à droite sur desktop) : le panneau s'aligne sur SON bord droit et s'ouvre
       vers la gauche, sous sa chip. C'est l'autre façon de tenir l'invariant de la fiche dropdown
       — ne jamais franchir un bord du conteneur : une chip à droite dont le panneau s'alignerait
       à gauche déborderait par la droite et ferait défiler la page de travers. La largeur est
       bornée au viewport (pas en % de l'ancre, qui ne fait que la taille de la chip). */
    .filter-anchor--end {
        position: relative;
    }

    .filter-anchor--end .filter-panel {
        right: 0;
        left: auto;
        min-width: 0;
        max-width: min(600px, calc(100vw - var(--sp-space-8)));
    }
}

/* Liste de filtres (DESIGNAPP, « Liste de filtres ») : glyphe, libellé, contrôle à droite.
   Une colonne sur mobile, deux sur desktop ; l'en-tête garde la ligne entière. */
.filter-list {
    display: grid;
    grid-template-columns: 1fr;
    /* Gouttière franche entre les colonnes (DESIGNAPP, « Liste de filtres ») : une colonne
       finit par un contrôle, la suivante commence par un glyphe — ils se confondent s'ils
       se frôlent. Deux listes autonomes, pas quatre colonnes. */
    column-gap: var(--sp-space-8);
    border: 0;
    padding: 0;
    margin: 0;
    min-width: 0;   /* un fieldset ne rétrécit pas sans ça */
}

@media (min-width: 992px) {
    .filter-list {
        grid-template-columns: 1fr 1fr;
    }

    /* Quelques options ne font pas deux listes : elles gardent leur colonne. Les deux
       classes portent le même élément — la spécificité tranche, pas l'ordre. */
    .filter-list.filter-list-single {
        grid-template-columns: 1fr;
    }

    .filter-list .filter-row-head {
        grid-column: 1 / -1;
    }
}

.filter-row {
    display: flex;
    align-items: center;
    gap: var(--sp-space-3);
    min-height: var(--sp-control-icon-button);   /* cible tactile (fiche checkbox) */
    padding: var(--sp-space-2) 0;
}

/* Le filet coiffe la ligne au lieu de la souligner : la dernière n'en porte donc aucun,
   quel que soit le nombre de sports, et sans avoir à désigner « la dernière » — que la
   grille à deux colonnes rendrait indésignable.

   Il ne sépare que les options entre elles : l'en-tête coiffe le groupe, il n'en est pas
   membre et ne s'en détache pas d'un trait. D'où le :not() — une option qui suit
   l'en-tête n'ouvre pas de filet. */
.filter-row:not(.filter-row-head) + .filter-row {
    border-top: 1px solid var(--sp-color-border-default);
}

/* Sur deux colonnes, l'en-tête tient la ligne entière : la première rangée d'options est
   faite des 2e et 3e lignes. La 3e ne suit pas l'en-tête dans le DOM — la règle ci-dessus
   lui pose donc un filet — mais elle est bien sur la première rangée. On le lui retire.

   nth-of-type et non nth-child : le <legend> du fieldset est le premier enfant, invisible
   mais bien là, et il décalait tout le comptage d'un rang — le filet sautait une ligne
   plus haut que voulu. nth-of-type ne compte que les div.

   Et seulement à deux colonnes : sur une seule, la 3e ligne n'a rien d'une première
   rangée, elle a besoin de son filet comme les autres.

   Placé APRÈS la règle qu'il corrige : à spécificité égale, c'est l'ordre qui tranche. */
@media (min-width: 992px) {
    .filter-list:not(.filter-list-single) > .filter-row:nth-of-type(3) {
        border-top: 0;
    }
}

.filter-row-icon {
    display: inline-flex;
    flex-shrink: 0;
    color: var(--sp-color-text-brown);
}

.filter-row-icon svg {
    display: block;
}

/* L'en-tête commande le groupe : son glyphe prend l'accent, son libellé le poids de titre */
.filter-row-icon-accent {
    color: var(--sp-color-accent-selected);
}

.filter-row-head .filter-row-label {
    font-weight: var(--sp-font-weight-title);
}

.filter-row-label {
    flex: 1;
    min-width: 0;
    margin: 0;
    cursor: pointer;
    color: var(--sp-color-text-default);
}

/* Le critère d'une option porte le poids de titre, son sens reste au poids de corps
   (DESIGNAPP, « Liste de filtres »). Le <strong> du navigateur vaudrait 700, que le DS
   réserve ailleurs : ici c'est font.weight.title. */
.filter-row-label strong {
    font-weight: var(--sp-font-weight-title);
}

/* Le contrôle tient le bout de ligne : même colonne pour tous, quel que soit le libellé */
.filter-row-check,
.filter-row-switch {
    flex-shrink: 0;
    margin: 0;
}

/* .form-switch réserve une gouttière à gauche pour son libellé ; ici le libellé est
   ailleurs sur la ligne. Les deux classes portent le même élément : on l'emporte par la
   spécificité, non par l'ordre du fichier. */
.form-switch.filter-row-switch {
    padding-left: 0;
    min-height: 0;
}

/* Breadcrumb */

.breadcrumb-nav .crumb {
    --bs-nav-link-padding-y: 8px;
    --bs-nav-link-padding-x: 8px;
    --bs-nav-link-font-weight: 600;
    color: var(--bs-heading-color);
    font-weight: 600;
    text-decoration: none;
    border-bottom: none;
    display: inline-block;
    padding: var(--bs-nav-link-padding-y) var(--bs-nav-link-padding-x) 8px var(--bs-nav-link-padding-x);
}

.breadcrumb-nav .separator {
    color: var(--sp-color-text-muted);
    font-size: 18px;
    margin: 0 6px;
}

.breadcrumb-nav.nav-underline .nav-link,
.nav.nav-underline .crumb{
    padding: 18px var(--bs-nav-link-padding-x) 18px var(--bs-nav-link-padding-x);
}

@media (min-width: 992px) {

    .breadcrumb-nav.nav-underline .nav-link,
    .nav.nav-underline .crumb{
        padding: 16px var(--bs-nav-link-padding-x) 16px var(--bs-nav-link-padding-x);
    }

}

/* Buttons */

/* Boutons DS : rayon lg (16px) — plus arrondi que les chips, c'est ce qui désigne
   l'élément qu'on presse ; anneau de focus orange, press ~0,97, disabled à 40 % */
.btn {
    --bs-btn-padding-x: 12px;
    --bs-btn-padding-y: 8px;
    --bs-btn-font-size: var(--sp-font-size-body);
    --bs-btn-font-weight: var(--sp-font-weight-body);
    --bs-btn-border-radius: var(--sp-radius-lg);
    --bs-btn-disabled-opacity: 0.4;
    --bs-btn-focus-box-shadow: var(--sp-shadow-ring);
    --bs-btn-line-height: var(--sp-font-leading-ui);
    letter-spacing: var(--sp-font-tracking-tight);
    transition: transform var(--sp-duration-fast) var(--sp-easing-standard),
                background-color var(--sp-duration-fast) var(--sp-easing-standard),
                border-color var(--sp-duration-fast) var(--sp-easing-standard),
                color var(--sp-duration-fast) var(--sp-easing-standard);
}

.btn:not(:disabled):active {
    transform: var(--sp-gesture-press);
}

.btn:focus-visible {
    box-shadow: var(--sp-shadow-ring);
}

@media (prefers-reduced-motion: reduce) {
    .btn {
        transition: none;
    }
    .btn:not(:disabled):active {
        transform: none;
    }
}

.btn-sm {
    --bs-btn-font-size: 12px;
    /* Coin resserré à radius.sm (8px) : à 32px de haut, le radius.lg de base arrondirait presque
       en pilule — le coin suit la taille (fiche button). */
    --bs-btn-border-radius: var(--sp-radius-sm);
}

/* Un Button réduit à son glyphe reste un Button (fiche button) : il garde la hauteur et le rayon
   du bouton nommé qu'il raccourcit, et devient carré. Ce n'est PAS .btn-circle, le disque 44px de
   l'IconButton, qui est un contrôle de chrome et dépasserait ses voisines dans la barre.

   Aucune taille propre n'est fixée ici : la hauteur vient de la rangée (align-self), et la largeur
   se REFAIT depuis les mêmes variables que celles qui donnent sa hauteur à un bouton libellé de
   même taille — gouttière verticale, filet, hauteur de ligne. `aspect-ratio` ne suffirait pas :
   dans une rangée flex, la largeur se résout sur le contenu (le glyphe, 16px) avant que la hauteur
   étirée ne soit connue, et le carré ne se ferait jamais. */
.btn-icon-only{
    display: inline-flex;
    align-items: center;
    justify-content: center;
    align-self: stretch;
    /* Le raccourci ne se déforme pas au profit des libellés voisins. */
    flex: 0 0 auto;
    width: calc(var(--bs-btn-font-size) * var(--bs-btn-line-height)
                + 2 * var(--bs-btn-padding-y)
                + 2 * var(--bs-btn-border-width));
    padding-left: 0;
    padding-right: 0;
}

.btn.p-0{
    padding: 0!important;
}

.btn-primary{
    --bs-btn-color: var(--sp-color-bg-surface);
    --bs-btn-bg: var(--bs-primary);
    --bs-btn-border-color: var(--bs-primary);
    --bs-btn-hover-color: var(--sp-color-bg-surface);
    --bs-btn-hover-bg: rgba(var(--bs-primary-rgb), .7);
    --bs-btn-hover-border-color: transparent;
    --bs-btn-disabled-bg: var(--bs-primary);
    --bs-btn-disabled-border-color: var(--bs-primary);
    --bs-btn-active-bg: var(--bs-primary);
    --bs-btn-active-border-color: var(--bs-primary);
}

.btn-outline-primary {
    --bs-btn-color: var(--bs-heading-color);
    --bs-btn-border-color: var(--bs-secondary);
    --bs-btn-hover-color: var(--sp-color-bg-surface);
    --bs-btn-hover-bg: var(--bs-primary);
    --bs-btn-hover-border-color: var(--bs-primary);
    --bs-btn-active-color: var(--sp-color-bg-surface);
    --bs-btn-active-bg: var(--bs-primary);
    --bs-btn-active-border-color: var(--bs-primary);
    --bs-btn-disabled-color: var(--bs-secondary);
    --bs-btn-disabled-border-color: var(--bs-secondary);
}

.btn-outline-primary {
    --bs-btn-font-weight: 600;
}

/* .btn-outline-secondary a été retiré : contour gris froid et texte gris, il ne correspondait
   à aucun variant de la fiche button, et le DS écarte le gris froid des filets. Les actions de
   faible emphase qu'il portait sont passées en .btn-neutral (crème) ; la navigation « voir
   tout » qu'il portait aussi est redevenue un lien (.sec-header-link). */

.btn-light {
    --bs-btn-color: var(--bs-primary);
    --bs-btn-bg: var(--light);
    --bs-btn-border-color: var(--sp-color-border-default);
    --bs-btn-hover-color: var(--bs-primary);
    --bs-btn-hover-bg: transparent;
    --bs-btn-hover-border-color: var(--bs-primary);
    --bs-btn-focus-shadow-rgb: 211, 212, 213;
    --bs-btn-active-color: var(--bs-primary);
    --bs-btn-active-bg: transparent;
    --bs-btn-active-border-color: var(--bs-primary);
    --bs-btn-disabled-color: var(--bs-primary);
    --bs-btn-disabled-bg: var(--sp-color-bg-grey);
    --bs-btn-disabled-border-color: var(--sp-color-bg-grey);
    font-variation-settings: 'wght' 400;
    transition: font-variation-settings 0.2s;
    position: relative;
}

.btn-light:active,
.btn-check+.btn-light:active,
.btn-check:checked+.btn-light {
    font-variation-settings: 'wght' 600;
}

.btn-check+.btn:hover {
    color: var(--bs-btn-hover-color);
    background-color: var(--bs-btn-hover-bg);
    border-color: var(--bs-btn-hover-border-color);
}

/* Chip DS (designsystem/spicto/app/components/chip.md) : les toggles de filtre
   (btn-check + label) prennent le traitement chip. Fond blanc et ombre douce
   stables entre états ; à la sélection, libellé et icône passent à l'orange. */
.btn-check + .btn-light {
    --bs-btn-bg: var(--sp-color-bg-surface);
    --bs-btn-color: var(--sp-color-text-default);
    --bs-btn-border-color: transparent;
    --bs-btn-hover-bg: var(--sp-color-bg-surface);
    --bs-btn-hover-color: var(--sp-color-text-default);
    --bs-btn-hover-border-color: transparent;
    --bs-btn-active-bg: var(--sp-color-bg-surface);
    --bs-btn-active-color: var(--sp-color-accent-selected);
    --bs-btn-active-border-color: transparent;
    --bs-btn-border-radius: var(--sp-radius-md);
    box-shadow: var(--sp-shadow-sm);
}

.btn-check:checked + .btn-light {
    color: var(--sp-color-accent-selected);
    background-color: var(--sp-color-bg-surface);
    border-color: transparent;
}

.btn-check:focus-visible + .btn-light {
    box-shadow: var(--sp-shadow-ring), var(--sp-shadow-sm);
}

/* Chips d'accès aux filtres (rangée sous les onglets, mockup home) :
   même traitement chip, libellé orange quand la catégorie est active */
.chip-filter {
    height: 34px;   /* fiche chip — 34 sur la maquette (Figma EVENT_FILTER 1904:17210) */
    gap: var(--sp-space-1);
    padding-left: var(--sp-space-3);
    padding-right: var(--sp-space-3);
    font-size: var(--sp-font-size-label);
    font-weight: var(--sp-font-weight-body);
    --bs-btn-bg: var(--sp-color-bg-surface);
    --bs-btn-color: var(--sp-color-text-default);
    --bs-btn-border-color: transparent;
    --bs-btn-hover-bg: var(--sp-color-bg-surface);
    --bs-btn-hover-color: var(--sp-color-text-default);
    --bs-btn-hover-border-color: transparent;
    --bs-btn-active-bg: var(--sp-color-bg-surface);
    --bs-btn-active-color: var(--sp-color-accent-selected);
    --bs-btn-active-border-color: transparent;
    --bs-btn-border-radius: var(--sp-radius-md);
    box-shadow: var(--sp-shadow-sm);
}

.chip-filter.active {
    color: var(--sp-color-accent-selected);
}

/* Le glyphe de 24 (chip Sports) porte son propre retrait : la chip n'en garde que 6px */
.chip-filter--glyph {
    padding-left: 6px;
}

/* Le chevron d'une chip qui restreint (fiche chip) : il dit qu'un réglage est posé et se
   rouvre. Le set n'a qu'un chevron, vers le haut : on le retourne. */
.chip-filter-chevron {
    display: inline-flex;
    transform: rotate(180deg);
}

/* Pastille d'annonce d'une chip (fiche chip, comme celle des onglets) : un point orange avant
   le libellé — « il y a là quelque chose à voir » —, sans sélectionner la chip. */
.chip-dot {
    display: inline-block;
    width: 7px;
    height: 7px;
    border-radius: var(--sp-radius-full);
    background-color: var(--sp-color-accent-selected);
}

/* Compteur d'un onglet sous filtre (fiche tabs) : une pastille orange qui dit combien
   l'onglet retient ; brune quand il ne retient rien — l'onglet reste là, il n'a juste rien.
   Un rond de 16px, pas un ovale de 16×15, et des chiffres à chasse fixe : le « 1 » proportionnel
   ne tombait pas au milieu. */
.tab-count {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 16px;
    height: 16px;
    padding: 0 var(--sp-space-1);
    border-radius: var(--sp-radius-full);
    background-color: var(--sp-color-accent-selected);
    color: var(--sp-color-text-inverse);
    font-size: var(--sp-font-size-12);
    font-weight: var(--sp-font-weight-title);
    font-variant-numeric: tabular-nums;
    line-height: 16px;
    letter-spacing: var(--sp-font-tracking-tight);
}

.tab-count--empty {
    background-color: var(--sp-color-text-brown);
}

/* Fil d'Ariane d'un en-tête de résultats (« Résultats › Live ») : le chevron sépare, il ne
   titre pas — il prend le muted du décompte. */
.sec-header-crumb {
    display: inline-flex;
    color: var(--sp-color-text-muted);
}

/* Localisation, Dates et Dossard ne sont pas des listes : rien ne doit y buter contre le filet
   du pied (bornes du rayon, dernière semaine du mois, champ du numéro), le corps reprend la
   gouttière du panneau. */
.filter-location-panel,
.calendar.filter-panel-body,
.event-bib-search.filter-panel-body {
    padding-bottom: var(--sp-space-6);
}

/* Dans le panneau Localisation, les suggestions se posent DANS le flux, sous le champ : le
   corps du panneau défile (overflow), un panneau absolu y était rogné et ne se voyait pas —
   c'est ce qui faisait croire que l'autocomplétion n'existait pas. En flux, elles poussent le
   curseur de rayon le temps du choix, comme sur la maquette. */
.filter-location-panel .places-suggestions {
    position: static;
    max-height: none;
    margin-top: var(--sp-space-2);
    box-shadow: none;
    border: 1px solid var(--sp-color-border-default);
}

/* Sortie de la rangée de chips (DESIGNAPP, « Effacer les filtres »). Pas de fond ni d'ombre :
   la surface est ce qui fait une chip, et une sortie n'est pas un filtre de plus. Elle se cale
   sur la hauteur des chips pour tenir la ligne, et garde la typo d'un lien de section.

   L'orange est une EXCEPTION tracée au DESIGNAPP : seul élément sans surface d'une rangée qui
   n'est faite que de surfaces, en ink il serait le plus discret de la barre au moment où il est
   le plus utile. text.link, donc — c'est un lien, et le tronc donne l'orange aux liens. Ne pas
   étendre : le « Voir tout » d'un en-tête de section reste ink.

   Typo des chips, pas celle d'un lien de section : size.label (14px) et weight.body (500). Elle
   prolonge la rangée, elle ne la surplombe pas — en 600 elle pèserait plus que les filtres
   qu'elle efface, et ajouterait une troisième graisse à la barre. */
.filter-clear {
    display: inline-flex;
    align-items: center;
    height: 36px;
    padding: 0 var(--sp-space-2);
    font-size: var(--sp-font-size-label);
    font-weight: var(--sp-font-weight-prose);
    line-height: 17px;
    letter-spacing: var(--sp-font-tracking-tight);
    color: var(--sp-color-text-link);
    text-decoration: none;
}

.filter-clear:hover {
    color: var(--sp-color-text-link);
    text-decoration: underline;
}

/* Le défilement horizontal impose overflow-x, qui rogne aussi le débord vertical :
   sans réserve, l'ombre des chips est coupée net. shadow.sm déborde de 4px sous la
   chip et de 2px au-dessus ; la réserve est symétrique pour ne pas décaler les chips
   quand la barre les centre (DESIGNAPP, « Défilement horizontal »). */
/* Les chips défilent au doigt sur mobile (DESIGNAPP, « Défilement horizontal »). Sur
   desktop elles tiennent la ligne : l'overflow y est rendu visible, sans quoi il rognerait
   le Dropdown ancré sous l'une d'elles — overflow-x rogne aussi le débord vertical, et
   c'est ce qui rendait le panneau invisible. */
.filter-chips {
    gap: var(--sp-space-2);
    scrollbar-width: none;
    padding: var(--sp-space-1) 0;
    overflow-x: auto;
}

@media (min-width: 992px) {
    .filter-chips {
        overflow: visible;
    }
}

.filter-chips::-webkit-scrollbar {
    display: none;
}

/* Btn-lg */

.btn-lg {
    --bs-btn-padding-y: .85rem;
    --bs-btn-padding-x: 1.25rem;
    --bs-btn-font-size: 1rem;
    /* radius.lg comme la taille md : la fiche button ne resserre le coin QUE sur `sm`. Ce bloc
       portait radius.md, ce qui faisait mentir la fiche sur toutes les grandes tailles. */
    --bs-btn-border-radius: var(--sp-radius-lg);
}

/*
 * Variantes DS (cf. designsystem/spicto/app/components/button.md) :
 * - .btn-marketing = « primary » du DS (orange) : l'intention la plus forte d'un
 *   parcours (inscription, achat), UN SEUL par écran.
 * - .btn-primary Bootstrap (ink) = « secondary » du DS : action standard.
 * - .btn-neutral = « neutral » du DS (crème) : action de faible emphase.
 */
/* Exception de rayon (fiche button) : les deux boutons d'acquisition d'une photo — acheter
   et télécharger — passent en pill. Ce sont les gestes qui font l'app ; ce rayon les distingue
   de tous les autres boutons, et d'eux seuls. */
.btn-pill {
    --bs-btn-border-radius: var(--sp-radius-full);
}

/* LE COIN DU BOUTON SUIT LA ZONE : radius.lg (16px) dehors, radius.md (12px) dans l'espace
   connecté. Pendant exact de la carte de section qui perd son ombre en passant la connexion —
   dehors l'interface accueille, dedans elle outille, et des boutons qui se multiplient en tête
   de section et en pied de formulaire paraissent plus gros qu'ils ne pèsent au rayon d'accueil
   (fiche button). Comme pour la carte, la frontière est la ZONE, portée par le gabarit, jamais
   la session : l'écran de connexion n'a pas de classe d'espace pro, ses boutons restent à 16px.

   Les trois exclusions sont écrites, jamais confiées à l'ordre de déclaration :
   - .btn-sm      garde radius.sm (8px) : le coin suit la TAILLE avant de suivre la zone ;
   - .btn-pill    garde son pill : acheter / télécharger le portent dans les deux zones ;
   - .btn-gesture les deux gestes fondateurs du tableau de bord (voir ci-dessous).
   .btn-circle n'a pas besoin d'exclusion : il pose son rayon en propriété directe, pas par la
   variable, et reste donc un disque.

   Rayon ET gouttière horizontale changent ENSEMBLE : c'est une seule décision à deux effets.
   Un coin resserré sur une gouttière d'accueil donne un bouton trapu ; une gouttière élargie
   sur un coin ouvert le fait paraître mou. Le vertical ne bouge pas — c'est la hauteur du
   bouton, elle appartient à la taille, pas à la zone. D'où un SEUL bloc pour les deux : les
   séparer, c'est se donner l'occasion de n'en déplacer qu'un. */
.club-layout .btn:not(.btn-sm):not(.btn-xs):not(.btn-pill):not(.btn-gesture),
.photographer-layout .btn:not(.btn-sm):not(.btn-xs):not(.btn-pill):not(.btn-gesture){
    --bs-btn-border-radius: var(--sp-radius-md);
    --bs-btn-padding-x: var(--sp-space-4);
    --bs-btn-padding-y: var(--sp-space-2);
}

/* « Créer un évènement » et « Déposer des photos » sur les TABLEAUX DE BORD : les deux gestes
   qui font vivre la plateforme gardent le coin d'accueil (16px), qui les rattache à ce dont ils
   sont la porte et les détache des commandes autour. La classe ne se pose QUE sur un tableau de
   bord (fiche button) : les mêmes gestes ailleurs dans l'espace connecté sont des boutons de
   travail à 12px. Elle ne s'étend à aucun troisième bouton — ce n'est pas « le CTA de l'écran »
   qui la reçoit, ce sont ces deux gestes-là. La valeur est réaffirmée plutôt que laissée au
   repli sur .btn : l'exclusion ci-dessus suffirait, mais elle rendrait l'intention illisible. */
.btn-gesture{
    --bs-btn-border-radius: var(--sp-radius-lg);
}

/* Variant « outline » de la fiche button : la même intention que primary, en retenue. Il garde
   l'orange pour dire qu'on reste dans la même famille d'action, mais rend le plein au CTA —
   il se définit par rapport au bouton qu'il suit. */
.btn-outline {
    --bs-btn-color: var(--sp-color-action-marketing);
    --bs-btn-bg: transparent;
    --bs-btn-border-color: var(--sp-color-action-marketing);
    --bs-btn-hover-color: var(--sp-color-action-primary-text);
    --bs-btn-hover-bg: var(--sp-color-action-marketing);
    --bs-btn-hover-border-color: var(--sp-color-action-marketing);
    --bs-btn-active-color: var(--sp-color-action-primary-text);
    --bs-btn-active-bg: var(--sp-color-action-marketing);
    --bs-btn-active-border-color: var(--sp-color-action-marketing);
    --bs-btn-disabled-color: var(--sp-color-action-marketing);
    --bs-btn-disabled-bg: transparent;
    --bs-btn-disabled-border-color: var(--sp-color-action-marketing);
}

/* Variant « tertiary » de la fiche button : lien / action fantôme, sans fond, texte ink. Sans
   surface, il ne pèse sur rien.

   LE SOULIGNEMENT APPARTIENT AU RENVOI, PAS AU VARIANT (fiche button). Un tertiary qui MÈNE
   AILLEURS — la sortie d'un parcours (« Annuler le dépôt ») — n'a que ce trait pour se donner
   comme cliquable. Un tertiary qui AGIT SUR PLACE et porte un glyphe — la proposition qui ouvre
   un champ facultatif — ne se souligne pas : le glyphe le désigne déjà comme un contrôle, et le
   trait lui promettrait une destination qu'il n'a pas. La frontière est celle de <a> et de
   <button>, d'où le sélecteur ci-dessous plutôt qu'un modificateur de plus. */
.btn-tertiary {
    --bs-btn-color: var(--sp-color-text-default);
    --bs-btn-bg: transparent;
    --bs-btn-border-color: transparent;
    --bs-btn-hover-color: var(--sp-color-text-default);
    --bs-btn-hover-bg: transparent;
    --bs-btn-hover-border-color: transparent;
    --bs-btn-active-color: var(--sp-color-text-default);
    --bs-btn-active-bg: transparent;
    --bs-btn-active-border-color: transparent;
}

/* Le renvoi, lui, se souligne : 0,1,1 l'emporte sur le `text-decoration: none` de .btn (0,1,0). */
a.btn-tertiary {
    text-decoration: underline;
}

/* Stepper (fiche stepper) : compteur puis noms d'étapes séparés de flèches. Il informe, il
   n'agit pas — d'où sa place au pied de la carte, sous les actions, et son absence de surface. */
.stepper{
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--sp-space-3);
}

.stepper-count{
    flex-shrink: 0;
}

.stepper-list{
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--sp-space-2);
    list-style: none;
    margin: 0;
    padding: 0;
    font-size: var(--sp-font-size-label);
    font-weight: var(--sp-font-weight-body);
}

.stepper-step--done{ color: var(--sp-color-text-default); }

/* Une étape faite y ramène : revenir sur un choix ne doit pas coûter plus cher que l'avoir
   fait (fiche stepper). Souligné, parce que dans une frise de mots c'est la seule chose qui
   distingue ce qui se clique de ce qui se lit. */
.stepper-link{
    color: inherit;
    text-decoration: underline;
}

.stepper-link:hover{ color: var(--sp-color-text-default); }
/* L'orange marque l'étape courante : c'est un état, pas une action (fiche stepper) */
.stepper-step--current{ color: var(--sp-color-accent-selected); }
.stepper-step--upcoming{ color: var(--sp-color-text-muted); }

.stepper-arrow{
    display: inline-flex;
    color: var(--sp-color-text-muted);
}

/* Étape franchie, repliée : nom, ce qui y a été décidé, et « Modifier ».

   bg.default, le crème du fond de page — le seul endroit du système où il revient DANS une
   carte, et c'est le sens qu'on lui donne : une étape close retombe au niveau de la page. Le
   bg.sunken, plus soutenu, dirait « regarde ici » à ce qui est justement derrière soi
   (DESIGNAPP, « Une étape faite se replie en récapitulatif »). */
/* Le récapitulatif est une COLONNE : sa tête (identité + « Modifier ») et, quand l'étape a
   décidé plusieurs choses de natures différentes, ses qualificatifs sous un filet (DESIGNAPP).
   C'est `.step-recap-head` qui porte désormais la rangée — le parcours de dépôt l'emploie aussi,
   pour que les deux récapitulatifs gardent la même anatomie. */
.step-recap{
    display: flex;
    flex-direction: column;
    padding: var(--sp-space-4);
    margin-bottom: var(--sp-space-4);
    background-color: var(--sp-color-bg-default);
    /* EN DESSOUS de la carte qui le porte, comme tout ce qui s'emboîte (DESIGN, « Ce qui est
       posé dans une carte a le coin plus fermé qu'elle »). Ce n'est pas son rayon qui
       l'empêche de se lire comme une étape encore ouverte, c'est sa surface : bg.default, le
       crème du fond de page — une étape close retombe au niveau de la page. */
    border-radius: var(--sp-radius-xl);
}

/* La tête : l'identité de l'étape à gauche, « Modifier » à droite. */
/* Le « Modifier » s'aligne en HAUT, jamais au centre (DESIGNAPP) : sa hauteur ne dépend pas de ce
   qu'il y a à côté, alors que la méta tient sur une ligne ou sur trois selon l'étape. Centré, il
   descendrait à mesure que le récapitulatif s'allonge, et une colonne de récapitulatifs verrait
   ses boutons flotter chacun à une hauteur différente. */
.step-recap-head{
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--sp-space-3);
}

/* Le nom de l'étape et ce qu'il résume respirent : collés, la méta se lit comme la deuxième ligne
   du titre et le bloc perd le seul indice qui dit lequel des deux porte. L'écart se pose ici, en
   gouttière de flex, et non en marge de titre : les deux `<p>` portent `mb-0`, qu'une utilitaire
   Bootstrap défend en `!important`. */
.step-recap-lines{
    display: flex;
    flex-direction: column;
    gap: var(--sp-space-2);
}

/* Le filet sépare l'IDENTITÉ de ses qualificatifs. Il prend la gouttière du récapitulatif sur
   toute sa largeur : c'est un partage du bloc, pas un ornement sous une ligne. */
.step-recap-rule{
    margin: var(--sp-space-3) 0;
    border: 0;
    border-top: var(--sp-border-width-default) solid var(--sp-color-border-cream);
    opacity: 1;
}

/* Les qualificatifs sont de la MÉTA : size.meta (13px), text.muted, libellé et valeur d'un SEUL
   ton (DESIGNAPP). Les partager en deux nuances reviendrait à hiérarchiser à l'intérieur de ce
   qui est déjà secondaire, et à faire croire qu'une moitié de la ligne prime alors qu'on la lit
   d'un bloc. C'est le contraste avec la ligne d'identité, en text.default, qui dit lequel des
   deux blocs porte. */
.step-recap-detail,
.step-recap-detail-label{
    font-size: var(--sp-font-size-meta);
    color: var(--sp-color-text-muted);
}

/* La valeur (discipline, organisateur) se détache en semibold ; le chemin porte le glyphe du
   sport et un chevron aéré de part et d'autre (retour client). */
.step-recap-detail{
    display: flex;
    flex-wrap: wrap;
    align-items: center;
}

.step-recap-detail-label{
    margin-right: var(--sp-space-1);
}

.step-recap-detail-value{
    font-weight: var(--sp-font-weight-title);
}

.step-recap-detail-icon{
    flex-shrink: 0;
    margin-right: var(--sp-space-2);
}

.step-recap-detail-chevron{
    flex-shrink: 0;
    margin: 0 var(--sp-space-2);
}

/* Le bouton y passe au blanc, sinon il se noie : son crème et celui de la surface sont trop
   proches pour se distinguer. Même règle que dans une carte crème (fiche card). */
.step-recap .btn-neutral{
    --bs-btn-bg: var(--sp-color-bg-surface);
    --bs-btn-border-color: var(--sp-color-bg-surface);
    --bs-btn-hover-bg: var(--sp-color-bg-surface);
    --bs-btn-hover-border-color: var(--sp-color-bg-surface);
    --bs-btn-active-bg: var(--sp-color-bg-surface);
    --bs-btn-active-border-color: var(--sp-color-bg-surface);
}

/* Le nom de l'étape est un titre de bloc DANS une carte : size.h4, et non la primitive 16 qu'il
   lisait — un composant ne lit jamais une primitive (DESIGN). Même valeur, le rôle en plus. */
.step-recap-title{
    font-size: var(--sp-font-size-h4);
    font-weight: var(--sp-font-weight-title);
    color: var(--sp-color-text-default);
}

/* Ce que l'étape a décidé : à `size.body`, un cran au-dessus des qualificatifs qui vivent sous le
   filet (`size.meta`). C'est la TAILLE qui range ces deux secondaires entre eux, la couleur ne
   sert qu'une fois — à les distinguer du nom de l'étape, seul en text.default (DESIGNAPP). */
.step-recap-meta{
    font-size: var(--sp-font-size-body);
    font-weight: var(--sp-font-weight-body);
    color: var(--sp-color-text-muted);
}

/* Variant « dark » de la fiche card : il isole le chiffre qui décide de la visite. UNE seule
   par vue — multiplié, il perd exactement ce qu'on lui demande : trancher. */
.card-dark {
    background-color: var(--sp-color-bg-dark);
    color: var(--sp-color-text-inverse);
    border-color: transparent;
}

/* Un lien ne suit PAS la couleur du texte courant : il tire la sienne de --bs-link-color, qui
   vaut l'ink — soit exactement bg.dark. Sans cette règle il disparaît dans son fond (1:1) sans
   qu'aucune autre n'ait l'air violée. Le soulignement reste : privé de couleur propre, il n'a
   plus que lui pour se distinguer de la phrase (fiche card, variant dark). Les boutons, eux,
   portent leurs propres --bs-btn-* et ne sont pas concernés. */
/* Même piège que le lien ci-dessous, un cran plus haut : un titre ne tire pas sa couleur du
   texte qui l'entoure mais de --bs-heading-color (l'ink). Entré dans la carte — l'en-tête de
   section est dedans, désormais —, il y resterait ink sur ink (DESIGNAPP, « L'en-tête entre
   dans la carte »). */
.card-dark :is(h1, h2, h3, h4, h5, h6){
    color: var(--sp-color-text-inverse);
}

.card-dark a:not(.btn) {
    color: var(--sp-color-text-inverse);
    text-decoration: underline;
}

/* Carte de SECTION : blanc, radius.lg, gouttière space.6, SANS filet — le même rendu partout,
   À UNE VARIABLE PRÈS, l'ombre. L'ombre ou le filet, jamais les deux (fiche card). C'est le
   pendant de `.section-surface`, qui applique le même rendu à un bloc qui n'est pas une .card
   Bootstrap ; les deux disent la même surface. */
.card-section{
    box-shadow: var(--sp-shadow-sm);
}

/* HORS espace connecté, la carte porte l'ombre : elle est minoritaire au milieu de
   photographies et de fond crème, et c'est l'ombre qui la pose comme une surface. DANS
   l'espace connecté, l'écran EST fait de cartes : une ombre sous chacune ne distingue plus
   rien et ajoute un halo par bloc — elles sont donc plates, exprès (fiche card).

   La frontière est la ZONE, jamais la session : c'est le GABARIT qui la porte, si bien qu'une
   page publique garde son ombre quand un utilisateur connecté la consulte. Prendre la session
   pour critère rendrait le même écran de deux façons selon le visiteur, et masquerait le
   défaut en développement, où l'on est presque toujours connecté. */
.club-layout .card-section,
.photographer-layout .card-section{
    box-shadow: var(--sp-shadow-none);
}

/* TABLEAU DE BORD, et lui seul : les cartes du fond ouvrent leur coin à 2xl (24px). C'est la
   suite de la règle ci-dessus — privée d'ombre, la carte n'a plus que son coin pour se donner
   comme surface. Ailleurs dans l'espace connecté, `lg` suffit : les cartes y sont peu
   nombreuses et empilées en une colonne. Le tableau de bord est le seul à les juxtaposer en
   mosaïque sur trois colonnes, où, plates et serrées, elles retomberaient en cases de tableau.

   Le sélecteur porte sur .card, PAS sur .card-section : la cagnotte est une `dark` et le profil
   une `photo`, ni l'une ni l'autre ne porte la classe de section, et toutes deux sont pourtant
   des cartes du fond. Les laisser à 16px les distinguerait par leur DÉCOUPE, alors que ces
   variants se distinguent par leur FOND et par lui seul (fiche card, « un même niveau de
   surface, un même rayon »).

   La règle d'emboîtement est LEVÉE ici : une carte de premier niveau est TOUJOURS à 24px,
   qu'elle héberge une tuile ou non — pas de 36px sur cet écran. La mosaïque prime, et
   l'emboîtement se dit sans le coin, par le filet de la tuile posée sur du blanc.

   Seul :not(.card-nested) demeure, et il est écrit plutôt que confié à l'ordre de déclaration
   (la fragilité qui avait rendu .card-section inerte) : les tuiles ne sont pas de premier
   niveau et gardent leurs 20px. */
.dashboard-view .card:not(.card-nested){
    --bs-card-border-radius: var(--sp-radius-2xl);
}

/* La carte `photo` ne porte pas sa gouttière sur son card-body : c'est le SCRIM qui la porte
   (fiche card), et il est à space.4 partout ailleurs. Sur le tableau de bord, où toute carte
   du fond est à 24px, il suit — sinon le contenu de la carte de profil commencerait 8px plus
   près du bord que celui de ses voisines, et la mosaïque perdrait son alignement. C'est le
   PORTEUR qui est propre au composant, pas la valeur. */
.dashboard-view .card-photo-scrim{
    padding: var(--sp-space-6);
}

/* Bulle de message adressée à l'utilisateur (fiche message). Elle prend la largeur de son
   texte, jamais celle de l'écran : pleine largeur, elle se lirait comme un bandeau système —
   quelque chose que la plateforme impose —, alors qu'ici l'interface s'adresse à quelqu'un.
   Même ombre que les chips de filtre : c'est la surface flottante de l'app. */
.message{
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--sp-space-4);
    width: fit-content;
    max-width: 100%;
    padding: var(--sp-space-4);
    border-radius: var(--sp-radius-lg);
    background-color: var(--sp-color-bg-surface);
    color: var(--sp-color-text-default);
    box-shadow: var(--sp-shadow-sm);
}

/* L'emoji précède le titre et reste décoratif : il donne un ton, jamais une information
   (fiche message, ICONS.md). L'espace le sépare du mot sans dépendre d'une espace typographique
   dans le gabarit. */
.message-title{
    font-size: var(--sp-font-size-16);
    font-weight: var(--sp-font-weight-title);
}

.message-title > span{
    margin-right: var(--sp-space-2);
}

/* La croix s'aligne sur la LIGNE DU TITRE, pas sur le centre de la bulle : elle ferme le
   message, elle ne l'accompagne pas (fiche message). Sa cible tactile fait 44px, soit deux
   fois la hauteur de cette ligne : on la remonte donc de la moitié de l'écart, pour que son
   glyphe retombe au centre du titre sans que le bouton perde sa cible. L'écart se calcule
   depuis la typo du titre — si elle change, l'alignement suit. */
.message-dismiss{
    flex-shrink: 0;
    margin-top: calc(
        (var(--sp-font-size-16) * var(--sp-font-leading-normal) - var(--sp-control-icon-button)) / 2
    );
}

/* Une section qui EST un chiffre le pose sur la ligne de son titre, aligné à droite : le titre
   nomme, le chiffre répond. En display sous le titre, il ouvrirait une deuxième zone de lecture
   pour dire ce que la section annonce déjà (DESIGNAPP, « Le chiffre d'une section »). */
.section-header-figure{
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-space-3);
}

/* Inter, pas Anuphan : deux fontes qui se font face sur une même ligne se lisent comme un
   accident de rendu, pas comme une hiérarchie — c'est la graisse qui distingue (tronc). */
.section-figure{
    font-family: var(--sp-font-family-base), sans-serif;
    font-size: var(--sp-font-size-figure);
    font-weight: var(--sp-font-weight-bold);
    white-space: nowrap;
}

/* L'en-tête entré dans la carte garde l'écart qu'il avait sur le fond (space.3, comme
   .sec-header) : entrer dans la surface ne change pas la respiration d'un titre. */
.card-section > h3,
.card-dark > h3{
    margin-bottom: var(--sp-space-3);
}

/* Carte IMBRIQUÉE dans une carte : filet et pas d'ombre — il n'y a plus de fond crème sous
   elle pour porter une ombre, et deux ombres empilées ne font que salir la carte hôte.
   Rayon xl (20px) pendant que son hôte monte à 3xl (36px) : l'emboîtement de deux CARTES
   ÉCARTE les deux coins au lieu de les rapprocher — à rayons voisins, deux surfaces
   concentriques se confondent en un défaut d'alignement (fiche card, tronc « Shape »). */
.card-nested{
    --bs-card-border-radius: var(--sp-radius-xl);
    /* La gouttière s'ajoute à celle de l'hôte : space.6 dedans comme dehors ferait 48px de
       vide le long du bord partagé (fiche card). */
    --bs-card-spacer-x: var(--sp-space-3);
    --bs-card-spacer-y: var(--sp-space-3);
    /* SEUL FILET GRIS DU SYSTÈME (tronc, « Color » ; fiche card). Il n'y a plus de crème sous
       cette carte à prolonger : border.default y tombe à 1,21:1 sur du blanc, un trait qu'on
       devine sans le voir. border.on-white remonte à 1,53:1. Ce n'est pas border.cream (1,58:1,
       même poids) parce que celui-là est le filet d'un CONTRÔLE, et une carte n'en est pas un. */
    border: 1px solid var(--sp-color-border-on-white);
    box-shadow: var(--sp-shadow-none);
}

/* Sur l'étape de VALIDATION, tous les blocs de la carte prennent le crème le plus clair, sans
   filet (DESIGNAPP) : cette étape ne demande plus rien, elle donne à relire avant l'orange, et
   tout y est au même rang — c'est la surface du récapitulatif d'étape, étendue à ses voisins. Le
   filet tombe parce que la teinte délimite déjà ; un filet par-dessus ferait double emploi, comme
   l'ombre et le filet ne cohabitent jamais (fiche card). Les étapes de SAISIE, elles, gardent
   leurs groupes d'options à filet sur le blanc : là on décide, ici on vérifie.

   Deux conséquences suivent le changement de sol, et elles sont ci-dessous : le filet interne
   redevient chaud, et le texte secondaire quitte le gris, qui est calculé pour le blanc. */
.card-nested-cream{
    background-color: var(--sp-color-bg-default);
    border-color: transparent;
}

.card-nested-cream .card-rule{
    border-top-color: var(--sp-color-border-cream);
}

/* Le texte secondaire d'un panneau : muted sur du blanc… */
.panel-note{
    color: var(--sp-color-text-muted);
}

/* …et brun dès que le sol devient crème — c'est le SOL qui décide, le gris étant calculé pour le
   blanc (DESIGNAPP, « Bordures et séparateurs »). */
.card-nested-cream .panel-note{
    color: var(--sp-color-text-brown);
}

/* Filet INTERNE d'une carte blanche : entre deux champs, entre une consigne et la case qui la
   suit, entre ce qui bouge et ce qui est décidé. Dans une carte qui empile des blocs sans surface
   propre, seule la ligne dit où l'un finit et où l'autre commence — un simple écart vertical se
   confond avec celui qui sépare un libellé de son champ. Il respire autant des deux côtés : il
   appartient à l'intervalle, pas au bloc qui le précède.

   Il court sur du BLANC, donc il est gris (border.on-white), comme le contour de la carte qui
   le porte : c'est le SOL qui décide de la teinte d'un filet, pas sa nature (DESIGNAPP). En
   crème il resterait chaud — cf. .step-recap-rule, qui vit dans un récapitulatif crème. */
.card-rule{
    margin: var(--sp-space-4) 0;
    border: 0;
    border-top: var(--sp-border-width-default) solid var(--sp-color-border-on-white);
    opacity: 1;   /* Bootstrap pose .5 sur hr : le filet est déjà un ton clair, l'atténuer l'efface */
}

/* Le filet qui sépare le contenu d'une carte de son PIED (le Stepper, sous les actions). Même
   teinte et même raison que .card-rule — blanc dessous —, mais sa gouttière est dissociée :
   il prend plus d'air au-dessus, où il quitte le formulaire, que dessous, où le pied le suit. */
.card-foot-rule{
    margin: var(--sp-space-6) 0 var(--sp-space-4);
    border: 0;
    border-top: var(--sp-border-width-default) solid var(--sp-color-border-on-white);
    opacity: 1;
}

/* Bloc de tête d'un Select, DÉCORATIF au même titre que le chevron (fiche select) : le glyphe du
   sport parent puis son nom, que le champ fermé perdrait sinon — il ne montre jamais l'optgroup.
   Il ne porte rien que la liste ne dise déjà. Le select natif reste le seul contrôle — d'où
   `pointer-events: none`, qui laisse passer le clic jusqu'à lui. */
.select-lead-icon{
    display: none;
    align-items: center;
    gap: var(--sp-space-2);
    color: var(--sp-color-text-default);
    /* Le parent ne se replie jamais : il occupe une colonne, et un retour à la ligne ferait
       grandir le champ au lieu de pousser le texte du select. */
    white-space: nowrap;
    /* Le select natif reste le seul contrôle : le clic traverse le bloc jusqu'à lui. */
    pointer-events: none;
}

.select-lead-glyph{
    display: inline-flex;
    align-items: center;
}

/* SANS valeur choisie, rien à loger : le select se rend seul, exactement comme les autres champs
   de la carte, et le placeholder démarre là où démarrent les leurs.

   AVEC une valeur, le bloc entre EN FLUX et c'est la mise en page qui lui réserve la place : le
   champ devient une rangée [bloc de tête][select]. L'habillage — fond, filet, rayon, hauteur,
   anneau de focus — passe alors au conteneur, et le select se rend transparent à l'intérieur.

   C'est volontairement du CSS et non une mesure JavaScript. Une gouttière calculée depuis la
   largeur du bloc doit tenir compte de son décalage, se recalculer au chargement de la fonte,
   au redimensionnement et à chaque changement de valeur — trois occasions de coller le texte
   contre le « › », et c'est exactement ce qui est arrivé. En flux, la place ne se calcule pas :
   elle est occupée. */
.select-lead.has-lead{
    display: flex;
    align-items: center;
    gap: var(--sp-space-2);
    height: calc(52px + calc(var(--bs-border-width) * 2));
    padding-left: var(--sp-space-3);
    background-color: var(--sp-color-bg-surface);
    border: var(--bs-border-width) solid var(--sp-color-border-cream);
    border-radius: var(--field-radius);
}

.select-lead.has-lead .select-lead-icon{
    display: inline-flex;
}

/* Le champ garde son chevron et son comportement natifs ; il rend seulement son habillage au
   conteneur, qui le porte désormais pour eux deux. */
.select-lead.has-lead .form-select{
    flex: 1 1 auto;
    min-width: 0;
    height: 100%;
    min-height: 0;
    padding-left: 0;
    background-color: transparent;
    border: 0;
    box-shadow: none;
}

/* L'anneau de focus suit le contrôle jusqu'à son nouveau porteur : c'est le conteneur qui se
   dessine, mais c'est bien le select natif qui a le focus. */
.select-lead.has-lead:focus-within{
    border-color: var(--sp-color-border-focus);
    box-shadow: var(--sp-shadow-ring);
}

/* Carte imbriquée qui porte des CHAMPS : gouttière dissociée, 16px en vertical et 24px en
   horizontal. Le space.3 ci-dessus a été calibré pour une TUILE, dont la gouttière mange le
   contenu ; un champ occupe toute la largeur qu'on lui laisse et n'a pas besoin de place mais
   d'un retrait qui le décolle du filet — à 12px, un contrôle de 40px paraît collé à son cadre.
   Les 48px le long du bord partagé sont assumés ici : rien ne se lit dans cette marge. Le
   vertical reste à 16px parce qu'il sert l'EMPILEMENT, pas le retrait (fiche card).

   Classe déclarée, jamais déduite d'un `form` ancêtre : le dépôt de photos est un écran de
   saisie SANS <form> (upload piloté en JS, les champs ne se sérialisent pas), et il doit
   respirer comme les autres étapes de son parcours. */
.card-nested-fields{
    --bs-card-spacer-y: var(--sp-space-4);
    --bs-card-spacer-x: var(--sp-space-6);
}

/* La carte dont le contenu principal est un CADRE VISIBLE — la zone de dépôt et son pointillé —
   reprend une gouttière UNIFORME (fiche card). La dissociation des axes est écrite pour un
   empilement de champs, où le vertical se rabat parce qu'il y a de la hauteur à économiser ; ici
   il n'y a rien à empiler, et la gouttière n'est plus un retrait avant des champs mais la marge
   autour d'un rectangle. Inégale, elle ne se lit pas comme de la densité mais comme un défaut de
   centrage. */
.card-nested-framed{
    --bs-card-spacer-y: var(--sp-space-6);
    --bs-card-spacer-x: var(--sp-space-6);
}

/* La carte qui HÉBERGE une carte imbriquée : c'est l'unique exception à « un même niveau de
   surface, un même rayon » (fiche card). Le sélecteur suit la RÈGLE plutôt qu'une classe à
   poser à la main : une carte devient hôte parce qu'elle contient une carte imbriquée, et
   c'est exactement ce que :has() sait dire. Descendant et non enfant direct — le formulaire
   rendu par form_start s'intercale souvent entre les deux. */
.card:has(.card-nested){
    --bs-card-border-radius: var(--sp-radius-3xl);
}

/* Quand la carte mène quelque part, c'est ELLE le lien : cible sur toute la surface, et
   aucun renvoi posé sous son contenu. Elle ne prend ni la couleur ni le soulignement d'un
   lien — c'est sa surface qui signale, pas sa typographie (fiche card). */
a.card-nested{
    color: inherit;
    text-decoration: none;
    transition: box-shadow var(--sp-duration-fast) var(--sp-easing-standard);
}

/* Élévation seule, comme toute carte (tronc DESIGN.md, Motion). */
a.card-nested:hover{
    box-shadow: var(--sp-shadow-md);
}

a.card-nested:focus-visible{
    outline: none;
    box-shadow: var(--sp-shadow-ring);
}

@media (prefers-reduced-motion: reduce) {
    a.card-nested{
        transition: none;
    }
}

/* Variant « sunken » de la fiche card : crème creusé, pour l'encart d'une autre nature que
   les blocs qui l'entourent. Le bouton y passe au blanc — le crème du bouton `neutral` est à
   un cran de ce fond et s'y noierait : deux crèmes voisins font une tache, pas un bouton. */
.card-sunken{
    background-color: var(--sp-color-bg-sunken);
}

.card-sunken .btn-neutral{
    --bs-btn-bg: var(--sp-color-bg-surface);
    --bs-btn-border-color: var(--sp-color-bg-surface);
    --bs-btn-hover-bg: var(--sp-color-bg-surface);
    --bs-btn-hover-border-color: var(--sp-color-bg-surface);
    --bs-btn-active-bg: var(--sp-color-bg-surface);
    --bs-btn-active-border-color: var(--sp-color-bg-surface);
}

/* Variant « photo » de la fiche card : le fond est une photographie, le texte repose sur le
   scrim de l'identité — bas-vers-haut, overlay.scrim vers transparent. C'est une surface
   d'identité : elle porte du texte en haut (avatar, nom, lieu) comme en bas (les chiffres),
   donc le scrim couvre TOUTE la surface et non une bande basse. Les actions restent en haut,
   en verre. Son fond n'est jamais vide (fiche card). */
.card-photo{
    position: relative;
    display: flex;
    flex-direction: column;
    min-height: 248px;
    overflow: hidden;
    border-color: transparent;
    color: var(--sp-color-text-inverse);
}

.card-photo-media{
    position: absolute;
    inset: 0;
    z-index: 0;
}

.card-photo-media img{
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* Le scrim occupe toute la carte : il porte l'identité en tête et les chiffres au pied, la
   rampe traversant la surface entière. Ce que ça coûte est tracé dans la fiche : en haut de
   rampe le scrim ne porte plus rien, et c'est l'IMAGE qui tient la lisibilité — admissible
   tant que ce fond est l'image de marque, sombre par construction et la même pour tous. Le
   jour où l'utilisateur pourra fournir sa couverture, la règle se rouvre (fiche card). */
.card-photo-scrim{
    position: relative;
    z-index: 1;
    display: flex;
    flex: 1;
    flex-direction: column;
    padding: var(--sp-space-4);
    background: linear-gradient(
        to top,
        var(--sp-color-overlay-scrim) 0,
        transparent 100%
    );
}

/* Le bloc d'identité doit pouvoir rétrécir sous la largeur de son contenu, sinon un long
   pseudo déborde du scrim au lieu de se tronquer. */
.card-photo-identity{
    min-width: 0;
}

/* Les chiffres sont à l'autre bout de la surface : ils disent ce qu'on a fait, pas qui l'on
   est (fiche card, variant photo). */
.card-photo-stats{
    margin-top: auto;
}

/* Blanc explicite sur le titre : le scrim donne sa couleur par héritage au texte courant,
   mais un <hN> tire la sienne de --bs-heading-color (l'ink) et casse l'héritage — le nom
   restait sombre sur la photographie. Même famille de piège que le lien sur card-dark
   (fiche card, variant photo : tout le texte de la carte est en text.inverse). */
.card-photo :is(h1, h2, h3, h4, h5, h6){
    color: var(--sp-color-text-inverse);
}

/* Le portrait en tête : avatar.lg quand la carte est en colonne (fiche avatar). La taille
   vient du token, jamais d'une règle d'écran.

   Cette règle existe pour le balisage du tableau de bord, qui pose un <img class="avatar">
   brut au lieu du composant Avatar et n'a donc pas de classe de taille. La disposition
   `banner` en est EXCLUE : son portrait passe le sien en `xl` par le composant, et sans ce
   `:not()` cette règle — plus spécifique — le ramènerait à 64px. */
.card-photo:not(.card-photo--banner) .avatar{
    width: var(--sp-avatar-lg);
    height: var(--sp-avatar-lg);
}

/* Le lieu, sous le nom : de la méta, en casse phrase — le DS n'écrit pas en majuscules. */
.card-photo-meta{
    font-size: var(--sp-font-size-meta);
    color: var(--sp-color-text-inverse);
}

.card-photo-actions{
    position: absolute;
    top: var(--sp-space-4);
    right: var(--sp-space-4);
    z-index: 2;
}

/* Deux actions ne tiennent pas dans le coin haut droit : empilées sur le visage, elles font
   un bloc de commandes et la carte cesse d'être un portrait. Elles descendent au pied, où le
   scrim est le plus opaque — donc l'endroit le plus sûr pour un libellé —, et s'y séparent
   par nature : à gauche celle qui MODIFIE la carte, à droite celle qui en SORT (fiche card).
   Sans glyphe : il venait après le mot pour ancrer un bouton à droite ; sur celui de gauche,
   il pointerait vers le vide. */
.card-photo-footer{
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-space-3);
    margin-top: auto;
}

/* Disposition « banner » du variant photo (fiche card) : l'identité se couche. La bascule
   tient à la LARGEUR DE LA COLONNE, pas à l'écran — cette carte occupe la colonne large des
   paramètres, là où le tableau de bord la range dans une colonne étroite parmi trois. Sous ce
   seuil elle redevient « column », et c'est le défaut : rien à défaire ici. */
@media (min-width: 992px){
    .card-photo--banner .card-photo-identity{
        display: flex;
        align-items: center;
        gap: var(--sp-space-4);
    }

    /* La colonne de texte doit pouvoir rétrécir sous son contenu, sinon un long pseudo pousse
       le bloc hors du scrim au lieu de se tronquer. */
    .card-photo--banner .card-photo-identity-text{
        min-width: 0;
    }

    /* Sans pied, l'identité se centre (fiche card). La carte a un plancher de 248px ; à deux
       actions il est tenu aux deux bouts, à une seule le pied reste vide et l'identité calée
       en tête laisse sous elle une bande de photographie nue. C'est le cas de l'organisateur,
       qui n'a pas de profil public d'où sortir. */
    .card-photo--banner .card-photo-scrim:not(:has(.card-photo-footer)){
        justify-content: center;
    }

    /* Les chiffres rejoignent l'identité : le pied revient aux actions, et un chiffre isolé
       sous deux boutons ne se lirait plus comme un trait de portrait (fiche card). */
    .card-photo--banner .card-photo-stats{
        margin-top: var(--sp-space-2);
    }

    /* Couchée, la carte change d'échelle : le nom devient ce qu'il est sur cette surface — le
       SUJET, pas un titre —, d'où font.size.identity (48px), la seule taille au-dessus du hero
       (DESIGN.md). Il monte avec le portrait, jamais sans lui : à avatar.lg sous un nom de
       48px, le visage serait plus petit que le mot qui le nomme (fiche avatar).

       Ce sélecteur est plus lourd qu'il n'en a l'air, et pas par confort : `.photographer-layout
       h1:not(.page-title)`, plus haut, dimensionne TOUS les h1 des espaces pro — y compris ceux
       qu'un composant possède — et il gagnait à égalité. C'est exactement ce que la fiche card
       interdit (« aucune règle de page ne redéfinit ce qui est propre au composant ») ; tant
       qu'elle vit, un titre de composant doit la dépasser au lieu de dépendre de l'ordre du
       fichier. */
    .card-photo--banner .card-photo-identity-text h1.card-photo-name{
        font-size: var(--sp-font-size-identity);
        line-height: var(--sp-font-leading-tight);
    }
}

/* Sur le scrim, le muted du libellé tomberait sous l'AA : valeur ET libellé passent en
   text.inverse, et c'est la taille qui hiérarchise — comme la méta d'EventCardHighlighted.
   Le bloc s'y resserre aussi : sur cette carte, un chiffre est un trait de portrait, pas le
   chiffre de l'écran — valeur en size.body, libellé en size.meta (DESIGNAPP, « Bloc de
   statistique »). */
.card-photo .stat-block-value,
.card-photo .stat-block-label{
    color: var(--sp-color-text-inverse);
}

.card-photo .stat-block-value{
    font-size: var(--sp-font-size-body);
}

.card-photo .stat-block-label{
    font-size: var(--sp-font-size-meta);
}

/* Variant « free » de la fiche button : le téléchargement OFFERT. Le vert y dit la gratuité,
   l'orange dirait l'achat — et les deux ne se disputent jamais la même zone (une photo est
   vendue ou offerte). Hors de ce rôle, le vert reste feedback.success. */
.btn-free {
    --bs-btn-color: var(--sp-color-action-primary-text);
    --bs-btn-bg: var(--sp-color-action-free);
    --bs-btn-border-color: var(--sp-color-action-free);
    --bs-btn-hover-color: var(--sp-color-action-primary-text);
    --bs-btn-hover-bg: var(--sp-color-action-free);
    --bs-btn-hover-border-color: var(--sp-color-action-free);
    --bs-btn-active-color: var(--sp-color-action-primary-text);
    --bs-btn-active-bg: var(--sp-color-action-free);
    --bs-btn-active-border-color: var(--sp-color-action-free);
    --bs-btn-disabled-color: var(--sp-color-action-primary-text);
    --bs-btn-disabled-bg: var(--sp-color-action-free);
    --bs-btn-disabled-border-color: var(--sp-color-action-free);
}

.btn-marketing {
    --bs-btn-color: var(--sp-color-action-primary-text);
    --bs-btn-bg: var(--sp-color-action-marketing);
    --bs-btn-border-color: var(--sp-color-action-marketing);
    --bs-btn-hover-color: var(--sp-color-action-primary-text);
    --bs-btn-hover-bg: var(--sp-color-orange-400); /* primitive dédiée au survol de l'accent */
    --bs-btn-hover-border-color: var(--sp-color-orange-400);
    --bs-btn-active-color: var(--sp-color-action-primary-text);
    --bs-btn-active-bg: var(--sp-color-action-marketing);
    --bs-btn-active-border-color: var(--sp-color-action-marketing);
    --bs-btn-disabled-color: var(--sp-color-action-primary-text);
    --bs-btn-disabled-bg: var(--sp-color-action-marketing);
    --bs-btn-disabled-border-color: var(--sp-color-action-marketing);
}

/* Sans souris, pas de survol : sur un écran tactile le :hover reste collé après le toucher, et
   le bouton gardait l'orange clair du survol — d'où « toujours pas la bonne teinte » (retour
   client). L'orange de marque est le seul qu'un doigt doit voir. */
@media (hover: none) {
    .btn-marketing{
        --bs-btn-hover-bg: var(--sp-color-action-marketing);
        --bs-btn-hover-border-color: var(--sp-color-action-marketing);
    }
}

/* La PORTE du dépôt (DESIGNAPP, « Le bouton de dépôt est le seul bouton de 65px du produit ») :
   il occupe la laize de la colonne de travail et il est la raison d'être de l'écran. Cette
   hauteur ne se répercute nulle part ailleurs — ce n'est pas un bouton de formulaire. */
.btn-drop{
    min-height: 65px;
    padding: var(--sp-space-4) var(--sp-space-6);
    gap: var(--sp-space-4);
    border-radius: var(--sp-radius-2xl);
    font-size: var(--sp-font-size-16);
    font-weight: var(--sp-font-weight-title);
    line-height: 19px;
}

/* Destructif : rouge DS (feedback.danger, réservé aux actions destructives) */
.btn-danger {
    --bs-btn-bg: var(--sp-color-feedback-danger);
    --bs-btn-border-color: var(--sp-color-feedback-danger);
    --bs-btn-hover-bg: color-mix(in srgb, var(--sp-color-feedback-danger) 85%, black);
    --bs-btn-hover-border-color: color-mix(in srgb, var(--sp-color-feedback-danger) 85%, black);
    --bs-btn-active-bg: var(--sp-color-feedback-danger);
    --bs-btn-active-border-color: var(--sp-color-feedback-danger);
    --bs-btn-disabled-bg: var(--sp-color-feedback-danger);
    --bs-btn-disabled-border-color: var(--sp-color-feedback-danger);
}

.btn-outline-danger {
    --bs-btn-color: var(--sp-color-feedback-danger);
    --bs-btn-border-color: var(--sp-color-feedback-danger);
    --bs-btn-hover-bg: var(--sp-color-feedback-danger);
    --bs-btn-hover-border-color: var(--sp-color-feedback-danger);
    --bs-btn-active-bg: var(--sp-color-feedback-danger);
    --bs-btn-active-border-color: var(--sp-color-feedback-danger);
}

.btn-neutral {
    --bs-btn-color: var(--sp-color-text-default);
    --bs-btn-bg: var(--sp-color-bg-cream);
    --bs-btn-border-color: var(--sp-color-bg-cream);
    --bs-btn-hover-color: var(--sp-color-text-default);
    --bs-btn-hover-bg: var(--sp-color-bg-sunken);
    --bs-btn-hover-border-color: var(--sp-color-bg-sunken);
    --bs-btn-active-color: var(--sp-color-text-default);
    --bs-btn-active-bg: var(--sp-color-bg-sunken);
    --bs-btn-active-border-color: var(--sp-color-bg-sunken);
    --bs-btn-disabled-color: var(--sp-color-text-default);
    --bs-btn-disabled-bg: var(--sp-color-bg-cream);
    --bs-btn-disabled-border-color: var(--sp-color-bg-cream);
}

/* IconButton variant surface (fiche icon-button) : disque blanc plein à glyphe ink, réservé
   aux commandes de carrousel posées sur une photo. */
.btn-surface {
    --bs-btn-color: var(--sp-color-text-default);
    --bs-btn-bg: var(--sp-color-bg-surface);
    --bs-btn-border-color: var(--sp-color-bg-surface);
    --bs-btn-hover-color: var(--sp-color-text-default);
    --bs-btn-hover-bg: var(--sp-color-bg-default);
    --bs-btn-hover-border-color: var(--sp-color-bg-default);
    --bs-btn-active-color: var(--sp-color-text-default);
    --bs-btn-active-bg: var(--sp-color-bg-default);
    --bs-btn-active-border-color: var(--sp-color-bg-default);
}

/* IconButton variant glass (fiche icon-button) : sur fond sombre ou photo, reprend le
   fond du badge glass — verre sombre translucide, flou, liseré clair atténué (les mêmes
   glass.overlay.* que les compteurs sur photo). Icône blanche : le crème trancherait sur
   l'image, l'ink y disparaîtrait. */
.btn-glass {
    --bs-btn-color: var(--sp-color-text-inverse);
    --bs-btn-hover-color: var(--sp-color-text-inverse);
    --bs-btn-active-color: var(--sp-color-text-inverse);
    --bs-btn-bg: transparent;
    --bs-btn-border-color: transparent;
    --bs-btn-hover-bg: transparent;
    --bs-btn-hover-border-color: transparent;
    background: var(--sp-glass-button-bg);
    backdrop-filter: blur(var(--sp-glass-button-blur));
    -webkit-backdrop-filter: blur(var(--sp-glass-button-blur));
    border: 1px solid var(--sp-glass-button-border);
}

/* Plusieurs actions glass voisines se groupent dans UNE pilule de verre (fiche icon-button) :
   c'est le conteneur qui porte le verre, les items ne portent rien, aucune séparation entre eux —
   le groupe se lit comme un seul objet. */
.glass-group {
    display: inline-flex;
    align-items: center;
    border-radius: var(--sp-radius-full);
    background: var(--sp-glass-button-bg);
    backdrop-filter: blur(var(--sp-glass-blur));
    -webkit-backdrop-filter: blur(var(--sp-glass-blur));
    border: 1px solid var(--sp-glass-button-border);
    color: var(--sp-color-text-inverse);
}

/* « Les boutons ne portent RIEN : ni fond, ni bordure » (fiche icon-button). Ce n'est pas
   qu'une consigne de balisage : un <button> arrive avec le fond et le filet du navigateur, et
   sans ce remise à zéro il se dessine en carré clair au milieu du verre — le groupe cesse de
   se lire comme un seul objet. Un <a> ne le montrait pas, d'où le défaut invisible tant que
   les deux actions étaient des liens. */
.glass-group-item {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    /* Un disque reste un disque : il ne rétrécit ni ne s'étire dans la rangée. */
    flex: 0 0 auto;
    width: var(--sp-control-icon-button);
    height: var(--sp-control-icon-button);
    padding: 0;
    background: none;
    border: 0;
    border-radius: var(--sp-radius-full);
    color: var(--sp-color-text-inverse);
}

.glass-group-item:hover{
    color: var(--sp-color-text-inverse);
}

.glass-group-item:focus-visible{
    outline: none;
    box-shadow: var(--sp-shadow-ring);
}

/* Action de page NOMMÉE, en pilule glass — desktop, header de la page évènement (fiche
   event-card-highlighted, « les actions de page se nomment dans le header »). Le verre vient de
   .btn-glass, le rayon de .rounded-pill ; ici on ne règle que l'anatomie icône + mot : ils se
   suivent sur une ligne, sans retour, à l'échelle d'un label. La pilule porte son propre fond
   sombre — le mot repose sur lui, pas sur la photo —, donc pas de scrim haut à ajouter. */
.event-hero-action{
    display: inline-flex;
    align-items: center;
    gap: var(--sp-space-2);
    /* Hauteur posée, pas déduite : livrée à son contenu elle suit l'interligne. */
    min-height: 40px;
    padding: 7px 14px;
    font-size: var(--sp-font-size-body);
    font-weight: var(--sp-font-weight-title);
    /* La maquette l'écrit à -0.03em, sous le seuil de 20px de la règle. */
    letter-spacing: var(--sp-font-tracking-tighter);
    white-space: nowrap;
}

@media (min-width: 992px) {
    /* Le retour du hero desktop n'est PAS le verre sombre des actions : la maquette le pose en
       disque clair translucide à glyphe ink, un cran plus petit qu'elles (40 contre 44). */
    .event-highlighted-header--page .event-hero-back{
        /* les quatre : `.btn-circle` pose un min-* à la cible tactile, qui primerait */
        width: 40px;
        height: 40px;
        min-width: 40px;
        min-height: 40px;
        background-color: var(--sp-glass-button-bg-back);
        border-color: transparent;
        color: var(--sp-color-text-default);
    }
}

/* « Organisé par » accompagne le nom sans le porter : blanc atténué sur le verre. */
.event-hero-action-muted{
    opacity: .7;
}

/* Menu déroulant de l'organisateur : surface claire d'app (héritée de .dropdown-menu), largeur
   plafonnée pour que la description reste lisible sans s'étaler. */
.event-organizer-menu{
    max-width: 320px;
}

/* Aperçu de la page publique : la carte EventCardHighlighted au repos, sans photo (le sombre est
   hérité de .event-highlighted). Décorative, elle ne répond pas au survol comme une vraie tuile
   cliquable — elle annulait le déplacement, qui n'existe plus nulle part ; il ne restait que
   l'ombre à neutraliser. */
.event-highlighted-preview {
    cursor: default;
}

.event-highlighted-preview:hover {
    box-shadow: none;
}

/* Titre de la colonne d'accompagnement : size.h3.dense (15px), la graisse de titre venant déjà de
   la règle des h1..h5. La colonne portait deux tailles pour un même rang (16px ici, 20px aux
   astuces) — à 15px elle parle d'une voix et ne dispute plus au formulaire l'entrée de l'écran
   (DESIGNAPP). Une classe, pas `.h4` : celle-ci lit une primitive, et le rang ne se déduit pas
   d'un nom d'utilitaire Bootstrap. */
.aside-title{
    font-size: var(--sp-font-size-h3-dense);
}

/* Le titre des astuces, lui, NE descend PAS avec la colonne : l'encart voyage d'un écran à
   l'autre (création, dépôt), et un composant qui change de taille selon la colonne qui l'accueille
   a deux rendus pour une même chose. Il garde donc le `size.h3` de `.sec-header-title`, sans
   règle propre — la constance du composant l'emporte sur l'uniformité de la colonne (fiche tips,
   DESIGNAPP). C'est la même raison qui laisse la carte « Validation » à `size.h3` dans cette
   colonne, par un autre chemin : elle, c'est une section de formulaire déplacée à droite. */

/* APERÇU DE LA PAGE PUBLIQUE, sous la carte : ce que la page dira de l'évènement (DESIGNAPP).

   IL NE CHANGE JAMAIS DE TEINTE : c'est la PAGE qui bouge sous lui (cf. --bs-body-bg plus haut).
   Sur mobile sa surface coïncide avec le fond de page, et il s'y lit comme du contenu qui coule
   dans le fil du formulaire ; sur desktop la page recule d'un cran et le même bloc devient, sans
   s'être redéclaré, la surface claire d'une colonne parallèle (DESIGNAPP). */
.preview-page{
    background-color: var(--sp-color-bg-default);
    margin-bottom: var(--sp-space-4);
}

/* Seules la gouttière et le coin sont conditionnels, et ils suivent la SURFACE, pas la largeur :
   confondu avec la page, le bloc n'a pas de bord dont écarter son contenu — il va pleine largeur.
   Détaché d'elle, il en a un. Même point de rupture que le fond de page, forcément : c'est la
   même décision vue de l'autre côté. */
@media (min-width: 992px){
    .preview-page{
        border-radius: var(--sp-radius-lg);
        padding: var(--sp-space-6);
    }
}

/* Une section masquée ne laisse pas sa gouttière derrière elle. */
.preview-page [hidden]{
    display: none;
}

.preview-organizer{
    display: flex;
    align-items: center;
    gap: var(--sp-space-3);
}

.preview-organizer-logo{
    flex: 0 0 auto;
    border-radius: var(--sp-radius-full);
    object-fit: cover;
}

.preview-organizer-text{
    display: flex;
    flex-direction: column;
}

/* « Organisé par » accompagne, le nom porte : le contraste des deux suffit à le dire. Sur crème,
   le secondaire est brun, jamais le gris calculé pour le blanc (tronc, Color). */
.preview-organizer-label{
    font-size: var(--sp-font-size-meta);
    color: var(--sp-color-text-brown);
}

.preview-organizer-name{
    font-weight: var(--sp-font-weight-title);
    color: var(--sp-color-text-default);
}

/* Filet sur CRÈME, donc chaud : c'est le sol qui décide (DESIGNAPP, « Bordures et séparateurs »).
   Il ne prend pas border.on-white, qui est le filet du blanc. */
.preview-rule{
    margin: var(--sp-space-4) 0;
    border: 0;
    border-top: var(--sp-border-width-default) solid var(--sp-color-border-cream);
    opacity: 1;
}

.preview-section + .preview-section{
    margin-top: var(--sp-space-5);
}

/* DEUX CLASSES, ET C'EST DÉLIBÉRÉ. Ces titres sont des `h3`, et `.photographer-layout h3` /
   `.club-layout h3` (0,1,1) leur impose encore sa marge de 16px dans les espaces pro : une
   classe seule (0,1,0) ne suffit pas à la ramener à space-3. Ne pas « simplifier » ce sélecteur
   en une seule classe. */
.preview-page .preview-section-title{
    font-size: var(--sp-font-size-h3-dense);
    font-weight: var(--sp-font-weight-title);
    color: var(--sp-color-text-default);
    margin-bottom: var(--sp-space-3);
}

.preview-pills{
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-space-2);
}

/* Étiquette de lien : PAS un Chip (blanc, ombré, et qui filtre — fiche chip). Celle-ci ne fait
   rien : elle représente un lien de la page publique. Creux crème sur le panneau crème, aucune
   ombre, aucun état de survol — rien qui invite à la presser (DESIGNAPP). */
.preview-pill{
    display: inline-flex;
    align-items: center;
    gap: var(--sp-space-2);
    padding: var(--sp-space-2) var(--sp-space-3);
    border-radius: var(--sp-radius-md);
    background-color: var(--sp-color-bg-sunken);
    font-size: var(--sp-font-size-label);
    color: var(--sp-color-text-default);
}

/* La description se coupe comme sur la page publique. Le nombre de lignes est ce qui décide, pas
   un nombre de caractères : c'est la hauteur du bloc qu'on borne, et le contrôleur mesure ensuite
   si « Voir plus » a lieu d'être.

   C'est le seul bloc de PROSE CONTINUE de la colonne : d'où size.label (14px) et weight.prose
   (400), un cran sous l'UI qui l'entoure sur les deux axes — elle cesse de se lire comme la
   valeur d'un champ recopiée à côté du formulaire (DESIGNAPP). La couleur, elle, ne suit pas :
   text.default, l'ink chaud. On allège le POIDS, jamais le contraste — le text.muted que la
   petite taille appelle par réflexe est exactement ce que le tronc interdit d'en déduire. */
.preview-description{
    display: -webkit-box;
    -webkit-line-clamp: 5;
    -webkit-box-orient: vertical;
    overflow: hidden;
    margin-bottom: var(--sp-space-3);
    font-size: var(--sp-font-size-label);
    font-weight: var(--sp-font-weight-prose);
    color: var(--sp-color-text-default);
    white-space: pre-line;   /* la description est saisie en lignes : elles comptent */
}

.preview-description.is-expanded{
    display: block;
    overflow: visible;
}

/* « Voir plus » déplie la description, comme sur la page publique (retour client). */
.preview-more{
    display: block;
    width: 100%;
    border: 0;
    text-align: center;
    padding: var(--sp-space-3);
    border-radius: var(--sp-radius-md);
    background-color: var(--sp-color-bg-sunken);
    font-weight: var(--sp-font-weight-title);
    color: var(--sp-color-text-default);
}

/* L'astérisque d'un champ requis : orange (accent.selected), rien d'autre (fiche input). */
.required-mark {
    color: var(--sp-color-accent-selected);
    margin-left: var(--sp-space-1);
}

/* Astuces du jour : navigation compacte du carrousel, dans l'en-tête de section. */
.tips-nav {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-space-1);
}

.tips-nav-btn {
    color: var(--sp-color-text-default);
}

.tips-nav-count {
    font-size: var(--sp-font-size-meta);
    font-weight: var(--sp-font-weight-title);
    color: var(--sp-color-text-muted);
    min-width: 2.5em;
    text-align: center;
}

/* Carte des astuces : aucun fond, aucune ombre, mais un filet chaud — elle se fond dans la page
   (crème), en retrait des cartes blanches du formulaire, tout en restant délimitée. */
/* Gouttière dissociée : 16px en vertical, 24px en horizontal (fiche tips). L'horizontal sert le
   retrait du texte contre le filet, le vertical sert l'empilement — à 24px en haut et en bas, une
   carte qui empile quatre blocs courts (en-tête, visuel, conseil, pastilles) prend une hauteur
   qu'aucun d'eux ne réclame. Ce sont les variables de la Card qu'on déplace, pas un `padding`
   posé par-dessus : le `card-body` lit les siennes. */
.tips-card {
    --bs-card-spacer-y: var(--sp-space-4);
    --bs-card-spacer-x: var(--sp-space-6);
    background-color: transparent;
    box-shadow: none;
    border: var(--bs-border-width) solid var(--sp-color-border-cream);
    border-radius: var(--sp-radius-2xl);
}

/* L'emplacement du visuel : la SEULE surface pleine de la carte (fiche tips). Le sous-titre et le
   texte se lisent à même la carte — un aplat qui courrait sous les trois créerait un second niveau
   de surface là où il n'y a qu'un niveau de lecture. Coin fermé d'un cran sous la carte qui le
   porte (tronc, « ce qui est posé dans une carte a le coin plus fermé qu'elle »). Aucune gouttière
   propre : le visuel, le sous-titre et le texte partagent le bord gauche de la carte. */
.tip-media {
    height: var(--sp-space-16);
    border-radius: var(--sp-radius-md);
    background-color: var(--sp-color-bg-sunken);
    margin-bottom: var(--sp-space-4);
    overflow: hidden;
}
.tip-media img { display: block; width: 100%; height: 100%; object-fit: cover; }

/* Le conseil lui-même, ramassé en une phrase : c'est ce qu'on retient si l'on ne lit rien
   d'autre. Titre d'un bloc DANS une carte, donc size.h4 et graisse de titre — pas le bold, qui
   est celui d'un titre de carte. */
.tip-title {
    font-size: var(--sp-font-size-h4);
    font-weight: var(--sp-font-weight-title);
    color: var(--sp-color-text-default);
    margin-bottom: var(--sp-space-2);
}

/* Ce qui l'explique : on le LIT, donc ni l'ink d'un titre ni le muted d'une méta (tronc,
   « text.advice »). Le muted y tomberait à 3,7:1 sur ce creux, sous l'AA pour du corps. */
.tip-text {
    font-size: var(--sp-font-size-body);
    font-weight: var(--sp-font-weight-body);
    color: var(--sp-color-text-advice);
}

.tips-dots {
    display: flex;
    justify-content: center;
    gap: var(--sp-space-2);
    margin-top: var(--sp-space-4);
}

.tips-dot {
    width: var(--sp-space-2);
    height: var(--sp-space-2);
    border-radius: var(--sp-radius-full);
    background-color: var(--sp-color-border-cream);
}

.tips-dot.is-active {
    background-color: var(--sp-color-text-muted);
}

/* Btn-circle */

/* IconButton DS : cible tactile control.icon-button (44px), disque radius.full */
.btn-circle{
    display: inline-flex;
    justify-content: center;
    align-items: center;
    height: var(--sp-control-icon-button);
    width: var(--sp-control-icon-button);
    /* Un bouton-icône garde son carré/disque — jamais déformé, contenu centré H et V (fiche
       icon-button). La taille est donc fermée des DEUX côtés : `width`/`height` disent la taille,
       `min-*` empêchent qu'un parent la reprenne. `flex: 0 0 auto` ne couvre que la rangée flex ;
       une grille, une cellule ou un conteneur en `stretch` compriment un bouton qui n'a pas de
       plancher, et le disque devient une ellipse — c'est ce qu'on voit sur les chevrons d'un
       carrousel, seuls boutons-icônes que le produit pose au milieu d'un contenu qui bouge. */
    min-width: var(--sp-control-icon-button);
    min-height: var(--sp-control-icon-button);
    flex: 0 0 auto;
    aspect-ratio: 1;
    /* La gouttière s'écrit en PROPRIÉTÉ, pas par la variable Bootstrap : dans l'espace connecté,
       la règle de densité du bouton pose `--bs-btn-padding-x: 16px` sur tout `.btn` non exclu, et
       elle atteignait aussi les disques — 32px de gouttière dans un cercle de 44 ne laissent que
       12px à un glyphe qui en fait 20. Un disque n'a de toute façon aucune gouttière à porter :
       sa taille est fixe et son contenu est centré par le flex. */
    padding: 0;
}

.btn-circle{
    border-radius: var(--sp-radius-full);
}

/* Icône de navigation : icon.size.nav (ICONS.md) */
.icon-nav{
    font-size: 20px;
    line-height: 1;
}

/* Les actions de la barre haute (avatar, menu, panier) : 16px entre elles sur desktop */
.topbar-actions{
    gap: var(--sp-space-4);
}

/* Barre haute front : hauteur mobile layout.topbar.h */
.topbar-front{
    min-height: var(--sp-layout-topbar-h);
    align-items: center;
    /* La barre haute — et la recherche qu'elle porte — flotte au-dessus du contenu
       (fiche search-bar). Sans z-index, elle vient avant le contenu dans le DOM et se
       peignait donc DESSOUS : le dropdown de suggestions passait sous les onglets et les
       cartes. Au-dessus du contenu (z-index max ~20), sous l'offcanvas (1045). */
    position: relative;
    z-index: 1000;
}

/* Profile picture upload */

.profile-picture-upload__preview {
    width: 96px;
    height: 96px;
    min-width: 96px;
    border-radius: 50%;
    background-color: var(--sp-color-border-default);
    background-size: cover;
    background-position: center;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 2rem;
    color: var(--sp-color-text-muted);
}

.profile-picture-upload__preview.has-image > svg {
    display: none;
}

.profile-picture-upload__btn {
    display: flex;
    align-items: center;
    width: 260px;
    height: 48px;
    gap: 8px;
    background-color: var(--sp-color-text-default);
    color: var(--sp-color-bg-surface);
    border: none;
    border-radius: 4px;
    padding: 12px 24px;
    font-size: 1rem;
    font-weight: 500;
    cursor: pointer;
    transition: background-color 0.2s;
}

.profile-picture-upload__btn:hover {
    background-color: var(--sp-color-text-brown);
}

.profile-picture-upload__btn-icon {
    font-size: 1.3rem;
    font-weight: 300;
    line-height: 1;
}

/* La puce de section garde ses cotes sur TOUS les supports : la maquette la dessine sur mobile,
   glyphe compris. Un ancien bloc la resserrait ici (0,4rem de gouttière, 0,9rem de libellé) et
   MASQUAIT son glyphe sous 992px — « Rejoindre » y perdait son appareil photo, « Publier mes
   photos » son plus. Le `!important` du libellé écrasait au passage la taille du composant. */

.modal .btn-close,
.offcanvas .btn-close {
    --bs-btn-close-opacity: 1;
    color: var(--bs-btn-close-color);
    background: var(--light) var(--bs-btn-close-bg) center / 1em auto no-repeat;
    height: 35px !important;
    width: 35px !important;
    background-size: 12px;
}

.modal .btn-close:hover,
.offcanvas .btn-close:hover {
    background: var(--sp-color-border-default) var(--bs-btn-close-bg) center / 1em auto no-repeat;
    background-size: 12px;
    opacity: 1;
}

/* Card */

/* La base .card vit EN HAUT de ce fichier, avant ses variants — voir le commentaire qui l'y
   accompagne. Elle était dupliquée ici, après eux, et les neutralisait. */

/* Gouttières plus serrées, pour les surfaces denses */
.card-spacer-md{
    --bs-card-spacer-y: var(--sp-space-3);
    --bs-card-spacer-x: var(--sp-space-3);
}

.card-spacer-lg{
    --bs-card-spacer-y: var(--sp-space-4);
    --bs-card-spacer-x: var(--sp-space-4);
}

.card-header{
    --bs-card-cap-padding-y: var(--bs-card-spacer-y);
    --bs-card-cap-padding-x: var(--bs-card-spacer-x);
    --bs-card-cap-bg: transparent;
}

/* Onboarding (club et photographe) : wrapper et carte de bienvenue */
.onboarding-container{
    max-width: 760px;
}

.onboarding-card{
    max-width: 480px;
}

/* Pastille d'upload sur l'avatar de profil */
.avatar-upload-badge{
    width: 32px;
    height: 32px;
}

/* Grille de tarification du wizard de dépôt */
/* Ce que le photographe encaissera, DANS sa phrase (DESIGNAPP) : le montant garde la taille de la
   ligne qui le porte. Il était en `size.figure`, et ce rang ne se justifiait plus une fois les
   pastilles de prix posées juste au-dessus, où la décision se prend — cette phrase la confirme.
   Un nombre de 24px au milieu d'une ligne de 15 rompt la ligne et fait crier la confirmation plus
   fort que le contrôle qui la produit. */
.earnings-figure{
    font-size: var(--sp-font-size-body);
    font-weight: var(--sp-font-weight-body);
    color: var(--sp-color-text-default);
    white-space: nowrap;
}

/* Simulation du barème (DESIGNAPP, « La remise activée montre le barème appliqué ») : des lignes
   posées sur une SURFACE, pas un tableau à filets. Quatre paliers ne sont pas des données à
   comparer colonne par colonne, ce sont quatre offres qu'on parcourt. */
.tier-head{
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--sp-space-3);
    margin-bottom: var(--sp-space-3);
    color: var(--sp-color-text-muted);
}

.tier-rows{
    display: flex;
    flex-direction: column;
    gap: var(--sp-space-3);
}

/* Le gris neutre, pas le crème : ces lignes sont dans une carte BLANCHE, où le crème vire au
   beige sale (tronc DESIGN, le raisonnement de sol de bg.control). Coin plus fermé que la carte
   imbriquée qui les porte (xl → md), comme tout ce qui s'emboîte. */
.tier-row{
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-space-3);
    padding: var(--sp-space-4);
    border-radius: var(--sp-radius-md);
    background-color: var(--sp-color-bg-grey);
}

/* L'erreur d'une remise refusée colle à sa ligne (4px) au lieu de flotter à l'écart des lignes. */
.tier-row-error{
    margin-top: calc(4px - var(--sp-space-3));
    text-align: right;
}

.tier-row-error .invalid-feedback{
    margin-top: 0;
}

.tier-row-label{
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: var(--sp-space-2);
}

/* Le seuil et la tranche disent la MÊME borne — l'un pour décider, l'autre pour vérifier : même
   taille et même encre, seule la graisse les départage. Les échelonner ferait croire à une
   hiérarchie qui n'existe pas. */
.tier-row-threshold{
    font-weight: var(--sp-font-weight-title);
}

.tier-row-range{
    font-weight: var(--sp-font-weight-body);
}

.tier-row-figures{
    display: flex;
    align-items: center;
    gap: var(--sp-space-3);
}

/* Le prix ferme la ligne : le seul chiffre que l'acheteur verra, donc la seule graisse forte.
   Sans surface propre — l'encadrer dans la ligne qui le porte déjà poserait un champ là où rien
   ne se saisit. */
.tier-row-price{
    font-weight: var(--sp-font-weight-bold);
    white-space: nowrap;
}

/* La remise, en pilule violette : la forme COMPACTE du bandeau de remise du panier (.cart-deal),
   même objet et même teinte, vue du côté où on la règle (DESIGNAPP). Ce n'est pas un `Badge` :
   le jeu de tons du composant est fermé et n'a pas de violet. Le taux est en graisse de titre,
   le mot suit — on lit le chiffre, on reconnaît le reste. */
.deal-pill{
    display: inline-flex;
    align-items: center;
    gap: var(--sp-space-1);
    padding: var(--sp-space-1) var(--sp-space-3);
    border-radius: var(--sp-radius-full);
    background-color: var(--sp-color-accent-deal);
    color: var(--sp-color-text-inverse);
    font-size: var(--sp-font-size-label);
    font-weight: var(--sp-font-weight-body);
    white-space: nowrap;
}

.deal-pill strong{
    font-weight: var(--sp-font-weight-title);
}

/* Les sorties du parcours de dépôt : ink souligné, jamais l'orange (DESIGNAPP). L'accent est
   réservé au geste qui dépose ; le soulignement fait ici tout le travail que la couleur ne fait
   plus, sans lui un mot ink au pied d'une carte ne se distingue pas du texte qui le précède. */
.flow-link{
    color: var(--sp-color-text-default);
    font-weight: var(--sp-font-weight-title);
    text-decoration: underline;
}

.flow-link:hover,
.flow-link:focus-visible{
    color: var(--sp-color-text-default);
}

/* Progress variant `transfer` (fiche progress) : même barre que la jauge du DS — 8px, rayon
   full, piste et remplissage arrondis — mais son remplissage porte l'ISSUE et non l'orange.
   C'est le seul variant qui quitte l'accent : il ne mesure pas un reste, il rapporte un état,
   et trois transferts empilés dont un a échoué doivent se distinguer d'un coup d'œil. */
.upload-progress{
    height: 8px;
    border-radius: var(--sp-radius-full);
    background-color: var(--sp-color-bg-grey);
}

.upload-progress .progress-bar{
    border-radius: var(--sp-radius-full);
    background-color: var(--sp-color-feedback-info);
    transition: width var(--sp-duration-base) var(--sp-easing-standard);
}

.upload-progress .progress-bar.is-done{ background-color: var(--sp-color-feedback-success-fill); }
.upload-progress .progress-bar.is-failed{ background-color: var(--sp-color-feedback-danger); }

/* Bande d'aperçus de la sélection (fiche dropzone) : cinq vignettes au plus, la sixième
   portant le reste en nombre. Elles se serrent sans se déformer si la carte rétrécit. */
.upload-preview-strip{
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-space-2);
}

.upload-preview{
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 88px;
    height: 88px;
    flex: 0 0 auto;
    border-radius: var(--sp-radius-md);
    overflow: hidden;
    background-color: var(--sp-color-bg-grey);
}

.upload-preview img{
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* Le reste en nombre : un aplat ink, parce qu'il ne montre rien — il compte. */
.upload-preview--more{
    background-color: var(--sp-color-bg-dark);
    color: var(--sp-color-text-inverse);
    font-size: var(--sp-font-size-16);
    font-weight: var(--sp-font-weight-title);
}

/* Carte d'un transfert, dans la colonne gauche sous l'évènement (DESIGNAPP, « La carte d'un
   transfert prend radius.xl et le crème clair ») : posée sur le fond desktop, elle s'en détache
   d'un cran sans passer au blanc, que cet écran ne donne à rien. */
.upload-item{
    background-color: var(--sp-color-bg-default);
    border-radius: var(--sp-radius-xl);
    padding: var(--sp-space-4) var(--sp-space-6) 11px;
    margin-bottom: var(--sp-space-3);
}

/* Le rang semibold, la cible medium à sa suite : c'est une ligne, pas un titre de carte. */
.upload-item-title{
    font-size: var(--sp-font-size-body);
    font-weight: var(--sp-font-weight-title);
    line-height: 18px;
    color: var(--sp-color-text-default);
}

/* En tête de carte : le rang et la cible à gauche, la croix d'abandon à droite. */
.upload-item-head{
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--sp-space-2);
    margin-bottom: var(--sp-space-3);
}

/* Croix d'abandon : IconButton variant ghost (fiche icon-button) — icône seule, sans fond, pour
   une action de liste (« retirer »). La cible 44px vient de .btn-circle ; la couleur est celle du
   ghost (text.default), l'icône la reprend via currentColor. */
.upload-item-abandon{
    color: var(--sp-color-text-default);
}

/* Le pourcentage et le mot d'état encadrent la barre : la couleur ne porte jamais seule
   (fiche progress). Le chiffre à gauche, ce qu'il vaut à droite. */
.upload-item-state{
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--sp-space-3);
    margin-top: var(--sp-space-2);
}

/* Le pourcentage descend de 20 à 16 (maquette) pour la raison qui le fait exister : il
   accompagne une barre qui dit déjà l'essentiel, il n'est pas le titre de la carte. */
.upload-item-pct{
    font-size: var(--sp-font-size-16);
    font-weight: var(--sp-font-weight-bold);
    line-height: 19px;
    color: var(--sp-color-text-meta);
}

.upload-item-status{
    font-size: var(--sp-font-size-meta);
    font-weight: var(--sp-font-weight-bold);
    line-height: 16px;
    letter-spacing: var(--sp-font-tracking-meta);
    color: var(--sp-color-text-meta);
}

.upload-item-meta{
    font-size: var(--sp-font-size-meta);
    line-height: 16px;
    color: var(--sp-color-text-brown);
}

/* Pagination : l'actif reprend l'ink d'action (partout, plus d'override inline) */
.pagination{
    --bs-pagination-active-bg: var(--sp-color-action-primary);
    --bs-pagination-active-border-color: var(--sp-color-action-primary);
}

/* Profil photographe public : avatar héro et vignettes d'activité 80px */
.profile-avatar-xl{
    width: 80px;
    height: 80px;
}

.cart-thumb-lg{
    width: 100px;
    height: 100px;
    object-fit: cover;
    border-radius: var(--sp-radius-sm);
}

/* Panier vide : cercle au trait ink (border.strong) */
.cart-empty-circle{
    width: 80px;
    height: 80px;
    border: 2px solid var(--sp-color-border-strong);
}

/* ------------------------------------------------------------------
   Panneau panier (DESIGNAPP, « Panier »)
   ------------------------------------------------------------------ */

/* Sur mobile le panneau COUVRE l'écran : il en prend le fond (maquette CART, #FAF9F5), pas le
   blanc que l'Offcanvas pose par défaut. C'est ce crème qui fait lire la carte d'évènement
   posée dessus. Sur desktop il se range en colonne par-dessus la page, et garde le blanc. */
@media (max-width: 991.98px) {
    #offcanvasCart {
        --bs-offcanvas-bg: var(--sp-color-bg-default);
    }
}

/* L'en-tête ne porte que le logotype (mobile) et la croix, et AUCUN filet : c'est le titre
   qui suit qui sépare le chrome du contenu (DESIGNAPP). */
.cart-header{
    border-bottom: 0;
    padding-bottom: 0;
}

.cart-header-brand{
    display: inline-flex;
    align-items: center;
}

.cart-body{
    padding: var(--sp-space-4);
}

/* Le titre du panneau et le total en vis-à-vis : le chiffre d'une section se lit sur la ligne
   de son titre, en font.size.figure et family.base (DESIGNAPP). */
.cart-title-row{
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--sp-space-4);
    margin-bottom: var(--sp-space-4);
}

/* Titre de PAGE : il nomme l'écran entier et se pose sur le fond, en font.size.h2 (DESIGNAPP,
   « Le titre d'une page reste sur le fond »). UNE seule règle pour tous les écrans qui le
   portent : c'est une règle du DS, pas un style d'écran — dupliquée par écran, elle dérive. */
.page-title,
.photo-side-title{
    font-size: var(--sp-font-size-h2);
    font-weight: var(--sp-font-weight-title);
    line-height: 34px;
    letter-spacing: var(--sp-font-tracking-tighter);
    margin: 0;
}

/* Titre de page du PARCOURS DE DÉPÔT, en 32/39 (maquette PHOTO_DROP, toutes ses frames).
   L'espace connecté écrit son titre d'un cran au-dessus : il n'a pas de photographie pour
   poser l'écran, et c'est ce titre qui le fait. La cote est relevée écran par écran ; elle ne
   vaut pas pour tout l'espace pro — et elle ne vaut que sur DESKTOP, seul support que la
   maquette dessine pour ce parcours : sur mobile le titre garde le h2 du DS. */
.page-title--drop{
    margin-bottom: var(--sp-space-4);
}

@media (min-width: 992px) {
    .page-title--drop{
        font-size: var(--sp-font-size-32);
        line-height: 39px;
    }
}

/* Là où DEUX titres se font face sur une même ligne — le nom de l'écran et celui de la section
   qu'on y règle —, ils descendent à h2.dense (24px) : à 28px ils se disputent l'entrée de la
   page (DESIGNAPP, « Paramètres du compte »). Seule la taille change, pas la hiérarchie. */
.page-title--dense{
    font-size: var(--sp-font-size-h2-dense);
    line-height: 29px;
}

/* Tunnel de paiement, mobile : le titre de page fait suite à celui du panier, en 20/24 */
@media (max-width: 991.98px) {
    .page-title--tunnel{
        font-size: var(--sp-font-size-h3);
        line-height: 24px;
        letter-spacing: var(--sp-font-tracking-tighter);
    }
}

/* Le titre du PANNEAU et son total se font face en 20/24 semibold (maquette CART) */
.cart-title,
.cart-title-total{
    margin: 0;
    font-family: var(--sp-font-family-base), sans-serif;
    font-size: var(--sp-font-size-h3);
    font-weight: var(--sp-font-weight-title);
    line-height: 24px;
    letter-spacing: var(--sp-font-tracking-tighter);
    color: var(--sp-color-text-default);
}

.cart-title-count{
    font-weight: var(--sp-font-weight-prose);
}

.cart-title-total{
    white-space: nowrap;
}

/* Groupe d'un photographe : carte crème posée sur la surface BLANCHE du panneau. Une carte
   blanche ne s'y détacherait pas, et une ombre n'y a rien à détacher : c'est le crème qui
   fait la surface (DESIGNAPP). */
.cart-group{
    padding: var(--sp-space-4);
    border-radius: var(--sp-radius-2xl);
    background-color: var(--sp-color-bg-cream);
}

.cart-group + .cart-group{
    margin-top: var(--sp-space-4);
}

.cart-group-event{
    display: flex;
    align-items: flex-start;
    gap: 13px;
    margin-bottom: var(--sp-space-3);
}

/* Un évènement de plus du même photographe, dans la même carte (retour client) : il reprend
   l'en-tête du premier, détaché des photos qui précèdent */
.cart-group-event--next{
    margin-top: var(--sp-space-6);
}

/* SportBadge de 41px au rayon de 10 (maquette) */
.cart-group-event > .sport-badge{
    flex: 0 0 41px;
    width: 41px;
    height: 41px;
}

/* Le bloc de texte doit pouvoir rétrécir sous la largeur de son contenu, sans quoi un nom
   d'évènement long pousse le badge hors de la carte. */
.cart-group-event-text{
    min-width: 0;
}

.cart-group-event-title{
    font-size: var(--sp-font-size-16);
    font-weight: var(--sp-font-weight-title);
    line-height: 19px;
    letter-spacing: var(--sp-font-tracking-tight);
}

/* Lieu, date et attribution : 12px ink — sur crème, jamais le gris muted (DESIGNAPP). */
.cart-group-event-meta,
.cart-group-author{
    font-size: var(--sp-font-size-12);
    font-weight: var(--sp-font-weight-body);
    line-height: 15px;
    letter-spacing: var(--sp-font-tracking-tight);
    color: var(--sp-color-text-default);
}

/* L'attribution est une phrase, pas un bloc : l'avatar y prend `xs`, la seule taille qui se
   pose DANS une ligne de texte (fiche avatar). Elle respire plus bas que les autres lignes —
   elle referme l'identité du groupe avant que la remise et les photos ne commencent. */
.cart-group-author{
    display: flex;
    align-items: center;
    gap: var(--sp-space-2);
    margin-bottom: var(--sp-space-3);
}

.cart-group-author-name{
    font-size: var(--sp-font-size-meta);
    font-weight: var(--sp-font-weight-title);
    line-height: 16px;
    letter-spacing: var(--sp-font-tracking-meta);
    color: var(--sp-color-text-default);
    text-decoration: none;
}

/* Bandeau de remise : le seul violet du produit (tronc, « Le violet de la remise »). Aplat
   accent.deal sous du texte blanc, en pilule pleine largeur. Il dit un avantage ACQUIS :
   il ne se clique pas, et le violet ne se pose jamais sur un bouton. */
.cart-deal{
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 5px;
    min-height: 41px;
    margin-bottom: var(--sp-space-4);
    padding: var(--sp-space-2);
    border-radius: var(--sp-radius-lg);
    background-color: var(--sp-color-accent-deal);
    color: var(--sp-color-text-inverse);
    font-size: var(--sp-font-size-12);
    font-weight: var(--sp-font-weight-body);
    letter-spacing: var(--sp-font-tracking-tight);
}

/* Lignes de photos : pas de filet entre elles — les vignettes découpent déjà la liste, et un
   filet de plus dans une carte crème la ferait passer pour un tableau (DESIGNAPP). */
.cart-lines{
    display: flex;
    flex-direction: column;
    gap: var(--sp-space-4);
}

.cart-line{
    display: flex;
    align-items: stretch;
    gap: var(--sp-space-3);
}

/* L'infobulle de licence suit le mot sur sa ligne : posée en frère flex, elle était rejetée
   à l'autre bout de la colonne dès que « Utilisation personnelle » passait à la ligne. */
.cart-line-info{
    margin-left: var(--sp-space-1);
    color: var(--sp-color-text-brown);
    vertical-align: -2px;
}

/* Vignette d'une ligne de panier : 80px, ratio 1:1, radius.xs (maquette CART) */
.cart-line-thumb{
    width: 80px;
    flex-shrink: 0;
    align-self: flex-start;
    aspect-ratio: 1;
    overflow: hidden;
    border-radius: var(--sp-radius-xs);
}

.cart-line-thumb img{
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.cart-line-specs{
    flex: 1 1 auto;
    min-width: 0;
}

.cart-line-label{
    margin-bottom: var(--sp-space-1);
    font-size: var(--sp-font-size-meta);
    font-weight: var(--sp-font-weight-title);
    line-height: 16px;
    letter-spacing: var(--sp-font-tracking-meta);
    color: var(--sp-color-text-meta);
}

.cart-line-value{
    font-size: var(--sp-font-size-body);
    font-weight: var(--sp-font-weight-prose);
    line-height: 18px;
    letter-spacing: var(--sp-font-tracking-tight);
    color: var(--sp-color-text-default);
}

/* Le prix en tête de ligne, le retrait calé au pied : la colonne s'étire sur la hauteur de la
   ligne pour que la corbeille tombe toujours au même endroit, quelle que soit la longueur du
   bloc de specs. */
.cart-line-aside{
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    flex-shrink: 0;
    text-align: right;
}

.cart-line-aside form{
    margin-top: auto;
}

.cart-line-price-was{
    font-size: var(--sp-font-size-12);
    font-weight: var(--sp-font-weight-body);
    line-height: 15px;
    letter-spacing: var(--sp-font-tracking-tight);
    color: var(--sp-color-text-meta);
    text-decoration: line-through;
}

.cart-line-price{
    font-size: var(--sp-font-size-16);
    font-weight: var(--sp-font-weight-bold);
    line-height: 19px;
    letter-spacing: var(--sp-font-tracking-tight);
}

/* IconButton variant ghost — icône seule, sans fond : la fermeture du panneau et le retrait
   d'une ligne. La cible 44px vient de .btn-circle, la couleur est celle du ghost. */
.cart-icon-ghost{
    color: var(--sp-color-text-default);
}

/* L'offre encore à saisir (paliers, autres photos) vit HORS de la carte du groupe : ce qui
   est décidé dedans, ce qui reste à décider dehors (DESIGNAPP). */
.cart-offer{
    margin-top: var(--sp-space-4);
    padding: 0 var(--sp-space-1);
}

/* Après l'offre d'un photographe, la carte du suivant : sans cet écart elle s'y collait —
   `.cart-group + .cart-group` ne joue plus quand l'offre s'intercale (retour client). Plus
   large que l'écart offre / carte : on change de photographe. */
.cart-offer + .cart-group{
    margin-top: var(--sp-space-6);
}

/* ------------------------------------------------------------------
   Résumé de la commande (DESIGNAPP, « Résumé de la commande »)
   Réemploi de la carte crème du panier : deux écrans qui montrent la même commande ne
   s'inventent pas deux surfaces. Seules les lignes changent — ici on COMPTE les photos.
   ------------------------------------------------------------------ */

.order-line{
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--sp-space-4);
}

.order-line-title{
    font-size: var(--sp-font-size-label);
    font-weight: var(--sp-font-weight-title);
    line-height: 17px;
}

/* La bande des vignettes : on reconnaît ses photos d'un coup d'œil, sans dérouler autant de
   lignes identiques qu'il y a de photos (DESIGNAPP). */
.order-thumbs{
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-space-2);
    margin-top: var(--sp-space-2);
}

.order-thumb{
    width: 56px;
    aspect-ratio: 1;
    overflow: hidden;
    border-radius: var(--sp-radius-md);
}

.order-thumb img{
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.order-group + .order-group{
    margin-top: var(--sp-space-4);
}

/* Le total de la commande : « Total » en 600/20, son décompte en 400/12, le montant en
   600/20 sur la même ligne — comme le montant de l'en-tête du panier (maquette CART,
   CHECKOUT). */
.order-total{
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--sp-space-4);
}

.order-total-label{
    display: flex;
    align-items: baseline;
    gap: var(--sp-space-2);
    font-size: var(--sp-font-size-h3);
    font-weight: var(--sp-font-weight-title);
    line-height: 24px;
    letter-spacing: var(--sp-font-tracking-tighter);
}

.order-total-count{
    font-size: var(--sp-font-size-12);
    font-weight: var(--sp-font-weight-prose);
    line-height: 15px;
    letter-spacing: var(--sp-font-tracking-tight);
    color: var(--sp-color-text-brown);
}

.order-total-amount{
    font-family: var(--sp-font-family-base);
    font-size: var(--sp-font-size-20);
    font-weight: var(--sp-font-weight-title);
    line-height: 24px;
    letter-spacing: var(--sp-font-tracking-tighter);
    white-space: nowrap;
}

/* Le second total, celui posé au-dessus du bouton qui paie : même construction, mais sur le
   fond de page et non dans la carte — sa méta reprend donc le gris du blanc. */
.order-total--foot{
    padding-top: var(--sp-space-4);
    border-top: 1px solid var(--sp-color-border-default);
}

.order-total--foot .order-total-count{
    color: var(--sp-color-text-muted);
}

/* ------------------------------------------------------------------
   Paramètres du compte (DESIGNAPP, « Paramètres du compte »)
   ------------------------------------------------------------------ */

/* Une LISTE DE LIENS, pas des onglets : chaque entrée mène à son adresse, qu'on doit pouvoir
   mettre en favori et rouvrir (DESIGNAPP). */
/* Les entrées respirent : ce sont quatre destinations distinctes, pas un bloc plein. L'écart
   compte double depuis que la surface courante est un crème très clair — c'est le blanc entre
   les lignes qui donne à la ligne teintée son contour. */
.settings-nav{
    display: flex;
    flex-direction: column;
    gap: var(--sp-space-3);
}

.settings-nav-item{
    display: flex;
    align-items: center;
    gap: var(--sp-space-3);
    padding: var(--sp-space-3) var(--sp-space-4);
    border-radius: var(--sp-radius-md);
    color: var(--sp-color-text-default);
    text-decoration: none;
}

/* Le survol prend la MÊME surface que l'entrée courante, pas une plus foncée : le crème de la
   page est déjà le plus clair de la palette, et tout ce qui se pose au-dessus rendrait la ligne
   survolée plus présente que celle où l'on est. Le partage se lit ainsi — la teinte dit
   « désignée », le poids de titre dit « courante ». */
.settings-nav-item:hover{
    background-color: var(--sp-color-bg-default);
    color: var(--sp-color-text-default);
}

/* L'entrée courante prend le crème de la page et le poids de titre — pas l'orange : c'est un
   lieu où l'on est, pas une action ni un filtre réglé (DESIGNAPP). Le creux (bg.sunken) est
   juste sur un fond crème ; dans une carte BLANCHE il se détache assez pour devenir un objet,
   et l'entrée réclame alors le clic qu'on vient de faire. La teinte peut être aussi discrète
   parce qu'elle ne porte pas l'état seule : le poids le tient à l'œil, aria-current au lecteur
   d'écran. */
.settings-nav-item.is-current{
    background-color: var(--sp-color-bg-default);
    font-weight: var(--sp-font-weight-title);
}

/* Glyphe à largeur constante : c'est ce qui rend la colonne parcourable d'un regard. */
.settings-nav-glyph{
    flex: 0 0 auto;
    display: inline-flex;
    width: 24px;
    color: var(--sp-color-text-default);
}

/* ------------------------------------------------------------------
   Livraison des photos (DESIGNAPP, « Livraison des photos »)
   ------------------------------------------------------------------ */

/* Mobile : une colonne à space.4, dans l'ordre de la maquette — titre, commande, encart, .zip,
   puis les photos, la consigne d'enregistrement au doigt après la première. Les deux
   conteneurs s'effacent (display: contents) pour que l'ordre se règle d'un seul tenant. */
.delivery{
    display: flex;
    flex-direction: column;
    gap: var(--sp-space-4);
}

.delivery-side,
.delivery-lead,
.delivery-photos{
    display: contents;
}

.delivery-lead > div{ order: 1; }
.delivery-order{ order: 2; }
.delivery-notice-link{ order: 3; }
.delivery-zip{ order: 4; }
.delivery-rule{ order: 5; }
.delivery-item{ order: 8; }
.delivery-item:first-child{ order: 6; }
.delivery-notice-touch{ order: 7; }

.delivery-title{
    font-size: var(--sp-font-size-h3);
    font-weight: var(--sp-font-weight-title);
    line-height: 24px;
    letter-spacing: var(--sp-font-tracking-tighter);
}

.delivery-thanks{
    display: none;
    font-size: var(--sp-font-size-label);
    font-weight: var(--sp-font-weight-body);
    line-height: 17px;
    letter-spacing: var(--sp-font-tracking-tight);
}

.delivery-rule{
    width: 100%;
    margin: 0;
    border: 0;
    border-top: .5px solid var(--sp-color-border-default);
    opacity: 1;
}

/* Encart d'information : glyphe de tête, titre, texte. Creux crème SANS ombre — c'est un
   bloc de contenu, pas une surface interactive (fiche card). */
.notice{
    display: flex;
    align-items: flex-start;
    gap: var(--sp-space-3);
    padding: 14px;
    border-radius: var(--sp-radius-lg);
    background-color: var(--sp-color-bg-sunken);
}

.notice-glyph{
    flex: 0 0 auto;
    display: inline-flex;
    color: var(--sp-color-text-meta);
}

.notice-title{
    margin-bottom: var(--sp-space-1);
    font-size: var(--sp-font-size-body);
    font-weight: var(--sp-font-weight-title);
    line-height: 18px;
    letter-spacing: var(--sp-font-tracking-tight);
}

.notice-text{
    font-size: var(--sp-font-size-meta);
    font-weight: var(--sp-font-weight-body);
    line-height: 16px;
    letter-spacing: var(--sp-font-tracking-meta);
    color: var(--sp-color-text-meta);
}

/* Identité de la commande : la seule surface dark de l'écran, en ligne de 52px */
.delivery-order{
    display: flex;
    align-items: center;
    gap: var(--sp-space-2);
    min-height: 52px;
    padding: var(--sp-space-2);
    border-radius: var(--sp-radius-lg);
    background-color: var(--sp-color-bg-dark);
    color: var(--sp-color-text-inverse);
}

.delivery-order-tile{
    flex: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    border-radius: var(--sp-radius-md);
    background-color: var(--sp-color-accent-soft);
    color: var(--sp-color-accent-selected);
}

/* Le bloc de texte doit pouvoir rétrécir sous la largeur de son contenu, sinon une date longue
   pousse la pastille hors de la carte. */
.delivery-order-text{
    min-width: 0;
}

.delivery-order-title{
    font-size: var(--sp-font-size-h4);
    font-weight: var(--sp-font-weight-title);
    line-height: 19px;
    letter-spacing: var(--sp-font-tracking-tight);
}

/* Sur un fond sombre, le muted ne survit pas : la méta passe en text.inverse et se distingue
   par sa taille, jamais par une teinte plus pâle (DESIGNAPP, « Bloc de statistique »). */
.delivery-order-meta{
    font-size: var(--sp-font-size-meta);
    font-weight: var(--sp-font-weight-body);
    line-height: 16px;
    letter-spacing: var(--sp-font-tracking-meta);
}

/* Actions de téléchargement : pills de 44px, libellé 15/18 semibold, glyphe de 14 */
.delivery-action{
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    width: 100%;
    height: 44px;
    padding-block: 0;
    font-size: var(--sp-font-size-body);
    font-weight: var(--sp-font-weight-title);
    line-height: 18px;
    letter-spacing: var(--sp-font-tracking-tight);
}

/* Le .zip : contour ink, propre à cet écran (DESIGNAPP) — pas le variant outline, orange */
.delivery-zip{
    --bs-btn-color: var(--sp-color-text-default);
    --bs-btn-bg: transparent;
    --bs-btn-border-color: var(--sp-color-text-default);
    --bs-btn-border-width: var(--sp-border-width-strong);
    --bs-btn-hover-color: var(--sp-color-text-inverse);
    --bs-btn-hover-bg: var(--sp-color-text-default);
    --bs-btn-hover-border-color: var(--sp-color-text-default);
    --bs-btn-active-color: var(--sp-color-text-inverse);
    --bs-btn-active-bg: var(--sp-color-text-default);
    --bs-btn-active-border-color: var(--sp-color-text-default);
}

.delivery-item{
    display: flex;
    flex-direction: column;
    gap: var(--sp-space-4);
}

/* La photo livrée : pleine largeur, radius.2xl, jamais déformée. */
.delivery-photo{
    display: block;
    width: 100%;
    height: auto;
    border-radius: var(--sp-radius-2xl);
    box-shadow: 0 -4px 5.1px rgba(0, 0, 0, .12);
}

/* Sur mobile la pilule de retour suit l'en-tête à 1px (maquette, rangée BUTTONS en padding
   1px 16px 0) ; 24px en pied. Desktop inchangé. */
.delivery-page{
    padding-top: 1px;
    padding-bottom: var(--sp-space-6);
}

@media (min-width: 992px) {
    .delivery-page{
        padding-top: var(--sp-space-6);
    }
}

/* Desktop : 1100px, l'identité et les encarts à gauche (354px), les photos en grille à droite */
@media (min-width: 992px) {
    .container.delivery-page{
        max-width: calc(var(--sp-layout-content-profile) + var(--bs-gutter-x));
    }

    .delivery{
        display: grid;
        grid-template-columns: 354px minmax(0, 1fr);
        align-items: start;
        gap: var(--sp-space-6);
    }

    .delivery-side{
        display: flex;
        flex-direction: column;
        gap: var(--sp-space-6);
    }

    .delivery-lead{
        display: flex;
        flex-direction: column;
        gap: var(--sp-space-6);
        padding: var(--sp-space-6);
        border-radius: var(--sp-radius-2xl);
        background-color: var(--sp-color-bg-default);
        box-shadow: var(--sp-shadow-sm);
    }

    .delivery-lead > div,
    .delivery-order,
    .delivery-notice-link,
    .delivery-notice-touch,
    .delivery-zip,
    .delivery-item,
    .delivery-item:first-child{
        order: 0;
    }

    .delivery-lead > div{
        display: flex;
        flex-direction: column;
        gap: 6px;
    }

    .delivery-thanks{
        display: block;
    }

    .delivery-rule{
        display: none;
    }

    .delivery-photos{
        display: grid;
        grid-template-columns: repeat(2, minmax(0, 1fr));
        column-gap: 25px;
        row-gap: 39px;
    }

    .delivery-photo{
        height: 262px;
        object-fit: cover;
    }
}

/* Carte imbriquée (fiche card) : filet, radius.md, AUCUNE ombre et gouttière resserrée —
   posée sur une autre surface, elle n'a plus de fond crème sous elle pour porter une ombre. */
.cart-payment-card{
    border: 1px solid var(--sp-color-border-default);
    border-radius: var(--sp-radius-md);
    box-shadow: none;
    --bs-card-spacer-y: var(--sp-space-3);
    --bs-card-spacer-x: var(--sp-space-3);
}

/* Le détail accompagne, le Total porte. */
.cart-summary-line{
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--sp-space-4);
    font-size: var(--sp-font-size-meta);
    line-height: 16px;
    letter-spacing: var(--sp-font-tracking-meta);
    color: var(--sp-color-text-muted);
}

.cart-total{
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--sp-space-4);
    margin-top: var(--sp-space-3);
    font-size: var(--sp-font-size-label);
    font-weight: var(--sp-font-weight-title);
    line-height: 17px;
    letter-spacing: var(--sp-font-tracking-tight);
}

/* Pied : le filet sépare le récapitulatif de l'action. Les moyens de paiement viennent APRÈS
   le bouton — ce sont une garantie, pas un choix à faire (DESIGNAPP). */
.cart-foot{
    padding: var(--sp-space-4);
    border-top: 1px solid var(--sp-color-border-default);
}

/* Boutons du tunnel (« Paiement », « Continuer ») : 40px, radius.lg, 16px medium, sans glyphe
   (maquettes CART et CHECKOUT) */
.cart-foot > .btn,
.btn-tunnel{
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 40px;
    padding-top: 0;
    padding-bottom: 0;
    border-radius: var(--sp-radius-lg);
    font-size: var(--sp-font-size-16);
    font-weight: var(--sp-font-weight-body);
    letter-spacing: var(--sp-font-tracking-tight);
}

/* « Paiement » du panier un peu plus haut que les autres boutons du tunnel (retour client du 14/10) */
.cart-foot > .btn{
    min-height: 45px;
}

/* Les moyens de paiement : le libellé au-dessus de sa rangée de logos */
.cart-methods{
    display: flex;
    flex-direction: column;
    gap: var(--sp-space-1);
    margin-top: var(--sp-space-4);
}

/* Tuiles relevées sur la capture cible du client (image31, même zoom que l'état d'avant) :
   73 × 50, coin de 6, 12px entre elles, fond #FAF7F6 ; chaque logo à sa taille de la capture */
.cart-method-row{
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
}

.cart-method{
    display: inline-flex;
    flex: none;
    align-items: center;
    justify-content: center;
    width: 73px;
    height: 50px;
    border-radius: 6px;
    overflow: hidden;
    background-color: #FAF7F6;
}

.cart-method img{
    display: block;
}

.cart-methods-label{
    font-size: var(--sp-font-size-meta);
    font-weight: var(--sp-font-weight-body);
    line-height: 16px;
    letter-spacing: var(--sp-font-tracking-meta);
    color: var(--sp-color-text-default);
}

/* Texte sur photo : scrim DS bas-vers-haut (voile léger en haut pour la ligne de retour) */
.card-image-overlay {
    background: linear-gradient(to top, var(--sp-color-overlay-scrim) 0%, rgba(15, 15, 17, .35) 100%);
    border-radius: var(--sp-radius-lg);
}

.thumbnail-wrapper{
    overflow: hidden;
}

.thumbnail-wrapper img {
    transition: .2s ease-in-out;
    object-fit: cover;
    height: 100%;
    width: 100%;
}

@media (min-width: 992px) {
    .card-spacer-lg{
        --bs-card-spacer-y: 24px;
        --bs-card-spacer-x: 24px;
    }
}

/* Carousel */

[data-controller="carousel"] .btn[data-action*="Left"],
[data-controller="carousel"] .btn[data-action*="Right"]{
    --bs-btn-bg: var(--sp-color-bg-surface);
    --bs-btn-border-color: transparent;
    --bs-btn-hover-bg: var(--sp-color-bg-surface);
    --bs-btn-hover-border-color: transparent;
    --bs-btn-active-bg: var(--sp-color-bg-surface);
    --bs-btn-active-border-color: transparent;
    border-radius: 0;
    font-size: 1.1rem;
    --bs-btn-padding-x: .5rem;
    --bs-btn-padding-y: .5rem;
}

[data-controller="carousel"] .btn[data-action*="Left"]{
    left: -10px;
}

[data-controller="carousel"] .btn[data-action*="Right"]{
    right: -10px;
}

/* Check-btn-pill */

.check-btn-pill .btn{
    display: inline-flex;
    align-items: center;
    height: 48px;
    gap: 8px;
    border-radius: 24px;
    padding: 8px 12px 8px 4px;
    border-width: 1px;
}

/* La croix garde sa place : elle se révèle en fondu, la rangée de chips ne saute pas */
.check-btn-pill .btn .check-pill-cross{
    opacity: 0;
    transform: scale(.8);
    transition: opacity var(--sp-duration-base) var(--sp-easing-standard),
                transform var(--sp-duration-base) var(--sp-easing-standard);
}

.check-btn-pill .btn-check:checked + .btn .check-pill-cross {
    opacity: 1;
    transform: scale(1);
}

@media (prefers-reduced-motion: reduce) {
    .check-btn-pill .btn .check-pill-cross{
        transition: none;
        transform: none;
    }
}

/* ------------------------------------------------------------------
   ChoicePill (fiche choice-pill.md)
   ------------------------------------------------------------------ */

/* Une case à cocher en forme de pilule, pas une chip : la chip filtre ce qu'on regarde et
   flotte (blanche, ombrée, radius.md) ; la pilule compose ce qu'on enregistre et reste plate
   au rang d'un champ (filet, radius.full). Le traitement chip des filtres vit plus haut, sur
   `.btn-check + .btn-light`, et n'est pas touché ici. */
.choice-pill-group{
    position: relative;
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-space-3);
}

/* La case reste une vraie case : masquée à l'œil, pas au clavier ni au lecteur d'écran —
   d'où ni `display:none` ni `visibility:hidden`, qui la sortiraient de l'ordre de tabulation.
   Elle s'absolute dans le groupe (`position:relative` ci-dessus) pour que le focus n'envoie
   pas la page en haut. */
.choice-pill-input{
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

.choice-pill{
    display: inline-flex;
    align-items: center;
    gap: var(--sp-space-2);
    min-height: 40px;
    padding: var(--sp-space-2) var(--sp-space-4);
    border: var(--sp-border-width-strong) solid var(--sp-color-border-default);
    border-radius: var(--sp-radius-full);
    background-color: var(--sp-color-bg-surface);
    color: var(--sp-color-text-muted);
    font-size: var(--sp-font-size-label);
    font-weight: var(--sp-font-weight-body);
    cursor: pointer;
    transition: color var(--sp-duration-fast) var(--sp-easing-standard),
                border-color var(--sp-duration-fast) var(--sp-easing-standard);
}

/* Le glyphe de sport se pose nu (sport-badge.md) : toute la zone ne parle que de disciplines,
   il n'y a rien dont l'isoler. Il prend la couleur du libellé, donc l'état. */
.choice-pill-glyph{
    flex: 0 0 auto;
    display: inline-flex;
}

.choice-pill:hover{
    border-color: var(--sp-color-text-brown);
}

/* Retenu = ink, PAS orange. Exception à checkbox.md, actée dans DESIGNAPP (« Là où les états
   cochés s'accumulent ») : trente pilules d'un coup, dont trois retenues, feraient de l'accent
   un semis d'alertes au lieu d'un point de mire. Glyphe, libellé et filet basculent ensemble ;
   le fond ne bouge pas — un aplat sous un libellé se lirait comme un bouton. */
.choice-pill-input:checked + .choice-pill{
    color: var(--sp-color-text-default);
    border-color: var(--sp-color-border-strong);
}

.choice-pill-input:focus-visible + .choice-pill{
    box-shadow: var(--sp-shadow-ring);
}

/* La croix n'existe qu'à l'état retenu : elle dit qu'on peut reprendre son choix. Elle est
   dans le libellé, jamais un bouton à part — un contrôle imbriqué dans un autre n'est
   atteignable ni au clavier ni au lecteur d'écran. C'est le SEUL aplat de la pilule, et le
   seul élément qui s'inverse : la croix y passe en blanc sur l'ink du filet retenu. */
.choice-pill .choice-pill-cross{
    display: none;
}

.choice-pill-input:checked + .choice-pill .choice-pill-cross{
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 18px;
    height: 18px;
    border-radius: var(--sp-radius-full);
    background-color: var(--sp-color-border-strong);
    color: var(--sp-color-text-inverse);
}

/* Cotes de la maquette (Paramètres › Profil, « Chips ») : 38px, coin de 24, filet de 0,75px
   GREY_FADE, libellé 14/18 semibold ; retenue, filet #4D4D4F et libellé #10110F. */
.choice-pill-group{
    gap: var(--sp-space-2);
}

.choice-pill{
    min-height: 38px;
    padding: 8px 12px 8px 8px;
    border: .75px solid #D1D1D1;
    border-radius: 24px;
    font-weight: 600;
    line-height: 18px;
    letter-spacing: -0.03em;
}

.choice-pill-input:checked + .choice-pill{
    color: #10110F;
    border-color: #4D4D4F;
}

.choice-pill-input:checked + .choice-pill .choice-pill-cross{
    width: 16px;
    height: 16px;
    background-color: #10110F;
}

/* Quota atteint : ce qu'on ne peut plus prendre le dit soi-même, plutôt qu'un message après coup. */
.choice-pill-input:disabled + .choice-pill{
    opacity: .45;
    cursor: not-allowed;
}

/* Dropdown */

.dropdown-menu {
    --bs-dropdown-padding-x: 1rem;
    --bs-dropdown-padding-y: 1rem;
    --bs-dropdown-item-padding-x: 1rem;
    --bs-dropdown-item-padding-y: 0.5rem;
    --bs-dropdown-border-color: var(--bs-border-color);
    --bs-dropdown-border-radius: var(--bs-border-radius);
    --bs-dropdown-link-active-bg: var(--bs-dropdown-link-hover-bg);
}

.dropdown-item {
    --bs-dropdown-link-color: var(--bs-secondary-color);
}

.dropdown-item strong{
    color: var(--bs-body-color);
}

.dropdown-item.active, .dropdown-item:active {
    --bs-dropdown-link-active-bg: transparent;
    --bs-dropdown-link-active-color: var(--bs-heading-color);
    font-weight: 800;
}

.dropdown-toggle.no-arrow:after {
    content: normal;
}

/* Modal — la Dialog du DS (designsystem/spicto/app/components/dialog.md) */

.modal {
    /* En-tête et pied suivent le corps : la modale est UNE surface, pas trois bandes */
    --bs-modal-header-bg: var(--sp-color-bg-default);
    --bs-modal-header-border-width: 0;
    --bs-modal-footer-bg: var(--sp-color-bg-default);
    --bs-modal-footer-border-width: 0;
    /* Gouttière space.6 à toutes les tailles : la fiche n'en connaît qu'une, et l'en-tête
       partage forcément celle du corps, sinon le titre ne s'aligne pas sur ce qu'il coiffe. */
    --bs-modal-padding: var(--sp-space-6);
    --bs-modal-header-padding-x: var(--sp-space-6);
    --bs-modal-header-padding-y: var(--sp-space-6);
    --bs-modal-header-padding: var(--sp-space-6) var(--sp-space-6);
    --bs-modal-border-radius: var(--sp-radius-lg);
    /* L'arrondi INTERNE ne se dérive pas tout seul du précédent : Bootstrap le recalcule
       depuis sa propre --bs-border-radius-lg. Sans cette ligne, l'en-tête et le pied gardent
       des coins de 6px dans une surface arrondie à 16px — invisible tant que leur fond est
       le même que celui du corps, visible dès qu'il change. */
    --bs-modal-inner-border-radius: var(--sp-radius-lg);
    --bs-modal-border-width: 0;
}

/* L'ombre se pose sur .modal-content, pas par variable : Bootstrap DÉCLARE
   --bs-modal-box-shadow mais ne la lit nulle part. La renseigner ne fait donc rien. */
.modal-content {
    box-shadow: var(--sp-shadow-pop);
}

/* Le voile de la fiche, pas le noir 50% de Bootstrap : ce qu'on recouvre reste deviné, et
   il reste chaud comme le reste de la marque.

   Il se règle ICI et pas sur .modal : .modal-backdrop est un élément que Bootstrap ajoute
   en fin de <body>, frère de la modale et non son enfant — une variable posée sur .modal ne
   l'atteint jamais, et il redéfinit de toute façon la sienne. L'opacité passe à 1 parce que
   le voile porte déjà la sienne dans son rgba ; laissée à .5, elle la diviserait par deux. */
.modal-backdrop {
    --bs-backdrop-bg: var(--sp-color-overlay-veil);
    --bs-backdrop-opacity: 1;
}

.modal-header {
    background-color: var(--bs-modal-header-bg);
    /* La croix se cale sur la ligne du titre, pas au milieu de la hauteur (fiche dialog) */
    align-items: flex-start;
}

/* Le titre entre dans le rythme du corps : space.4 sous lui, pas la gouttière de la modale
   (fiche dialog). La gouttière borne la SURFACE — ce qui la sépare du dehors ; le titre, lui,
   coiffe ce qui le suit dedans, et à 24px il flotte au-dessus au lieu de l'annoncer.

   Le sélecteur porte sur `.dialog`, la classe du composant, et non sur `.modal` : les modales
   qui ne sont pas des Dialog du DS (visionneuse d'image, remerciement de téléchargement) gardent
   ce qu'elles avaient. Une règle de fiche vaut en revanche pour TOUTES les Dialog. */
.dialog .modal-header {
    padding-bottom: var(--sp-space-4);
}

/* Modale « Prévenez-moi » (Figma 1719:11026) : coins xl, titre 20px serré, corps en 15px
   regular (le nom de l'évènement en gras), action ink de 40px au rayon lg, mention légale
   en 10px medium muted. */
.modal.dialog {
    --bs-modal-border-radius: var(--sp-radius-xl);
    --bs-modal-inner-border-radius: var(--sp-radius-xl);
}

.dialog .modal-title {
    letter-spacing: var(--sp-font-tracking-tighter);
}

.dialog-body strong {
    font-weight: var(--sp-font-weight-700);
}

/* Centré par flex : un <a> (« Retour à la page d'accueil ») ne centre pas son texte dans une
   hauteur fixée comme le fait un <button> — il restait collé en haut (retour client). */
.dialog-cta {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: 40px;
    padding-top: 0;
    padding-bottom: 0;
    border-radius: var(--sp-radius-lg);
    font-size: var(--sp-font-size-body);
    font-weight: var(--sp-font-weight-title);
    letter-spacing: var(--sp-font-tracking-tight);
}

/* Le titre d'une modale est un h3 : c'est le rang du DS pour un titre de surface. Le niveau
   HTML, lui, suit la page ; la classe ne le décide pas. */
.modal-title {
    font-size: var(--sp-font-size-h3);
    font-weight: var(--sp-font-weight-title);
}

.modal-footer {
    justify-content: space-between;
}

/* Largeur plafonnée (fiche dialog) : au-delà, la ligne de texte dépasse les 75 caractères et
   le champ unique se met à flotter au milieu d'un vide. La variable se pose sur .modal, jamais
   sur .modal-content : c'est .modal-dialog qui la lit, et elle ne remonterait pas jusqu'à lui. */
@media (min-width: 768px) {
    .modal.dialog {
        --bs-modal-width: 420px;
    }
}

/* Corps : des blocs séparés de space.4, sans marges du bas héritées de Bootstrap — la
   gouttière appartient au conteneur, pas à chaque paragraphe. */
.dialog-body,
.dialog-form {
    display: flex;
    flex-direction: column;
    gap: var(--sp-space-4);
}

.dialog-body {
    padding-top: 0;   /* l'en-tête porte déjà la gouttière haute */
}

/* Champs d'une Dialog : un groupe serré (maquettes NOTIFICATION et SIGNALER), l'écart du corps
   reste entre les blocs */
.dialog-fields {
    display: flex;
    flex-direction: column;
    gap: var(--sp-space-2);
}

/* Le champ libre garde sa hauteur de départ (attribut `rows`), pas celle d'un champ d'une ligne */
.dialog-fields textarea.form-control {
    height: auto;
}

/* Page de repli d'une Dialog (« Signaler la photo » sans JavaScript) : la même surface, posée
   dans la page */
.dialog-page {
    max-width: 420px;
    margin-inline: auto;
    padding: 18px var(--sp-space-6) var(--sp-space-6);
    border-radius: var(--sp-radius-xl);
    background-color: var(--sp-color-bg-surface);
}

.dialog-page-head {
    display: flex;
    align-items: center;
    padding-bottom: var(--sp-space-4);
}

.dialog-page-head .modal-title {
    margin: 0;
}

/* Rappel de contexte : la ligne canonique d'évènement, seule. Son filet de séparation ne
   sépare rien ici (il n'y a pas de liste), et sa gouttière verticale est celle d'une liste,
   pas d'un premier bloc de modale. */
.dialog-recap .list-item {
    padding-top: 0;
    padding-bottom: 0;
    border-bottom: 0;
}

.dialog-recap .list-item::after {
    content: none;
}

/* Croix : IconButton ghost. Pas de fond au repos, la surface n'apparaît qu'au survol.
   La taille reste celle de .btn-circle (control.icon-button, 44px) : la redéfinir plus
   petite pour « équilibrer » l'en-tête coûterait la cible tactile que la fiche impose.
   Les marges négatives ne la rognent pas, elles la recentrent sur la gouttière — et sur la
   ligne du titre (24px) : sans elles en bas, la croix gonflait l'en-tête et l'écart sous le
   titre passait de space.4 à 28px. */
.dialog-close {
    color: var(--sp-color-text-default);
    background-color: transparent;
    /* `auto` à gauche, et lui seul, pousse la croix au coin : .modal-header de Bootstrap ne
       porte AUCUN justify-content, il compte sur la marge auto de son propre .btn-close.
       Remplacé par l'IconButton du DS, le bouton se collait au titre. */
    margin: -10px calc(-1 * var(--sp-space-2)) -10px auto;
}

.dialog-close:hover {
    background-color: var(--sp-color-bg-cream);
    color: var(--sp-color-text-default);
}

/* Le LIEN À PARTAGER d'une modale `done` (fiche dialog). Ce n'est pas un input habillé : c'est
   une surface qui TIENT LIEU de champ, et qui en prend donc le fond, le filet et le rayon de
   zone — 12px, l'espace connecté (fiche input, « Ce qui tient lieu de champ suit la règle du
   champ »). Blanc sur le crème de la modale : c'est la raison même pour laquelle la Dialog n'est
   pas blanche, un champ blanc sur du blanc n'ayant plus que son filet pour exister. */
.share-link {
    display: flex;
    align-items: center;
    gap: var(--sp-space-2);
    min-height: 44px;   /* hauteur de champ (fiche input) */
    padding-left: var(--sp-space-3);
    padding-right: var(--sp-space-2);
    border: var(--sp-border-width-default) solid var(--sp-color-border-cream);
    border-radius: var(--sp-radius-md);
    background-color: var(--sp-color-bg-surface);
}

/* L'anneau se pose sur la SURFACE, pas sur le champ nu qu'elle contient : c'est elle qui a le
   filet et le rayon, et un anneau dessiné à l'intérieur d'elle se lirait comme un second cadre.
   Le champ garde donc son focus — il ne le perd pas, il le délègue. */
.share-link:focus-within {
    border-color: var(--sp-color-border-focus);
    box-shadow: var(--sp-shadow-ring);
}

.share-link-glyph {
    flex-shrink: 0;
    color: var(--sp-color-text-muted);
}

/* Le lien se lit en entier ; s'il déborde, c'est lui qui se tronque, jamais le bouton de copie
   qui se serre. */
.share-link-input {
    flex: 1;
    min-width: 0;
    padding: 0;
    border: 0;
    background-color: transparent;
    color: var(--sp-color-text-default);
    font-size: var(--sp-font-size-body);
    text-overflow: ellipsis;
}

.share-link-input:focus {
    outline: none;   /* l'anneau est porté par .share-link:focus-within, il n'est pas supprimé */
}

/* IconButton ghost : pas de fond au repos, la surface n'apparaît qu'au survol. Sa largeur est un
   MINIMUM et non une taille fixe — le contrôleur de copie remplace le glyphe par « Copié ! »
   pendant deux secondes, et un disque figé couperait le mot. */
.share-link-copy {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: var(--sp-control-icon-button);
    min-height: var(--sp-control-icon-button);
    padding: 0 var(--sp-space-3);
    border: 0;
    border-radius: var(--sp-radius-full);
    background-color: transparent;
    color: var(--sp-color-text-muted);
    font-size: var(--sp-font-size-meta);
    white-space: nowrap;
}

.share-link-copy:hover {
    background-color: var(--sp-color-bg-cream);
    color: var(--sp-color-text-default);
}

.share-link-copy:focus-visible {
    outline: none;
    box-shadow: var(--sp-shadow-ring);
}

/* La MENTION de Spicto Pro, sous le filet de la carte du prix : elle nomme l'offre là où sa limite
   se rencontre, et reste INERTE tant que l'abonnement n'existe pas (DESIGNAPP). Elle ne porte donc
   ni surface, ni chevron, ni soulignement — rien qui promette une destination. La pastille se cale
   sur la ligne du texte plutôt que sur sa boîte, sinon elle en dépasse. */
.pro-mention {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--sp-space-2);
}

/* Ce que l'offre changerait, à la suite de son nom : en `size.meta`, parce que la ligne porte deux
   rangs — le nom du produit, puis ce qu'il fait — et qu'ils ne peuvent pas peser pareil. La graisse
   ne descend pas pour autant (`weight.body`), et l'encre reste `text.default` : ce qui rétrécit est
   la taille, pas le registre — une promesse qu'on met en gris est une promesse qu'on ne lit pas. */
.pro-mention-claim {
    font-size: var(--sp-font-size-meta);
    font-weight: var(--sp-font-weight-body);
    color: var(--sp-color-text-default);
}

/* Le VERROU de marque « Spicto Pro » (BRAND) : logotype, sceau, rang « PRO ». Trois pièces d'un
   seul nom — elles se serrent d'un cran sous l'espacement des mots pour se lire comme un bloc, et
   la zone de protection du logo ne s'applique pas ici : posée dans une phrase, elle y ferait un
   trou au lieu de protéger quoi que ce soit. */
.pro-lockup {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-space-1);
}

/* Le logotype seul : le signe est déjà là, porté par le sceau. Hauteur de plancher (15px), la
   même que dans les en-têtes — au-dessous, le tracé unique du mot perd ses liaisons. */
.pro-lockup-logotype {
    display: block;
    height: 15px;
    width: auto;
}

/* Le sceau prend `accent.seal` : même valeur que l'orange d'état, autre rôle — c'est de
   l'identité, pas un élément coché (DESIGN). Il n'est pas le logo, donc il peut être orange. */
.pro-lockup-seal {
    display: inline-flex;
    color: var(--sp-color-accent-seal);
}

/* Le rang, en capitales : un morceau de nom d'offre, pas un libellé d'interface — la seule casse
   haute admise ici avec le marqueur « PUBLICITÉ » (DESIGN, « Casse »). Sa pastille est à CONTOUR
   et n'est donc pas un `Badge` : le jeu de tons du composant est fermé et tout en aplat. */
.pro-lockup-tier {
    display: inline-flex;
    align-items: center;
    padding: 0 var(--sp-space-1);
    border: var(--sp-border-width-default) solid var(--sp-color-border-strong);
    border-radius: var(--sp-radius-xs);
    color: var(--sp-color-text-default);
    font-size: var(--sp-font-size-12);
    font-weight: var(--sp-font-weight-body);
    line-height: var(--sp-font-leading-normal);
    text-transform: uppercase;
}

/* Le « S » seul après le nom d'un abonné : il suit la taille du nom, d'un titre à une ligne de liste. */
.pro-seal {
    display: inline-block;
    margin-left: 0.25em;
    color: var(--sp-color-accent-seal);
    line-height: 1;
    vertical-align: -0.08em;
}

.pro-seal svg {
    display: block;
    width: 0.8em;
    height: 0.8em;
    min-width: 12px;
    min-height: 12px;
}

/* L'EFFET d'une réponse, montré à sa place (fiche dialog, variant `ask`) : la ligne concernée
   telle qu'elle paraîtra, posée sur le crème creusé pour se distinguer de la modale sans devenir
   une carte. Rien ne s'y clique — c'est une démonstration, pas un contenu. */
.dialog-preview {
    padding: var(--sp-space-3);
    border-radius: var(--sp-radius-md);
    background-color: var(--sp-color-bg-sunken);
}

/* Mention légale : 10/12 medium, -0.03em (fiche dialog — la seule mention
   qui descende sous le plus petit pas de l'échelle). */
.dialog-note {
    font-size: 10px;
    font-weight: var(--sp-font-weight-body);
    line-height: 12px;
    letter-spacing: var(--sp-font-tracking-tighter);
    color: var(--sp-color-text-muted);
}

/* L'abonnement déjà pris : un fait acquis, pas une alerte — d'où feedback.success et
   aucune surface. Le variant qui conviendrait au Message n'existe pas (sa liste est
   fermée), et en inventer un pour une phrase serait ajouter au DS ce qu'il refuse. */
.dialog-confirm {
    color: var(--sp-color-feedback-success);
    font-weight: var(--sp-font-weight-title);
}

/* Remerciement après un téléchargement offert (fiche dialog, maquette PAGE_DOWNLOAD) : une
   `done` de 341px qui ne passe pas en plein écran — on la quitte en touchant le voile. */
.modal.dialog--thanks {
    --bs-modal-width: 341px;
    --bs-modal-bg: var(--sp-color-bg-default);
    --bs-modal-border-width: 0;
}

.dialog--thanks .modal-dialog {
    max-width: var(--bs-modal-width);
    margin-inline: auto;
}

.dialog--thanks .modal-content {
    gap: var(--sp-space-4);
    padding: var(--sp-space-4);
}

.thanks-photo {
    position: relative;
    display: flex;
    align-items: flex-end;
    justify-content: center;
    aspect-ratio: 309 / 358;
    padding: var(--sp-space-4) var(--sp-space-3) var(--sp-space-6);
    overflow: hidden;
    border-radius: var(--sp-radius-lg);
    box-shadow: var(--sp-shadow-photo);
}

.thanks-photo > img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.thanks-photo::after {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(180deg, transparent 58.38%, rgba(0, 0, 0, 0.5) 100%);
    pointer-events: none;
}

/* Pastille du photographe : le verre clair des superpositions sur photo, en pilule de 52px */
.badge.thanks-author {
    z-index: 1;
    gap: 7px;
    max-width: 100%;
    height: 52px;
    padding: 6px var(--sp-space-5) 6px 7px;
    border-radius: var(--sp-radius-full);
    text-align: left;
    text-decoration: none;
}

.thanks-author-text {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.thanks-author-name {
    overflow: hidden;
    font-size: var(--sp-font-size-h4);
    font-weight: var(--sp-font-weight-title);
    line-height: 19px;
    letter-spacing: var(--sp-font-tracking-tight);
    text-overflow: ellipsis;
}

.thanks-author-meta {
    font-size: var(--sp-font-size-meta);
    font-weight: var(--sp-font-weight-body);
    line-height: 16px;
    letter-spacing: var(--sp-font-tracking-meta);
}

.thanks-lead {
    margin-top: calc(-1 * var(--sp-space-2));
    font-size: var(--sp-font-size-meta);
    font-weight: var(--sp-font-weight-body);
    line-height: 16px;
    letter-spacing: var(--sp-font-tracking-meta);
    color: var(--sp-color-text-default);
}

/* Le filet au-dessus des actions : un demi-pixel #DCDAD1 (maquette PAGE_DOWNLOAD, DIVIDER) */
.thanks-actions {
    display: flex;
    flex-direction: column;
    gap: var(--sp-space-3);
    padding-top: var(--sp-space-4);
    border-top: .5px solid #DCDAD1;
}

.thanks-follow,
.thanks-credit {
    display: flex;
    align-items: center;
    height: 44px;
    border-radius: var(--sp-radius-lg);
    font-size: var(--sp-font-size-meta);
    line-height: 16px;
    letter-spacing: var(--sp-font-tracking-meta);
}

.thanks-follow {
    justify-content: center;
    gap: var(--sp-space-2);
    padding: 0 var(--sp-space-2);
    font-weight: var(--sp-font-weight-title);
}

.thanks-credit {
    gap: var(--sp-space-1);
    padding: 0 var(--sp-space-2) 0 var(--sp-space-3);
    border: 1px solid var(--sp-color-border-control-strong);
    font-weight: var(--sp-font-weight-body);
    color: var(--sp-color-text-meta);
}

/* « Crédit : » ne se coupe jamais : c'est le texte du crédit qui cède (points de suspension) —
   en flex, le libellé rétrécissait et passait à la ligne (retour client, octobre 2026). */
.thanks-credit-label {
    flex: none;
    white-space: nowrap;
}

.thanks-credit-text {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.thanks-credit-copy {
    flex: none;
    display: inline-flex;
    align-items: center;
    min-height: 28px;
    padding: 0 var(--sp-space-1);
    border: 0;
    background: none;
    font: inherit;
    color: inherit;
}

/* Nav-pills */

/* Tabs DS : l'actif est une pill crème à libellé ink, l'inactif est estompé
   (cf. designsystem/spicto/app/components/tabs.md) */
.nav-pills {
    --bs-nav-pills-border-radius: var(--sp-radius-md);
    --bs-nav-pills-link-active-color: var(--sp-color-text-default);
    --bs-nav-pills-link-active-bg: var(--sp-color-bg-sunken);
    --bs-nav-pills-border-width: 0;
    --bs-nav-pills-border-color: transparent;
    --bs-nav-pills-link-active-border-color: transparent;
    --bs-nav-link-color: var(--sp-color-text-muted);
    --bs-nav-link-hover-color: var(--sp-color-text-default);
}

.nav-pills .nav-link{
    border: var(--bs-nav-pills-border-width) solid var(--bs-nav-pills-border-color);
}

.nav-pills .nav-link.active, .nav-pills .show>.nav-link,
.nav-pills .nav-link:hover,
.nav-pills .nav-link:hover:focus{
    color: var(--bs-nav-pills-link-active-color);
    border-color: var(--bs-nav-pills-link-active-border-color);
}

/* Nav-underline */

.nav-underline .nav-link {
    --bs-nav-link-color: var(--sp-color-text-muted);
    --bs-nav-link-hover-color: var(--sp-color-text-default);
    --bs-nav-link-padding-y: 8px;
    --bs-nav-link-padding-x: 8px;
    --bs-nav-link-font-weight: 600;
    padding: var(--bs-nav-link-padding-y) var(--bs-nav-link-padding-x) 8px var(--bs-nav-link-padding-x);
}

.nav-underline .nav-link.active,
.nav-underline .show>.nav-link {
    font-weight: 600;
    border-width: 2px;
}

.nav-underline .nav-link:focus, .nav-underline .nav-link:hover {
    border-width: 2px;
}

@media (min-width: 992px) {

    .nav-underline .nav-link {
        padding: var(--bs-nav-link-padding-y) var(--bs-nav-link-padding-x) 16px var(--bs-nav-link-padding-x);
    }

}

/* Mobile tab bar - full width */

@media (max-width: 991.98px) {

    /* Filet bas sur la largeur du composant, jamais bord à bord (fiche tabs) */
    .tab-bar-nav {
        width: 100%;
    }

}

/* La fiche tabs ne prescrit pas de typographie : les onglets héritent du corps.
   Ne rien imposer ici tant que le DS ne le dit pas. */

/* Onglet d'une fonctionnalité à venir : lisible mais clairement inerte */
.tab-bar-nav .nav-link.disabled {
    opacity: .4;
    pointer-events: none;
}

/* Filet bas des onglets sous le groupe (fiche tabs), espace tabs.separator.gap
   de part et d'autre du filet ; le bloc tab-bar et la recherche mobile respirent
   de layout.section.gap */
.tab-bar-nav {
    border-bottom: 1px solid var(--sp-color-border-default);
    padding-bottom: var(--sp-space-3);
    margin-bottom: var(--sp-space-3);
}

.tab-bar-block {
    margin-bottom: var(--sp-layout-section-gap);
}

.tab-bar-search {
    margin-bottom: var(--sp-layout-section-gap);
}

/* Groupe d'onglets (fiche tabs, « Groupe ») : quatre parts égales, chaque onglet centré dans
   la sienne, actif ou non — un onglet ne bouge pas quand on en sélectionne un autre. Seule la
   pilule active porte ses 18px de côté : un onglet inactif se mesure à son libellé, sans quoi
   les compteurs font déborder le groupe. */
.tab-bar-block .tab-bar-nav {
    gap: 0;
}

.tab-bar-block .tab-bar-nav .nav-item {
    display: flex;
    flex: 1 1 0;
    align-items: flex-start;
    justify-content: center;
    min-height: 32px;   /* maquette : la pilule de 31px sur 1px de réserve */
}

.tab-bar-block .tab-bar-nav .nav-link:not(.active) {
    padding-left: 0;
    padding-right: 0;
}

/* Desktop : onglets à gauche, chips de filtre à droite, sur une seule ligne
   (DESIGNAPP, « Barre d'onglets »). Le filet ancre alors la barre entière et non le
   seul groupe d'onglets — il passe donc du <ul> au bloc. Placé après .tab-bar-nav :
   même spécificité, c'est l'ordre qui tranche. */
@media (min-width: 992px) {
    .tab-bar-block {
        display: flex;
        align-items: center;
        gap: var(--sp-space-3);
        border-bottom: var(--sp-border-width-hairline) solid var(--sp-color-border-default);
        /* 2px de plus que les 20 de la barre haute : la rangée à 22px du bandeau (maquette) */
        padding: 2px var(--sp-space-4) var(--sp-space-3);
    }

    .tab-bar-nav {
        --bs-nav-pills-link-active-bg: var(--sp-color-bg-sunken-strong);
        border-bottom: 0;
        padding-bottom: 0;
        margin-bottom: 0;
    }

    /* Le groupe reprend la mesure de la barre mobile (fiche tabs, « Groupe ») */
    .tab-bar-block .tab-bar-nav {
        flex: 0 0 375px;
        min-height: 37px;
    }

    .tab-bar-block .tab-bar-nav .nav-item {
        align-items: center;
    }

    /* Les chips se rangent à droite, sur la hauteur de la rangée. Sur desktop l'overflow est
       visible : l'ombre n'a plus besoin de réserve. */
    .tab-bar-block .filter-chips {
        align-items: center;
        min-height: 37px;
        margin-left: auto;
        padding-block: 0;
    }
}

/* Off-canvas */

.offcanvas {
    --bs-offcanvas-width: 100vw;
}

/* Menu (maquette « Login & menu mobile », retour client) : fond crème de page, une carte crème
   plus soutenue pour l'espace du connecté — son nom, sa sortie, ses rubriques, publier —, puis
   les rubriques du site en listes nues : un titre estompé en méta, des entrées ink. Le même
   panneau sur tous les supports ; il prend toute la hauteur de la fenêtre, y compris sur un
   iPhone dont les barres se replient (dvh). */
.mobile-menu{
    --bs-offcanvas-bg: var(--sp-color-bg-default);
    height: 100dvh;
}

/* Maquette « Login & menu mobile » (Figma 1806:11059) : en-tête de 56px sur gouttière 16,
   logotype 89×17, croix de 14 ; le corps enchaîne ses blocs à 16px. */
.mobile-menu .offcanvas-header{
    justify-content: space-between;
    min-height: var(--sp-layout-topbar-h);
    padding: var(--sp-space-1) var(--sp-space-4);
    /* Pas de filet sous le logotype : la maquette n'en met pas, et celui que l'Offcanvas pose
       par défaut est un gris FROID posé sur le crème de la feuille. Le menu sépare déjà ses
       blocs par leurs propres filets, chauds ceux-là. */
    border-bottom: 0;
}

.mobile-menu .offcanvas-header .brand{
    width: 89px;
    height: 17px;
}

.mobile-menu .offcanvas-body{
    display: flex;
    flex-direction: column;
    gap: var(--sp-space-4);
    padding: 0 var(--sp-space-4) var(--sp-space-4);
}

/* La carte de l'espace : creux crème (bg.sunken), rayon xl, gouttière 16 (Figma « AVANTAGES ») */
.mobile-menu-space{
    display: flex;
    flex-direction: column;
    padding: var(--sp-space-4);
    border-radius: var(--sp-radius-xl);
    background-color: var(--sp-color-bg-sunken);
}

.mobile-menu-user{
    display: flex;
    align-items: center;
    gap: 10px;
    padding-bottom: 14px;
    margin-bottom: 5px;
    border-bottom: var(--sp-border-width-hairline) solid var(--sp-color-border-cream);
}

.mobile-menu-user-link{
    display: flex;
    align-items: center;
    gap: 10px;
    min-width: 0;
    flex: 1;
    color: var(--sp-color-text-default);
    text-decoration: none;
}

/* Le nom : 20px semibold serré (Figma) */
.mobile-menu-user-name{
    font-size: var(--sp-font-size-h3);
    font-weight: var(--sp-font-weight-title);
    letter-spacing: var(--sp-font-tracking-tighter);
}

.mobile-menu-logout{
    color: var(--sp-color-text-default);
}

/* Les entrées de l'espace : 15px semibold, 12px de haut et de bas, 8px de côté (Figma « ITEM »),
   la dernière garde 8px de plus avant le bouton */
.mobile-menu-space-links{
    margin: 0 0 var(--sp-space-2);
}

.mobile-menu-space-links a{
    display: flex;
    align-items: center;
    padding: var(--sp-space-3) var(--sp-space-2);
    font-size: var(--sp-font-size-body);
    font-weight: var(--sp-font-weight-title);
    letter-spacing: var(--sp-font-tracking-tight);
    color: var(--sp-color-text-default);
    text-decoration: none;
}

/* Les deux boutons de l'espace : 36px, rayon md, 15px medium (Figma) */
.mobile-menu-space .btn{
    height: 36px;
    padding: var(--sp-space-1) var(--sp-space-2);
    border-radius: var(--sp-radius-md);
    font-size: var(--sp-font-size-body);
    font-weight: var(--sp-font-weight-body);
}

.mobile-menu-space .btn-marketing{
    margin-bottom: var(--sp-space-4);
}

/* .btn-light fige l'axe de la police à wght 400, qui l'emporte sur font-weight : « Créer un
   évènement », « Passer à » et le rang PRO rendaient du 400 au lieu du medium de la maquette
   (MENU) — l'axe est rendu à font-weight. */
.mobile-menu-space .btn-light{
    --bs-btn-bg: var(--sp-color-bg-default);
    --bs-btn-border-color: var(--sp-color-bg-default);
    --bs-btn-hover-bg: var(--sp-color-bg-surface);
    --bs-btn-hover-border-color: var(--sp-color-bg-surface);
    --bs-btn-color: var(--sp-color-text-default);
    font-variation-settings: normal;
}

/* Les rubriques : titre en légende 13px medium (text.caption), entrées 15px medium sur 11px
   de haut et de bas ; un filet fin borde chaque rubrique, à 10px de part et d'autre (Figma) */
.mobile-menu-section{
    margin: 0;
    padding-bottom: 10px;
    border-bottom: var(--sp-border-width-hairline) solid var(--sp-color-border-default);
}

.mobile-menu-section + .mobile-menu-section{
    padding-top: 10px;
}

.mobile-menu-section:last-child{
    border-bottom: 0;
    padding-bottom: 0;
}

.mobile-menu-section a{
    display: flex;
    align-items: center;
    padding: 11px var(--sp-space-2);
    font-size: var(--sp-font-size-body);
    font-weight: var(--sp-font-weight-body);
    letter-spacing: var(--sp-font-tracking-tight);
    color: var(--sp-color-text-default);
    text-decoration: none;
}

.mobile-menu-heading{
    padding: 5px var(--sp-space-2) 9px;
    font-size: var(--sp-font-size-meta);
    font-weight: var(--sp-font-weight-body);
    letter-spacing: var(--sp-font-tracking-meta);
    color: var(--sp-color-text-caption);
}

/* Le corps enchaîne ses blocs : les rubriques forment UN bloc, sans marge entre elles */
.mobile-menu .offcanvas-body > .mobile-menu-section + .mobile-menu-section{
    margin-top: calc(-1 * var(--sp-space-4));
}

/* Le pied : bouton orange de 52px, rayon xl, 15px semibold (Figma « Primary Button ») */
.mobile-menu-foot{
    padding: var(--sp-space-4);
    background-color: var(--sp-color-bg-default);
}

.mobile-menu-foot .btn{
    height: 52px;
    border-radius: var(--sp-radius-xl);
    font-size: var(--sp-font-size-body);
    font-weight: var(--sp-font-weight-title);
}

/* Sous 992px le panneau couvre toute la fenêtre : le voile n'a rien à voiler. Il restait sous
   les barres d'un iPhone, que Safari teinte alors en sombre — les « bandes noires » en haut et
   en bas de l'écran (retour client). Même chose pour une Dialog en plein écran sous 768px. */
@media (max-width: 991.98px) {
    body:has(.mobile-menu.show) > .offcanvas-backdrop{
        --bs-backdrop-opacity: 0;
    }
}

@media (max-width: 767.98px) {
    body:has(.modal.show .modal-fullscreen-md-down) > .modal-backdrop{
        --bs-backdrop-opacity: 0;
    }

    .modal-fullscreen-md-down .modal-content{
        min-height: 100dvh;
    }
}

/* Tooltip (retour client) : une bulle blanche portée par une ombre, large de la page à 90 %
   au plus — 200px de Bootstrap coupaient l'explication en cinq lignes. */
.tooltip{
    --bs-tooltip-max-width: min(90vw, 360px);
    --bs-tooltip-bg: var(--sp-color-bg-surface);
    --bs-tooltip-color: var(--sp-color-text-default);
    --bs-tooltip-opacity: 1;
    --bs-tooltip-border-radius: var(--sp-radius-lg);
    --bs-tooltip-padding-x: var(--sp-space-4);
    --bs-tooltip-padding-y: var(--sp-space-3);
    --bs-tooltip-font-size: var(--sp-font-size-label);
    filter: drop-shadow(0 4px 12px rgba(0, 0, 0, .18));
}

/* Sur desktop, un panneau latéral est une COLONNE, et une colonne a une largeur — pas un
   pourcentage d'écran. En vw, le panier et le menu grandissaient jusqu'à 1 039px (65vw à 1599)
   avant de retomber d'un coup à 480px au palier suivant : deux tiers de l'écran pour un panier,
   puis un tiers, sans que rien n'ait changé sauf la fenêtre. 480px est précisément ce que
   l'ancien palier haut donnait à 1600 ; c'est aussi la famille des autres colonnes du produit
   (420 pour la vue photo, 454 pour le dépôt). Sous 992px, le panneau couvre l'écran. */
@media (min-width: 992px) {
    .offcanvas {
        --bs-offcanvas-width: 480px;
    }
}

.offcanvas-header {
    border-bottom: 1px solid var(--light);
    gap: 1rem;
}

.offcanvas-header .btn-close {
    padding: 0;
}

.offcanvas-footer {
    display: flex;
    align-items: center;
    padding: var(--bs-offcanvas-padding-y) var(--bs-offcanvas-padding-x);
}

/* Placeholder */

.placeholder{
    background-color: var(--bs-secondary);
    opacity: .4;
    border-radius: var(--bs-border-radius);
}

/* Progress */

.progress {
    --bs-progress-height: 8px;
}

/* --- CookieBadge --- */

/* Le consentement se demande en bas de fenêtre, sans voile ni blocage : il n'interrompt rien,
   il ouvre un choix. Surface blanche, filet fin, ombre douce — le chrome reste discret. */
.cookie-badge {
    position: fixed;
    left: var(--sp-space-4);
    right: var(--sp-space-4);
    bottom: var(--sp-space-4);
    /* sous l'offcanvas panier (1045) et les panneaux de filtres : il ne recouvre rien */
    z-index: 1030;
    display: flex;
    flex-direction: column;
    gap: var(--sp-space-3);
    max-width: 420px;
    padding: var(--sp-space-4);
    background-color: var(--sp-color-bg-surface);
    border: 1px solid var(--sp-color-border-on-white);
    border-radius: var(--sp-radius-lg);
    box-shadow: var(--sp-shadow-pop);
}

.cookie-badge-text {
    margin: 0;
    font-size: var(--sp-font-size-meta);
    color: var(--sp-color-text-muted);
}

.cookie-badge-text a {
    color: var(--sp-color-text-link);
}

.cookie-badge-actions {
    display: flex;
    justify-content: flex-end;
    gap: var(--sp-space-2);
}

/* TOPBAR */

/* Photographer Topbar - Club Topbar */

.photographer-layout #top-bar,
.club-layout #top-bar{
    min-height: 56px;
    display: flex;
    align-items: center;
    margin-bottom: 24px;
}

@media (min-width: 992px) {
    .photographer-layout #top-bar,
    .club-layout #top-bar{
        border-bottom: 1px solid var(--sp-color-border-default);
        margin-bottom: 48px;
    }
}

/* Space Switcher (Dior-style toggle) */

.space-switcher {
    display: none;
    background-color: var(--sp-color-border-default);
    border-radius: var(--sp-radius-full);
    padding: 3px;
    gap: 0;
}

@media (min-width: 992px) {
    .space-switcher {
        display: flex;
    }
}

.space-switcher-option {
    padding: 6px 20px;
    border-radius: var(--sp-radius-full);
    font-size: 0.8125rem;
    font-weight: 500;
    text-decoration: none;
    color: var(--sp-color-text-muted);
    white-space: nowrap;
    transition: all 0.2s ease;
}

.space-switcher-option:hover {
    color: var(--sp-color-text-default);
}

.space-switcher-option.active {
    background-color: var(--sp-color-bg-surface);
    color: var(--sp-color-text-default);
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}

/* SPECIFIC CONTENT */

/* Event preview (form) */

.event-preview-card {
    --bs-heading-color: var(--sp-color-bg-surface);
    --bs-body-color: var(--sp-color-bg-surface);
    --bs-card-color: var(--sp-color-bg-surface);
    min-height: 240px;
    background-size: cover;
    background-position: center;
    transition: .3s ease-in-out;
}

.event-preview-card .card-image-overlay {
    color: var(--sp-color-bg-surface);
}

.event-preview-card .event-date {
    font-weight: 400;
    font-size: 1rem;
}

.event-preview-card h1 {
    color: var(--sp-color-bg-surface);
    margin-bottom: 1rem;
    font-size: 1.5rem;
}

.event-preview-card a,
.event-preview-card span {
    color: var(--sp-color-bg-surface);
}

@media (min-width: 992px) {
    .event-preview-card .event-date {
        font-size: 1.2rem;
        letter-spacing: 1px;
    }

    .event-preview-card h1 {
        font-size: 2rem;
    }
}

/* La mention à recopier : une surface imbriquée dans sa carte, donc un filet et pas d'ombre,
   au cran de rayon de l'emboîtement (fiche card, « Une carte imbriquée »). Le texte est le
   sujet du bloc : on le donne à lire tel qu'il sera copié. */
.club-mention{
    padding: var(--sp-space-3);
    border: 1px solid var(--sp-color-border-default);
    border-radius: var(--sp-radius-md);
}

/* Login */

/* Le sélecteur Photographe / Club (Figma 1806:10952) : une pilule blanche de 52px filetée
   border.cream ; l'onglet retenu est une pilule ink de la même hauteur, portée par une ombre
   courte ; l'autre se lit en brun, 14px medium. */
.login-toggle .toggle-group {
    display: flex;
    height: 52px;
    background: var(--sp-color-bg-surface);
    border: 1px solid var(--sp-color-border-cream);
    border-radius: var(--sp-radius-full);
}

.login-toggle .toggle-btn {
    flex: 1;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: var(--sp-space-3) var(--sp-space-6);
    border-radius: var(--sp-radius-full);
    border: none;
    background: transparent;
    color: var(--sp-color-text-brown);
    font-size: var(--sp-font-size-label);
    font-weight: var(--sp-font-weight-body);
    line-height: 22px;
    cursor: pointer;
    transition: 0.25s;
}

.login-toggle .toggle-btn.active {
    flex: 0 0 auto;
    min-width: 169px;
    margin: -1px;
    height: 52px;
    background: var(--sp-color-action-primary);
    color: var(--sp-color-action-primary-text);
    font-size: var(--sp-font-size-body);
    font-weight: var(--sp-font-weight-title);
    letter-spacing: var(--sp-font-tracking-tight);
    box-shadow: 0 4px 2px rgba(0, 0, 0, .07);
}

/* UTILITIES */

/* height */

@media (min-width: 992px) {
    .vh-xl-100 {
        height: 100vh !important;
    }
}

/* p */

.p-4{
    padding: 24px!important;
}

/* g */

.g-3 {
    --bs-gutter-x: 8px;
    --bs-gutter-y: 8px;
}

@media (min-width: 992px) {
    .g-3 {
        --bs-gutter-x: 16px;
        --bs-gutter-y: 16px;
    }
}

/* margin-bottom */

.mb-16px{
    margin-bottom: 16px;
}

/* bg-wallpaper */

.bg-mobile-wallpaper{
    background-image: var(--bg-wallpaper);
    background-size: cover;
    background-repeat: no-repeat;
    background-attachment: fixed;
}

.bg-triathlon{
    --bg-wallpaper: url("../images/login-wallpaper-DpbYD6r.jpg");
}

.bg-athletics{
    --bg-wallpaper: url("../images/athletics-wallpaper-6LUdrYL.jpg");
}

.bg-team{
    --bg-wallpaper: url("../images/team-wallpaper-pEWZuRs.jpg");
}

.bg-athletics-track{
    --bg-wallpaper: url("../images/athletics-track-wallpaper-FKv3zDs.jpg");
}

.bg-volley{
    --bg-wallpaper: url("../images/volley-wallpaper--tPDHf7.jpg");
}

@media (min-width: 576px) {
    .bg-wallpaper{
        background-image: var(--bg-wallpaper);
        background-size: cover;
        background-repeat: no-repeat;
        background-attachment: fixed;
    }
}

/* Ce qui autorise une troncature : un enfant de flex vaut `min-width: auto`, donc il refuse de
   descendre sous la largeur de son contenu — son texte ne se coupe jamais et il pousse ses voisins
   hors du cadre. Bootstrap ne génère pas cette classe alors que les gabarits l'emploient partout
   où un texte doit céder à côté d'un bouton-icône (fiche icon-button) : sans elle, tous les
   `line-clamp` et `text-truncate` posés dans une rangée flex sont inertes. */
.min-w-0{
    min-width: 0;
}

/* Line-clamp */

.line-clamp{
    display: -webkit-box;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.line-clamp-1{
    -webkit-line-clamp: 1;
}

/* fixed */

@media (min-width: 992px) {
    .position-xl-fixed {
        position: fixed !important;
    }
}

/* Google Auth */

.gsi-material-button {
    -moz-user-select: none;
    -webkit-user-select: none;
    -ms-user-select: none;
    -webkit-appearance: none;
    background-color: WHITE;
    background-image: none;
    border: 1px solid #747775;
    -webkit-border-radius: var(--bs-border-radius);
    border-radius: var(--bs-border-radius);
    box-sizing: border-box;
    color: #1f1f1f;
    cursor: pointer;
    font-family: 'Roboto', arial, sans-serif;
    font-size: 16px;
    height: 46px;
    letter-spacing: 0.25px;
    outline: none;
    overflow: hidden;
    padding: 0 12px;
    position: relative;
    text-align: center;
    -webkit-transition: background-color .218s, border-color .218s, box-shadow .218s;
    transition: background-color .218s, border-color .218s, box-shadow .218s;
    vertical-align: middle;
    white-space: nowrap;
    width: 100%;
    min-width: min-content;
}

.gsi-material-button .gsi-material-button-icon {
    height: 22px;
    margin-right: 8px;
    min-width: 22px;
    width: 22px;
}

.gsi-material-button .gsi-material-button-content-wrapper {
    -webkit-align-items: center;
    align-items: center;
    display: flex;
    -webkit-flex-direction: row;
    flex-direction: row;
    -webkit-flex-wrap: nowrap;
    flex-wrap: nowrap;
    height: 100%;
    justify-content: space-between;
    position: relative;
    width: 100%;
}

.gsi-material-button .gsi-material-button-contents {
    -webkit-flex-grow: 1;
    flex-grow: 1;
    font-family: 'Roboto', arial, sans-serif;
    font-weight: 500;
    overflow: hidden;
    text-overflow: ellipsis;
    vertical-align: top;
}

.gsi-material-button .gsi-material-button-state {
    -webkit-transition: opacity .218s;
    transition: opacity .218s;
    bottom: 0;
    left: 0;
    opacity: 0;
    position: absolute;
    right: 0;
    top: 0;
}

.gsi-material-button:disabled {
    cursor: default;
    background-color: #ffffff61;
    border-color: #1f1f1f1f;
}

.gsi-material-button:disabled .gsi-material-button-contents {
    opacity: 38%;
}

.gsi-material-button:disabled .gsi-material-button-icon {
    opacity: 38%;
}

.gsi-material-button:not(:disabled):active .gsi-material-button-state,
.gsi-material-button:not(:disabled):focus .gsi-material-button-state {
    background-color: #303030;
    opacity: 12%;
}

.gsi-material-button:not(:disabled):hover {
    -webkit-box-shadow: 0 1px 2px 0 rgba(60, 64, 67, .30), 0 1px 3px 1px rgba(60, 64, 67, .15);
    box-shadow: 0 1px 2px 0 rgba(60, 64, 67, .30), 0 1px 3px 1px rgba(60, 64, 67, .15);
}

.gsi-material-button:not(:disabled):hover .gsi-material-button-state {
    background-color: #303030;
    opacity: 8%;
}

.profile-card {
    max-width: none;
}

.profile-photo {
    width: 48px;
    height: 48px;
    border-radius: 50%;
    object-fit: cover;
}

.ts-wrapper.form-select {
    background-image: none !important;
}

.chevron-toggle{display:inline-flex;transition:transform var(--sp-duration-fast) var(--sp-easing-standard)}
.chevron-toggle.rotate {
    transform: rotate(180deg);
}

/* Tuile « Vu à l'instant » (fiche photo-gallery) : le voile vit DANS la tuile, dont il prend le rayon */
.gallery-highlight-overlay {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 10px;
    border-radius: inherit;
    background-color: var(--sp-glass-overlay-tile-veil-seen);
    color: var(--sp-color-text-inverse);
    font-size: var(--sp-font-size-meta);
    font-weight: var(--sp-font-weight-title);
    line-height: 16px;
    letter-spacing: var(--sp-font-tracking-meta);
    text-align: center;
    pointer-events: none;
    transition: opacity 0.5s ease;
}

.gallery-highlight-fade {
    opacity: 0;
}

@media (max-width: 767.98px) {
    #photo-actions {
        width: 100%;
    }
}

/* Bloc de statistique (DESIGNAPP) : la valeur en grand, le libellé dessous en muted. Tous les
   blocs partagent la même taille de valeur, quelle que soit la longueur du nombre — c'est
   l'alignement qui les rend comparables. */
.stat-block-value{
    font-size: var(--sp-font-size-h2);
    font-weight: var(--sp-font-weight-title);
    color: var(--sp-color-text-default);
    line-height: 1.1;
}

.stat-block-label{
    font-size: var(--sp-font-size-meta);
    color: var(--sp-color-text-muted);
}

/* Les glyphes à la place du nombre : au rang de la valeur et à sa hauteur, nus et en
   currentColor — la zone ne parle que de disciplines, le badge n'aurait rien à isoler
   (DESIGNAPP, « Bloc de statistique » ; fiche sport-badge). */
.stat-block-glyphs{
    display: flex;
    align-items: center;
    gap: var(--sp-space-1);
}

/* 1,15em, pas 1em : un glyphe carré posé à la taille exacte des chiffres paraît plus petit
   qu'eux — sa hauteur inclut ses marges, celle d'un chiffre non (DESIGNAPP). */
.stat-block-glyphs svg{
    width: 1.15em;
    height: 1.15em;
}

/* Tabs variant `filter` (fiche tabs) : partition d'une liste DANS une carte. Exclusif et
   exhaustif — il n'y a jamais « rien de sélectionné ». L'actif est un aplat ink parce que la
   surface l'impose : dans une carte blanche, les pills au repos occupent déjà le crème, et un
   actif crème ne se distinguerait plus de ses voisines. */
.tabs-filter{
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--sp-space-2);
}

.tabs-filter-item{
    display: inline-flex;
    align-items: center;
    min-height: 36px;
    padding: var(--sp-space-2) var(--sp-space-4);
    border: 1px solid transparent;
    border-radius: var(--sp-radius-md);
    /* bg.control, pas le crème : ces pills vivent DANS une carte blanche, où le crème vire au
       beige sale contre le blanc qui l'entoure (tronc, « Pas de gris hors des échelles »).
       Scopé à ce variant : les onglets existants gardent leur pill crème. */
    background-color: var(--sp-color-bg-control);
    color: var(--sp-color-text-default);
    font-size: var(--sp-font-size-label);
    text-decoration: none;
    transition: background-color var(--sp-duration-fast) var(--sp-easing-standard);
}

.tabs-filter-item--active{
    background-color: var(--sp-color-action-primary);
    color: var(--sp-color-action-primary-text);
}

.tabs-filter-item:focus-visible{
    outline: none;
    box-shadow: var(--sp-shadow-ring);
}

/* Second axe (la période) : il se DESSINE au lieu de se remplir. Ses pills restent blanches,
   et c'est le filet qui porte l'état — ink et trait fort quand l'option est retenue, clair et
   libellé muted quand elle ne l'est pas. Deux aplats sur deux lignes donneraient deux ancres
   qui se disputent le regard (fiche tabs, variant filter). Scopé au second axe : le premier
   garde son aplat, et les onglets existants leur pill crème. */
.tabs-filter--second .tabs-filter-item{
    background-color: var(--sp-color-bg-surface);
    border-color: var(--sp-color-border-control);
    color: var(--sp-color-text-muted);
}

.tabs-filter--second .tabs-filter-item--active{
    background-color: var(--sp-color-bg-surface);
    border-width: var(--sp-border-width-strong);
    border-color: var(--sp-color-border-strong);
    color: var(--sp-color-text-default);
}

/* Le filet entre deux axes : celui de tout le produit (border.default, le même que le
   séparateur d'une ListItem), et une respiration ÉGALE des deux côtés (separator.gap). Le
   `hr` de Bootstrap arrive avec une opacité de .25 qui le rendait plus pâle que les autres
   filets — c'est elle qu'on annule, pas la couleur (fiche tabs). */
.tabs-filter-separator{
    margin: var(--sp-space-3) 0;
    border: 0;
    border-top: 1px solid var(--sp-color-border-default);
    opacity: 1;
}

/* Ligne de transaction (DESIGNAPP, « Pastille de transaction ») */
/* Cotes de la maquette (DESIGNAPP, « Cotes d'une ligne de transaction ») : 54px, gouttière 16,
   retrait 8 à gauche, et les lignes se suivent à 8px SANS filet — ce sont des mouvements
   d'argent, déjà séparés par leur pastille, leur date et leur montant. */
.transaction-row{
    display: flex;
    /* Aligné en haut, pas centré : une vente dépliée grandit vers le bas, et sa pastille
       comme son montant doivent rester sur la ligne de la date (DESIGNAPP). */
    align-items: flex-start;
    gap: var(--sp-space-4);
    min-height: 54px;
    padding: var(--sp-space-2) 0 var(--sp-space-2) var(--sp-space-2);
    border-radius: var(--sp-radius-lg);
}

.transaction-row + .transaction-row{
    margin-top: var(--sp-space-2);
}

/* La teinte classe la NATURE du mouvement — jamais son signe. */
.transaction-row-tile{
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 36px;
    height: 36px;
    border-radius: var(--sp-radius-md);
    color: var(--sp-color-text-default);
}

.transaction-row-tile--sale{ background-color: var(--sp-color-accent-soft); }
.transaction-row-tile--ad{ background-color: var(--sp-color-bg-sunken); }
.transaction-row-tile--payout{ background-color: var(--sp-color-bg-cream); }
.transaction-row-tile--adjustment{ background-color: var(--sp-color-bg-sunken); }

/* Un virement en cours n'est pas encore un mouvement : son montant s'estompe jusqu'à ce que
   l'argent parte vraiment. La pastille garde sa teinte — la nature n'a pas changé. */
.transaction-row--pending .transaction-row-amount{
    color: var(--sp-color-text-muted);
}

.transaction-row-date{
    color: var(--sp-color-text-default);
    font-weight: var(--sp-font-weight-title);
    line-height: 18px;
}

/* L'heure garde la TAILLE de la date et perd sa graisse : c'est la même information,
   précisée — pas une méta (maquette). */
.transaction-row-time{
    font-weight: var(--sp-font-weight-body);
    color: var(--sp-color-text-meta);
}

/* La méta se LIT (« 5 photos · Criterium de la Somme ») : text.meta, pas le gris clair qui
   la reléguait. Sa valeur de tête est en graisse de titre. */
.transaction-row-detail{
    font-size: var(--sp-font-size-meta);
    line-height: 16px;
    color: var(--sp-color-text-meta);
    font-weight: var(--sp-font-weight-body);
}

/* Dans une colonne de montants alignés à droite, c'est le signe et la couleur qui distinguent,
   pas l'épaisseur (maquette). */
.transaction-row-amount{
    flex-shrink: 0;
    white-space: nowrap;
    font-weight: var(--sp-font-weight-body);
    line-height: 18px;
    color: var(--sp-color-text-default);
}

/* Le signe qualifie : une sortie se lit en rouge — celui de la maquette, plus clair que le
   rouge du système (cf. DESIGNAPP, « Le montant sortant garde le rouge de la maquette »). */
.transaction-row-amount--out{
    color: var(--sp-color-transaction-amount-out);
}

/* Une vente déplie ses photos SUR PLACE, sous la ligne, sans quitter la page. L'affordance
   dit le nombre, et son libellé bascule avec l'état — un « + » qui reste « + » une fois
   ouvert ment sur ce qu'un second clic va faire (DESIGNAPP, « Une vente déplie ses photos »). */
.transaction-row-toggle{
    color: var(--sp-color-text-default);
    font-weight: var(--sp-font-weight-title);
    text-decoration: none;
}

.transaction-row-toggle .transaction-row-toggle-hide,
.transaction-row-toggle[aria-expanded="true"] .transaction-row-toggle-show{
    display: none;
}

.transaction-row-toggle[aria-expanded="true"] .transaction-row-toggle-hide{
    display: inline;
}

/* Le bloc déplié (`.transaction-row-more`, que Bootstrap ouvre et ferme) porte le lien de
   téléchargement puis la grille des photos (retour client). */
.transaction-row-photos{
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(64px, 1fr));
    gap: var(--sp-space-2);
    margin-top: var(--sp-space-3);
}

/* Une vignette est un bouton : elle ouvre la photo en grand (retour client) */
.transaction-row-thumb{
    padding: 0;
    border: 0;
    background: none;
    cursor: zoom-in;
}

.transaction-row-photos .thumbnail-wrapper{
    border-radius: var(--sp-radius-md);
    overflow: hidden;
}

/* Liste d'informations (DESIGNAPP, « Liste d'informations ») : une ligne par fait, séparées
   d'un filet ; visuel de tête de largeur constante, puis titre et méta. */
.info-list{
    margin: 0;
}

.info-row{
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: var(--sp-space-4) 0;
    border-top: var(--sp-border-width-hairline) solid var(--sp-color-border-default);
}

/* Le filet sépare, il n'encadre pas : pas de trait au-dessus de la première ligne. */
.info-row:first-child{
    border-top: 0;
    padding-top: 0;
}

/* Le visuel de tête sort de 2px de la gouttière (maquette) : avatar rond et SportBadge de 31px,
   centrés sur leur texte ; un glyphe nu de 24 tient une colonne de 25px, calé en haut, texte à
   14px (DESIGNAPP, « Cotes de la liste d'informations »). */
.info-row-visual,
.info-row > .sport-badge{
    flex: 0 0 31px;
    margin-left: -2px;
}

.info-row-visual{
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

.info-row-visual img{
    width: 31px;
    height: 31px;
}

.info-row > .sport-badge{
    height: 31px;
}

.info-row > .sport-badge svg{
    width: 16px;
    height: 16px;
}

.info-row:has(> .sport-badge),
.info-row:has(> .info-row-visual:not(.info-row-glyph)){
    align-items: center;
}

.info-row:has(> .sport-badge){
    gap: var(--sp-space-3);
}

.info-row-glyph{
    flex-basis: 25px;
    color: var(--sp-color-text-default);
}

.info-row:has(> .info-row-glyph){
    gap: 14px;
}

.info-row-title + .info-row-meta{
    margin-top: var(--sp-space-1);
}

/* Une méta tient sur une ligne (DESIGNAPP) : au-delà de ce que le contenu prévoit, elle se coupe
   plutôt que de passer à la ligne */
.info-row .info-row-meta{
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Sauf quand la couper cacherait l'essentiel : l'heure de la photo, ou des dossards qui sont
   autant de liens — au-delà du premier, ils disparaissaient sous les points de suspension */
.info-row .info-row-meta--wrap{
    overflow: visible;
    white-space: normal;
}

/* Le texte d'une ligne de License se lit en entier : il passe à la ligne, en ink (DESIGNAPP) */
.info-row-text{
    margin-top: var(--sp-space-1);
    font-size: var(--sp-font-size-label);
    font-weight: var(--sp-font-weight-prose);
    line-height: 17px;
    letter-spacing: var(--sp-font-tracking-tight);
    color: var(--sp-color-text-default);
}

.info-row-text + .info-row-text{
    margin-top: var(--sp-space-2);
}

/* Le numéro de dossard mène à ses autres photos : souligné, en gras */
.info-row-link{
    font-weight: var(--sp-font-weight-bold);
    color: inherit;
    text-decoration: underline;
}

/* Les autres photos d'un dossard (DESIGNAPP) : l'action, puis quatre vignettes */
/* Onglet Offres (DESIGNAPP, « L'onglet Offres ») : une carte en creux, la remise en tête, les
   paliers en tuiles blanches, les vignettes du photographe et le chemin vers ses photos */
.photo-offers{
    display: flex;
    flex-direction: column;
    gap: var(--sp-space-4);
    padding: var(--sp-space-4);
    border-radius: var(--sp-radius-xl);
    background-color: var(--sp-color-bg-sunken);
}

.photo-offers-head{
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--sp-space-3);
    text-align: center;
}

.photo-offers-deal{
    padding: var(--sp-space-2) 11px;
    border-radius: var(--sp-radius-full);
    background-color: var(--sp-color-accent-deal);
    color: var(--sp-color-text-inverse);
    font-size: var(--sp-font-size-h4);
    font-weight: var(--sp-font-weight-title);
    line-height: 19px;
    letter-spacing: var(--sp-font-tracking-tight);
}

.photo-offers-lead{
    font-size: var(--sp-font-size-body);
    font-weight: var(--sp-font-weight-prose);
    line-height: 18px;
    letter-spacing: var(--sp-font-tracking-tight);
    color: var(--sp-color-text-default);
}

.photo-offers-author{
    font-weight: var(--sp-font-weight-title);
    color: var(--sp-color-text-default);
    text-decoration: none;
}

.photo-offers-tiers{
    display: flex;
    gap: var(--sp-space-2);
}

.photo-offers-tier{
    display: flex;
    flex: 1 1 0;
    flex-direction: column;
    gap: var(--sp-space-2);
    min-width: 0;
    padding: var(--sp-space-2);
    border-radius: var(--sp-radius-md);
    background-color: var(--sp-color-bg-surface);
}

.photo-offers-qty{
    font-size: var(--sp-font-size-meta);
    font-weight: var(--sp-font-weight-title);
    line-height: 16px;
    color: var(--sp-color-text-default);
}

.photo-offers-price{
    display: flex;
    flex-direction: column;
    gap: var(--sp-space-1);
    padding-top: var(--sp-space-2);
    border-top: var(--sp-border-width-hairline) solid var(--sp-color-border-cream);
}

.photo-offers-was{
    font-size: var(--sp-font-size-12);
    line-height: 15px;
    color: var(--sp-color-text-brown);
}

.photo-offers-now{
    font-size: var(--sp-font-size-h4);
    font-weight: var(--sp-font-weight-bold);
    line-height: 19px;
    letter-spacing: var(--sp-font-tracking-tight);
    color: var(--sp-color-text-default);
}

/* Le prix ne se coupe pas ; l'unité passe dessous quand la tuile est étroite */
.photo-offers-unit{
    white-space: nowrap;
    font-size: var(--sp-font-size-12);
    font-weight: var(--sp-font-weight-body);
    letter-spacing: var(--sp-font-tracking-tight);
}

.photo-offers-thumbs{
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: var(--sp-space-2);
}

.photo-offers-thumb{
    display: block;
    aspect-ratio: 1;
    overflow: hidden;
    border-radius: var(--sp-radius-md);
}

.photo-offers-thumb img{
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.btn.photo-offers-action{
    --bs-btn-bg: var(--sp-color-action-primary);
    --bs-btn-color: var(--sp-color-text-inverse);
    --bs-btn-hover-bg: var(--sp-color-action-primary);
    --bs-btn-hover-color: var(--sp-color-text-inverse);
    --bs-btn-active-bg: var(--sp-color-action-primary);
    --bs-btn-active-color: var(--sp-color-text-inverse);
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 46px;
    border: 0;
    border-radius: var(--sp-radius-md);
    font-size: var(--sp-font-size-body);
    font-weight: var(--sp-font-weight-title);
    line-height: 18px;
    letter-spacing: var(--sp-font-tracking-tight);
}

.bib-others{
    display: flex;
    flex-direction: column;
    gap: var(--sp-space-6);
    padding: var(--sp-space-4);
    border-radius: var(--sp-radius-xl);
    background-color: var(--sp-color-bg-sunken);
}

.btn.bib-others-action{
    --bs-btn-bg: var(--sp-color-action-primary);
    --bs-btn-color: var(--sp-color-text-inverse);
    --bs-btn-hover-bg: var(--sp-color-action-primary);
    --bs-btn-hover-color: var(--sp-color-text-inverse);
    --bs-btn-active-bg: var(--sp-color-action-primary);
    --bs-btn-active-color: var(--sp-color-text-inverse);
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 46px;
    /* 6px de côté (10 sur la maquette, libellé centré) : un dossard de cinq chiffres tient la ligne */
    padding: var(--sp-space-1) 6px;
    border: 0;
    border-radius: var(--sp-radius-lg);
    box-shadow: var(--sp-shadow-sm);
    font-size: var(--sp-font-size-label);
    font-weight: var(--sp-font-weight-body);
    line-height: 17px;
    letter-spacing: var(--sp-font-tracking-tight);
}

.bib-others-grid{
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: var(--sp-space-2);
}

.bib-others-tile{
    position: relative;
    display: block;
    aspect-ratio: 1;
    overflow: hidden;
    border-radius: var(--sp-radius-md);
}

.bib-others-tile img{
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.bib-others-more{
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    background-color: var(--sp-glass-overlay-tile-veil);
    color: var(--sp-color-text-inverse);
    font-size: var(--sp-font-size-h4);
    font-weight: var(--sp-font-weight-title);
    line-height: 19px;
    letter-spacing: var(--sp-font-tracking-tight);
}

.info-row-title{
    color: var(--sp-color-text-default);
}

.info-row-meta{
    font-size: var(--sp-font-size-meta);
    color: var(--sp-color-text-muted);
}

.info-row-sep{
    margin: 0 var(--sp-space-1);
}

/* Progress (fiche progress) : la barre figure ce qui RESTE, part de la gauche, et ne porte
   aucune étiquette — le compte est dit au-dessus, en toutes lettres. */
.progress-gauge{
    height: 8px;
    border-radius: var(--sp-radius-full);
    background-color: var(--sp-color-accent-soft);
    overflow: hidden;
}

.progress-gauge-fill{
    display: block;
    height: 100%;
    width: var(--progress-value, 0%);
    border-radius: var(--sp-radius-full);
    background-color: var(--sp-color-accent-selected);
}

/* La légende de la jauge : plus petite que le corps parce qu'elle accompagne un chiffre déjà
   écrit en grand sur la ligne du titre — la graisse compense ce que la taille lui retire. Elle
   reste une phrase, jamais un style de libellé (fiche progress). */
.progress-gauge-legend{
    font-family: var(--sp-font-family-base), sans-serif;
    font-size: var(--sp-font-size-meta);
    font-weight: var(--sp-font-weight-title);
}

/* Onglets d'information de la vue photo (fiche tabs) : le filet bas ancre le groupe,
   à la même distance de part et d'autre (separator.gap). */
.photo-tabs{
    border-bottom: 1px solid var(--sp-color-border-default);
    padding-bottom: var(--sp-space-4);
    margin-bottom: var(--sp-space-4);
}

/* Chaque onglet tient un quart de la mesure, à partir de la gauche ; un onglet absent laisse sa
   part vide (DESIGNAPP, « Vue photo »). Seule la pilule active porte ses 18px de côté ; le
   premier se cale sur le bord de la liste et les garde, actif ou non. */
.photo-tabs .nav-item{
    display: flex;
    flex: 0 0 25%;
    justify-content: center;
}

.photo-tabs .nav-link:not(.active){
    padding-left: 0;
    padding-right: 0;
}

.photo-tabs .nav-item:first-child{
    justify-content: flex-start;
}

.photo-tabs .nav-item:first-child .nav-link{
    padding-left: 18px;
    padding-right: 18px;
}

/* Mobile (maquette INFOS LICENSE) : filet BROWN_BORDER_MEDIUM à 15px sous les pilules. Les
   onglets gardent leurs quarts fixes (ci-dessus) : la maquette donne à l'actif la mesure de sa
   pilule et répartit le reste, mais la rangée se redistribuait alors à chaque changement
   d'onglet. En quarts, la pilule de License tombe à 2px de sa place sur la maquette, et rien ne
   bouge. */
@media (max-width: 991.98px) {
    .photo-tabs{
        padding-bottom: 15px;
        border-bottom-color: #DCDAD1;
    }
}

/* La rangée ne se replie jamais (une pilule active plus large renvoyait « Offres » à la ligne),
   et un onglet centré se mesure à son libellé, actif ou non : ses 18px de pilule débordent de sa
   boîte (marge négative) au lieu de l'élargir — sans quoi, plus large que son quart, la pilule
   se calait au début de la colonne et le libellé sautait de 4px. */
.photo-tabs{
    flex-wrap: nowrap;
}

.photo-tabs .nav-item:not(:first-child) .nav-link{
    padding-left: 18px;
    padding-right: 18px;
    margin: 0 -18px;
}

/* Le 4e onglet se cale à droite, pilule comprise, comme le 1er à gauche : centré, sa pilule
   dépassait la mesure de 5px sur mobile */
.photo-tabs .nav-item:nth-child(4){
    justify-content: flex-end;
}

.photo-tabs .nav-item:nth-child(4) .nav-link{
    margin: 0 0 0 -18px;   /* sa boîte tient dans son quart : l'alignement à droite s'applique */
}

/* Pastille d'annonce d'un onglet : elle annonce, elle ne sélectionne pas — seul orange
   admis dans une barre d'onglets, et il y dit un état (fiche tabs). */
.tab-dot{
    display: inline-block;
    width: 6px;
    height: 6px;
    flex: 0 0 auto;
    border-radius: var(--sp-radius-full);
    background-color: var(--sp-color-accent-selected);
}

/* EMPLACEMENT de la photo (DESIGNAPP, « Vue photo ») : c'est LUI qui a la taille fixe, ratio 3:2,
   pas la carte. Sans ça, le ruban, l'achat et les onglets qui vivent dessous montent et descendent
   à chaque photo. La carte s'y centre, et ce qui reste libre autour d'elle est le fond de page —
   jamais une bande dans la carte. Les flèches lui sont absolues, donc hors flux. */
.photo-frame{
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    aspect-ratio: 3 / 2;
    /* Conteneur de requête : c'est ce qui permet de borner la photo sur CET emplacement, en
       `cqw`/`cqh`. Une chaîne de `max-height: 100%` ne marcherait pas — un pourcentage de hauteur
       ne résout pas contre un parent en hauteur auto, et la carte reprenait toute la place. */
    container-type: size;
    /* Le glissement se joue ICI (DESIGNAPP, « Vue photo ») : c'est la seule boîte dont la taille
       ne dépend pas de la photo. Le nom porté par la CARTE faisait animer au navigateur son
       redimensionnement en même temps que le déplacement, et les deux mouvements se contrariaient. */
    view-transition-name: photo-frame;
}

/* Vue photo (DESIGNAPP, « Vue photo ») : la photo est la vedette, coins radius.2xl. La carte
   ÉPOUSE la photo — c'est elle qui s'ajuste, jamais la photo —, donc ses coins arrondissent
   l'image et non un vide. Elle est bornée par l'emplacement, en hauteur comme en largeur. */
.photo-stage{
    position: relative;
    display: inline-block;
    max-width: 100%;
    max-height: 100%;
    border-radius: var(--sp-radius-2xl);
    overflow: hidden;
}

/* Transition de défilement entre deux photos (DESIGNAPP, « Vue photo »). Elle n'existe QUE si la
   direction a été posée sur <html> — donc entre deux photos, jamais en quittant l'écran. Le signe
   porte le sens : on sort du côté d'où l'on vient, on entre du côté où l'on allait. Le décalage
   est une AMORCE (12%), pas une traversée : la photo est la vedette, elle ne part pas en voyage. */
html[data-photo-transition="next"]{ --photo-slide: 1; }
html[data-photo-transition="prev"]{ --photo-slide: -1; }

/* Glissement FRANC : la sortante quitte le cadre par un bord, l'entrante arrive par l'autre, sur
   toute la largeur de la carte. Un décalage de 12% ne disait aucun sens — il ne restait qu'un
   fondu (DESIGNAPP, « Vue photo »). Pas de fondu ici, donc : ce qui porte le sens, c'est le
   déplacement, et une photo qui s'efface en même temps qu'elle sort brouille la lecture.

   Le repli à 1 n'est pas décoratif : sans lui, un `--photo-slide` absent rendrait le `calc()`
   invalide et la photo ne bougerait plus, en silence. Mieux vaut glisser du mauvais côté que ne
   plus glisser du tout — l'erreur se voit, et se corrige. */
@keyframes photo-slide-out{
    to { transform: translateX(calc(var(--photo-slide, 1) * -100%)); }
}

@keyframes photo-slide-in{
    from { transform: translateX(calc(var(--photo-slide, 1) * 100%)); }
}

/* La couche de transition recouvre TOUTE la page le temps du glissement (captures comprises,
   plus longues sur iPhone) : le premier tap après un balayage — « Acheter en HD », une vignette du
   ruban — tombait sur elle et se perdait, il fallait taper deux fois (retour client). Elle laisse
   passer les taps vers la page, qui reste utilisable pendant l'animation. */
html[data-photo-transition]::view-transition{
    pointer-events: none;
}

/* PAS D'ESPACE avant le pseudo-élément : les pseudo-éléments de transition sont attachés à
   l'élément racine LUI-MÊME. `html[...] ::view-transition-old()` est un combinateur descendant —
   il cherche une transition née d'un descendant de <html>, ce qui n'existe pas, et la règle ne
   s'applique jamais (sans erreur, la feuille reste valide). */
html[data-photo-transition]::view-transition-old(photo-frame){
    animation: photo-slide-out var(--sp-duration-base) var(--sp-easing-standard) both;
}

html[data-photo-transition]::view-transition-new(photo-frame){
    animation: photo-slide-in var(--sp-duration-base) var(--sp-easing-standard) both;
}

/* Le groupe DÉTOURE le mouvement : sans ce clip, une photo qui se déplace de toute sa largeur
   passerait par-dessus ce qui l'entoure — la colonne d'achat sur desktop, le ruban sur mobile —
   et la vedette voyagerait en travers de la page au lieu d'être remplacée.

   Sur desktop l'emplacement ne change pas de taille : le groupe n'a donc rien à morpher, et le
   glissement est le SEUL mouvement à l'écran. Sur mobile sa hauteur suit la photo ; on lui donne
   la durée du système pour que le redimensionnement finisse avec le glissement, jamais après. */
html[data-photo-transition]::view-transition-group(photo-frame){
    animation-duration: var(--sp-duration-base);
    animation-timing-function: var(--sp-easing-standard);
    overflow: hidden;
}

/* Les deux images gardent leurs proportions pendant que le groupe change de taille : sans ça,
   l'ancienne est étirée aux dimensions de la nouvelle et la photo se tord en glissant. */
html[data-photo-transition]::view-transition-old(photo-frame),
html[data-photo-transition]::view-transition-new(photo-frame){
    object-fit: contain;
    height: 100%;
    width: 100%;
}

/* Le reste de la page (achat, onglets, ruban) se contente du fondu, à la durée du système —
   la valeur par défaut du navigateur (250ms) sort de l'échelle du DS. */
html[data-photo-transition]::view-transition-old(root),
html[data-photo-transition]::view-transition-new(root){
    animation-duration: var(--sp-duration-base);
    animation-timing-function: var(--sp-easing-standard);
}

/* La photo garde SON format, entière : ni rognée, ni remplie. Pas d'`object-fit` ici — la carte
   fait exactement sa taille (tronc, « Images » : la seule image du produit qui ne soit pas en
   `cover`). Elle se borne à l'emplacement par ses deux dimensions, sans quoi un portrait le
   déborderait en hauteur. */
.photo-stage img{
    display: block;
    width: auto;
    height: auto;
    max-width: 100cqw;
    max-height: 100cqh;
}

/* MOBILE : l'emplacement ne réserve RIEN (DESIGNAPP, « Vue photo »). La carte prend toute la
   largeur, sa hauteur suit la photo, et ce qui vit dessous se déplace d'une photo à l'autre —
   c'est assumé. Réserver la hauteur du cas portrait laissait, sous une photo paysage, un vide de
   la hauteur d'une main et repoussait l'achat sous la ligne de flottaison.

   Ce bloc vit APRÈS les règles de base, et pas avec les autres surcharges mobiles plus haut :
   à spécificité égale, un média query ne prime pas — c'est l'ordre qui tranche. */
@media (max-width: 767.98px) {
    .photo-frame{
        aspect-ratio: auto;
        /* Plus de hauteur définie, donc plus de conteneur de requête en hauteur : les `cqh` ne
           résoudraient plus rien. La carte se borne à la largeur seule. */
        container-type: inline-size;
    }

    .photo-stage img{
        max-height: none;
    }
}

/* Actions de page et évènement posés sur la photo, sur un scrim DESCENDANT : l'inverse de
   celui des cartes, puisque le texte est ici en haut. */
.photo-stage-bar{
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    z-index: 1;
    display: flex;
    align-items: center;
    gap: var(--sp-space-3);
    padding: var(--sp-space-4);
    text-align: left;
    color: var(--sp-color-text-inverse);
    background: linear-gradient(to bottom, var(--sp-color-overlay-scrim), transparent);
}

/* Indicateur de carousel au BAS de la photo (DESIGNAPP, « Vue photo ») : miroir de la barre du
   haut — scrim MONTANT, texte blanc. Le compteur à gauche, les points au centre absolu. */
.photo-stage-carousel{
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    z-index: 1;
    display: flex;
    align-items: center;
    padding: var(--sp-space-4);
    color: var(--sp-color-text-inverse);
    background: linear-gradient(to top, var(--sp-color-overlay-scrim), transparent);
}

/* Compteur de position : il ne porte QUE la mise en page ; la taille, la graisse, le rayon, le
   verre et le liseré viennent de `.badge.badge-glass` — le même objet que le compteur de photos
   d'une EventCardHighlighted (fiche badge). Le `gap` du badge sert à décoller un glyphe de son
   nombre ; ce compteur n'en a pas, et sans cette remise à zéro il écarterait « 2 » de « /14 ». */
.photo-stage-counter{
    gap: 0;
}

/* Le total accompagne, la position porte : un cran plus discret. La hiérarchie se fait à
   l'opacité, jamais à la graisse — un badge n'a qu'une graisse (fiche badge). */
.photo-stage-counter-total{
    opacity: .7;
}

/* Points centrés dans la barre, quelle que soit la largeur du compteur à gauche. */
.photo-stage-dots{
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    display: inline-flex;
    align-items: center;
    gap: var(--sp-space-2);
}

/* Même pastille que l'indicateur de carrousel de l'EventRail (`.rail-dot`, fiche event-rail) :
   `carousel.dot` (6px), inactif `border.cream`, actif `accent.selected` — un rond qui change de
   couleur, jamais une pilule qui s'allonge. On garde le pattern commun, pas un second style. */
.photo-stage-dot{
    width: var(--sp-carousel-dot);
    height: var(--sp-carousel-dot);
    border-radius: var(--sp-radius-full);
    background-color: var(--sp-color-border-cream);
    transition: background-color var(--sp-duration-fast) var(--sp-easing-standard);
}

.photo-stage-dot.is-active{
    background-color: var(--sp-color-accent-selected);
}

/* Cadre desktop de la colonne droite (DESIGNAPP, « Vue photo » deux colonnes). */

/* Retour texte vers la galerie : lien ink (pas l'orange, réservé à l'achat), avec chevron. */
.photo-back-gallery{
    color: var(--sp-color-text-default);
    font-size: var(--sp-font-size-body);
    font-weight: var(--sp-font-weight-title);
    line-height: 18px;
    text-decoration: none;
}

.photo-back-gallery:hover{
    color: var(--sp-color-text-default);
    text-decoration: underline;
}

/* .photo-side-title est un titre de page : sa règle vit avec .page-title, plus haut. */

/* Carte évènement (maquette PHOTO DESKTOP) : creux crème ombré au rayon 24 — de la couleur du
   sol desktop, elle disparaissait —, SportBadge de 42px, nom en 20/24, « journée › album » en 15/18 */
.photo-event-card{
    padding: var(--sp-space-4);
    border-radius: var(--sp-radius-2xl);
    background-color: var(--sp-color-bg-sunken);
    box-shadow: var(--sp-shadow-sm);
    color: var(--sp-color-text-default);
}

.photo-event-card > .sport-badge{
    flex: 0 0 42px;
    width: 42px;
    height: 42px;
    border-radius: var(--sp-radius-md);
}

.photo-event-card-title{
    font-size: var(--sp-font-size-h3);
    font-weight: var(--sp-font-weight-title);
    line-height: 24px;
    letter-spacing: var(--sp-font-tracking-tighter);
}

.photo-event-card-meta{
    font-size: var(--sp-font-size-body);
    font-weight: var(--sp-font-weight-body);
    line-height: 18px;
    letter-spacing: var(--sp-font-tracking-tight);
    color: var(--sp-color-text-default);
}

/* Grille de la vue photo (DESIGNAPP, « Vue photo »). Mobile : une colonne — la photo, la
   mini-galerie, la décision, les autres photos du dossard. Desktop : la photo et la colonne de
   420px à 34px, puis à 24px un bandeau pleine largeur, la mini-galerie et le panneau du dossard. */
.photo-page-row{
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas: "main" "strip" "side" "bib";
    margin-bottom: var(--sp-space-6);
}

.photo-page-main{
    grid-area: main;
    min-width: 0;
}

.photo-page-side{
    grid-area: side;
    min-width: 0;
}

.photo-page-below{
    display: contents;
}

.photo-page-below > .photo-filmstrip{
    grid-area: strip;
}

.photo-page-below > .bib-others{
    grid-area: bib;
}

/* Mobile : le panneau du dossard suit la carte d'onglets sans écart — l'onglet Offres (violet)
   le touchait (retour du 06/11). 16px, comme entre les autres blocs de la colonne. */
@media (max-width: 991.98px) {
    .photo-page-below > .bib-others{
        margin-top: var(--sp-space-4);
    }
}

@media (min-width: 992px) {
    .container.photo-page{
        max-width: calc(var(--sp-layout-content-wide) + var(--bs-gutter-x));
    }

    .photo-page-row{
        grid-template-columns: minmax(0, 1fr) 420px;
        grid-template-areas: "main side" "below below";
        column-gap: 34px;
        row-gap: var(--sp-space-6);
    }

    /* L'emplacement de la photo prend la proportion de la maquette, 826 × 626 */
    .photo-page .photo-frame{
        aspect-ratio: 413 / 313;
    }

    .photo-page-below{
        grid-area: below;
        display: flex;
        align-items: flex-start;
        gap: var(--sp-space-6);
    }

    .photo-page-below > .photo-filmstrip{
        position: relative;
        flex: 1 1 0;
        min-width: 0;
        gap: var(--sp-space-4);
        padding: 12px var(--sp-space-4) var(--sp-space-4);
    }

    /* Sur la vignette voilée, à 21px de son bord et centré sur la rangée (maquette : 37px) */
    .photo-page-below .photo-filmstrip-arrow{
        display: inline-flex;
        top: calc(50% - 2px);
        z-index: 1;
    }

    .photo-page-below .photo-filmstrip-arrow--prev{
        left: calc(var(--sp-space-4) + 21px);
    }

    .photo-page-below .photo-filmstrip-arrow--next{
        right: calc(var(--sp-space-4) + 21px);
    }

    .photo-page-below > .bib-others{
        flex: 0 0 420px;
        margin-left: auto;
    }

    /* Photo offerte avec annonce (retour du 06/11) : la mini-galerie passe sous la photo, son
       haut aligné sur la carte d'onglets, et ses vignettes grandissent (5 au lieu de 7). La
       hauteur de la photo suit donc le haut de la colonne de droite (retour, titre, achat,
       annonce) ; le panneau du dossard reste en dessous. */
    .photo-page-row:has(.photo-detail-ad){
        grid-template-areas: "main top" "strip card" "bib bib";
        row-gap: var(--sp-space-4);
    }

    .photo-page-row:has(.photo-detail-ad) > .photo-page-below,
    .photo-page-row:has(.photo-detail-ad) > .photo-page-side{
        display: contents;
    }

    .photo-page-row:has(.photo-detail-ad) .photo-side-top{
        grid-area: top;
        padding-top: 12px;
    }

    .photo-page-row:has(.photo-detail-ad) .photo-page-side > .event-section-card{
        grid-area: card;
        align-self: start;
    }

    .photo-page-row:has(.photo-detail-ad) .photo-page-below > .photo-filmstrip{
        align-self: start;
        align-items: flex-start;
        gap: var(--sp-space-4);
        /* 6px de réserve pour l'ombre de la courante, compensés par la marge du ruban défilant */
        padding-top: 6px;
    }

    /* La photo ne fixe plus la hauteur de sa rangée : elle remplit ce que la colonne lui laisse */
    .photo-page-row:has(.photo-detail-ad) > .photo-page-main{
        position: relative;
    }

    .photo-page-row:has(.photo-detail-ad) #photo-main{
        position: absolute !important;
        inset: 0;
    }

    .photo-page-row:has(.photo-detail-ad) .photo-frame{
        aspect-ratio: auto;
        height: 100%;
    }

    .photo-page-row:has(.photo-detail-ad) .photo-page-below > .bib-others{
        width: 420px;
        justify-self: end;
    }

    /* La courante un cran plus grande : 175 pour 163 */
    .photo-page-below .photo-filmstrip-item{
        flex-grow: 163;
    }

    .photo-page-below .photo-filmstrip-item.is-current{
        flex-grow: 175;
    }

    /* À côté du panneau du dossard, la galerie se resserre : six vignettes égales à space.2 */
    .photo-page-below:has(> .bib-others) > .photo-filmstrip{
        gap: var(--sp-space-2);
    }

    .photo-page-below:has(> .bib-others) .photo-filmstrip-item.is-current{
        flex-grow: 163;
    }

    /* La colonne : 12px sous le haut de la photo, des blocs à space.4. Les marges utilitaires
       du gabarit servent la colonne mobile ; ici c'est l'écart du flex qui compte. */
    .photo-page-side,
    .photo-side-top{
        display: flex;
        flex-direction: column;
        gap: var(--sp-space-4);
    }

    .photo-page-side{
        padding-top: 12px;
    }

    .photo-side-head{
        flex-direction: column;
        align-items: flex-start;
        gap: var(--sp-space-4);
    }

    .photo-side-head > .photo-event-card{
        align-self: stretch;
    }

    .photo-page-side #photo-actions,
    .photo-page-side #photo-actions > .d-flex{
        gap: var(--sp-space-3) !important;
    }

    .photo-page-side #photo-actions{
        margin-bottom: 0 !important;
    }

    /* Achat en pilule de 50px, partage en disque de 48px centré sur elle */
    .photo-page-side .photo-actions .btn{
        min-height: 50px;
    }

    .photo-page-side .photo-actions .btn-circle{
        align-self: center;
        min-height: 48px;
    }

    /* La carte Infos n'a pas de gouttière : onglets et lignes portent leur retrait */
    .photo-page-side .event-section-card{
        padding: 0 0 var(--sp-space-6);
        box-shadow: var(--sp-shadow-sm);
    }

    .photo-page-side .photo-tabs{
        --bs-nav-pills-link-active-bg: var(--sp-color-bg-sunken-strong);
        margin: 0 var(--sp-space-4) var(--sp-space-4);
        padding-top: var(--sp-space-4);
        padding-bottom: 15px;
    }

    .photo-page-side .info-list,
    .photo-page-side .photo-offers{
        margin: 0 var(--sp-space-4);
    }

    /* L'aperçu prend le même retrait que les onglets (retour client : il touchait les bords) */
    .photo-page-side .photo-zoom-crop{
        /* Le bouton est à 100 % : sans ce calcul, ses marges le font déborder de la carte (retour du 29/10). */
        width: calc(100% - var(--sp-space-4) * 2);
        margin-left: var(--sp-space-4);
        margin-right: var(--sp-space-4);
    }

    /* La carte porte ses 24px sous la dernière ligne */
    .photo-page-side .info-row:last-child{
        padding-bottom: 0;
    }
}

/* Le titre de l'écran seul : plus de compteur à côté sur desktop (retour client) */
.photo-side-heading{
    display: flex;
    align-items: baseline;
    gap: 17px;
}

@media (min-width: 992px) {
    .photo-side-title{
        font-size: var(--sp-font-size-h2-dense);
        line-height: 29px;
        letter-spacing: var(--sp-font-tracking-tighter);
    }
}

/* Barre d'acquisition, sous le filmstrip (DESIGNAPP, « Vue photo ») : un libellé de bouton ne se
   coupe jamais en deux lignes — un CTA sur deux lignes se lit comme deux actions empilées, et le
   pill l'accuse. Quand les deux CTA ne tiennent plus côte à côte, c'est la BARRE qui passe à la
   ligne, pas le texte : `wrap` + un libellé `nowrap` font que le second bouton descend au moment
   exact où il ne tient plus (fiche button, « une barre d'actions se replie »). */
.photo-actions{
    flex-wrap: wrap;
}

.photo-actions .btn{
    white-space: nowrap;
    /* La cible tactile ne peut plus venir du voisin : `align-items: stretch` n'égalise QUE les
       boutons d'une même ligne, et une fois la barre repliée le bouton seul sur la sienne retombe
       à sa hauteur de texte. Chacun tient donc ses 44px pour lui-même (fiche button). */
    min-height: var(--sp-control-icon-button);
}

/* Dernier recours seulement : sous ~300px, même seul sur sa ligne un libellé peut déborder. On
   l'ellipse alors plutôt que de laisser la page défiler en largeur ; au-dessus de cette laize la
   règle ci-dessus l'a déjà fait descendre, et rien n'est coupé. */
.photo-actions .text-truncate{
    min-width: 0;
}

/* Groupe d'actions sur la photo : les boutons glass voisins partagent UNE pilule de verre
   plutôt que de se répéter en disques isolés (fiche icon-button). Poussé à droite de la barre. */
.photo-stage-actions{
    display: flex;
    align-items: center;
    flex-shrink: 0;
    margin-left: auto;
    border-radius: var(--sp-radius-full);
    background-color: var(--sp-glass-button-bg);
    backdrop-filter: blur(var(--sp-glass-blur));
    -webkit-backdrop-filter: blur(var(--sp-glass-blur));
    border: 1px solid var(--sp-glass-button-border);
}

/* Chaque action garde une cible tactile pleine (control.icon-button) */
.photo-stage-action{
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: var(--sp-control-icon-button);
    height: var(--sp-control-icon-button);
    flex: 0 0 auto;
    padding: 0;
    border: 0;
    background: none;
    border-radius: var(--sp-radius-full);
    color: var(--sp-color-text-inverse);
}

/* Aucune séparation entre les actions : le groupe se lit comme UN objet, pas comme des
   boutons accolés (fiche icon-button). C'est le conteneur qui porte le verre ; les boutons
   ne portent ni fond, ni bordure, ni filet. */

/* Menu (fiche menu, maquette « Above Keyboard Button ») : surface sombre quasi pleine — un
   libellé d'action doit rester lisible quelle que soit la photo dessous —, 242px, gouttière de
   16, liseré d'1px en dégradé posé en masque. */
.menu-overlay{
    --bs-dropdown-bg: transparent;
    --bs-dropdown-border-width: 0;
    --bs-dropdown-padding-y: var(--sp-space-4);
    --bs-dropdown-padding-x: var(--sp-space-4);
    --bs-dropdown-min-width: 242px;
    width: 242px;
    background-color: var(--sp-glass-menu-bg);
    backdrop-filter: blur(var(--sp-glass-menu-blur));
    -webkit-backdrop-filter: blur(var(--sp-glass-menu-blur));
    border: 0;
    border-radius: var(--sp-radius-lg);
    box-shadow: var(--sp-shadow-pop);
}

.menu-overlay.show{
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.menu-overlay::after{
    content: '';
    position: absolute;
    inset: 0;
    padding: 1px;
    border-radius: inherit;
    background: var(--sp-glass-menu-rim);
    -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    -webkit-mask-composite: xor;
    mask: linear-gradient(#000 0 0) content-box exclude, linear-gradient(#000 0 0);
    pointer-events: none;
}

/* Une ligne = une action : glyphe de 18, puis libellé 15/18 sur une seule ligne */
.menu-overlay-item{
    display: flex;
    align-items: center;
    gap: var(--sp-space-3);
    width: 100%;
    min-height: 23px;
    padding: 0;
    border: 0;
    border-radius: var(--sp-radius-xs);
    background: none;
    font-size: var(--sp-font-size-body);
    font-weight: var(--sp-font-weight-body);
    line-height: 18px;
    letter-spacing: var(--sp-font-tracking-tight);
    text-align: left;
    text-decoration: none;
    white-space: nowrap;
    color: var(--sp-color-text-inverse);
}

.menu-overlay-item:hover,
.menu-overlay-item:focus-visible{
    color: var(--sp-color-text-inverse);
    background-color: var(--sp-glass-overlay-bg);
    box-shadow: 0 0 0 var(--sp-space-1) var(--sp-glass-overlay-bg);
}

.photo-stage-title{
    font-size: var(--sp-font-size-label);
    font-weight: var(--sp-font-weight-title);
    color: var(--sp-color-text-inverse);
}

/* Le texte est ce qui cède quand la barre manque de place — les boutons-icônes, eux, restent
   côte à côte (fiche icon-button). Le titre porte son clamp dans le gabarit ; la date le prend
   ici, sans quoi elle passerait sur deux lignes et grandirait la barre au lieu de se couper. */
.photo-stage-date{
    font-size: var(--sp-font-size-meta);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Flèches de la vue photo et de sa mini-galerie (DESIGNAPP, « Vue photo ») : IconButton variant
   surface, disques blancs de 40px ; celles de la photo à space.4 des bords de l'emplacement. */
.photo-nav-arrow,
.photo-filmstrip-arrow {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    z-index: 10;
    width: 40px;
    height: 40px;
    min-width: 40px;
    min-height: 40px;
}

/* Une commande de carrousel ne se dérobe pas sous le doigt — et surtout, le `scale` de la
   pression remplacerait le `translateY` qui la centre : elle retomberait d'une demi-hauteur au
   moment du clic. Même exception que les chevrons du rail. */
.photo-nav-arrow:not(:disabled):active,
.photo-filmstrip-arrow:not(:disabled):active {
    transform: translateY(-50%);
}

/* Pas de disque sur la mini-galerie mobile : on glisse */
.photo-filmstrip-arrow {
    display: none;
}

.photo-nav-arrow--prev {
    left: var(--sp-space-4);
}

.photo-nav-arrow--next {
    right: var(--sp-space-4);
}

/* Filmstrip de la vue photo (DESIGNAPP, « Vue photo ») : ruban horizontal des photos voisines,
   la courante mise en avant à l'OPACITÉ seule. Le padding vertical laisse respirer l'anneau de
   FOCUS, le seul qui se dessine encore ici. Vignettes radius.md (fiche card / DESIGN images). */
.photo-filmstrip {
    display: flex;
    align-items: center;
    gap: var(--sp-space-2);
    /* Ni scroll, ni overflow : le contrôleur ne laisse visibles QUE les vignettes voulues
       (4 mobile / 7 desktop, centrées sur la courante), les autres sont `hidden`. Rien ne clippe,
       donc l'anneau de focus s'affiche en entier ; le ruban tient la largeur du contenu et
       reste aligné avec le reste, jamais collé au bord (DESIGNAPP, « Vue photo »). */
    padding-block: var(--sp-space-2);
}

.photo-filmstrip-item {
    /* Les vignettes VISIBLES se partagent la largeur du contenu ; le carré suit leur largeur. */
    flex: 1 1 0;
    aspect-ratio: 1;
    border-radius: var(--sp-radius-md);
    overflow: hidden;
    opacity: .55;
    transition: opacity var(--sp-duration-fast) var(--sp-easing-standard);
}

.photo-filmstrip-item img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.photo-filmstrip-item:hover {
    opacity: 1;
}

.photo-filmstrip-item:focus-visible {
    opacity: 1;
    outline: 2px solid var(--sp-color-border-focus);
    outline-offset: 2px;
}

/* La courante : pleine opacité, et RIEN d'autre. Pas d'anneau — l'orange cerné dit « coché »
   (PhotoGallery, état selected) ou « focus », jamais « vous êtes ici » (DESIGNAPP, « Vue photo »).
   Ce sont les voisines qui reculent ; la courante ne fait que rester entière. */
.photo-filmstrip-item.is-current {
    opacity: 1;
}

/* Voile de bord : l'album continue au-delà de ce bout du ruban (posé par photo-filmstrip) */
.photo-filmstrip-item.is-edge-start,
.photo-filmstrip-item.is-edge-end {
    position: relative;
}

.photo-filmstrip-item.is-edge-start::after,
.photo-filmstrip-item.is-edge-end::after {
    content: "";
    position: absolute;
    inset: 0;
    background-image: linear-gradient(to left, var(--sp-glass-overlay-edge-veil-inner), var(--sp-glass-overlay-edge-veil-outer));
    pointer-events: none;
}

.photo-filmstrip-item.is-edge-end::after {
    background-image: linear-gradient(to right, var(--sp-glass-overlay-edge-veil-inner), var(--sp-glass-overlay-edge-veil-outer));
}

/* Mobile : pas de flèches de navigation — on change de photo au swipe et par le filmstrip
   (DESIGNAPP, « Vue photo »). Les flèches restent sur desktop, où il n'y a pas de swipe. */
@media (max-width: 767.98px) {
    .photo-nav-arrow {
        display: none;
    }
}

/* Swipe hint animation */
.swipe-hint {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 20;
    pointer-events: none;
    animation: swipe-hint-fade 3s ease forwards;
}

.swipe-hint-hand {
    font-size: 2rem;
    animation: swipe-hint-move 1.5s ease-in-out 2;
}

@keyframes swipe-hint-move {
    0% { transform: translateX(30px); opacity: 0.8; }
    50% { transform: translateX(-30px); opacity: 1; }
    100% { transform: translateX(30px); opacity: 0.8; }
}

@keyframes swipe-hint-fade {
    0% { opacity: 1; }
    80% { opacity: 1; }
    100% { opacity: 0; }
}

/* Text truncation */
/* Le dépliement est instantané : une transition vers `max-height: none` ne s'interpole pas.
   Pour l'animer un jour, passer le contenu en grid (0fr → 1fr), ce qui demande un wrapper. */
.text-truncate-content {
    max-height: 4.5em;
    overflow: hidden;
}

.text-truncate-content.text-truncate-expanded {
    max-height: none;
}

/* Character counter */

.char-counter {
    font-size: 0.85rem;
    margin-top: 4px;
    display: block;
    text-align: right;
}

/* Image preview */

.image-preview {
    max-height: 200px;
    object-fit: cover;
    border-radius: var(--bs-border-radius);
    margin-top: 0.5rem;
    width: 100%;
}

/* Suggestions d'organisateurs (maquette CREATE_EVENT › SEARCH) : carte blanche au coin de 24,
   logo rond de 40, nom en 16 semibold, « Ville · Sport » dessous, filet entre les lignes. */
.organizer-suggestions {
    position: absolute;
    top: calc(100% + var(--sp-space-2));
    left: 0;
    right: 0;
    z-index: 1050;
    padding: var(--sp-space-3) var(--sp-space-6);
    background-color: var(--sp-color-bg-surface);
    border-radius: var(--sp-radius-2xl);
    box-shadow: var(--sp-shadow-suggest);
}

.organizer-suggestion {
    display: flex;
    align-items: center;
    gap: var(--sp-space-3);
    margin: 0 calc(-1 * var(--sp-space-3));
    padding: 0 var(--sp-space-3);
    border-radius: var(--sp-radius-md);
    cursor: pointer;
}

.organizer-suggestion:hover {
    background-color: var(--sp-color-bg-cream);
}

.organizer-suggestion-text {
    display: flex;
    flex-direction: column;
    gap: var(--sp-space-1);
    flex: 1 1 auto;
    min-width: 0;
    padding: var(--sp-space-3) 0;
}

.organizer-suggestion + .organizer-suggestion .organizer-suggestion-text {
    border-top: var(--sp-border-width-default) solid var(--sp-color-border-on-white);
}

.organizer-suggestion-name {
    font-size: var(--sp-font-size-h4);
    font-weight: var(--sp-font-weight-title);
    line-height: 19px;
    letter-spacing: var(--sp-font-tracking-tight);
    color: var(--sp-color-text-default);
}

.organizer-suggestion-meta {
    font-size: var(--sp-font-size-label);
    font-weight: var(--sp-font-weight-body);
    line-height: 17px;
    letter-spacing: var(--sp-font-tracking-tight);
    color: var(--sp-color-text-meta);
}

.organizer-avatar,
.organizer-avatar-placeholder {
    width: 40px;
    height: 40px;
    flex-shrink: 0;
    border-radius: var(--sp-radius-full);
    border: var(--sp-border-width-default) solid var(--sp-color-border-on-white);
}

.organizer-avatar {
    object-fit: contain;
    background-color: var(--sp-color-bg-surface);
}

.organizer-avatar-placeholder {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background-color: var(--sp-color-bg-sunken);
    font-size: var(--sp-font-size-label);
    font-weight: var(--sp-font-weight-title);
    color: var(--sp-color-text-brown);
}

/* Trix editor */

.photographer-layout trix-editor,
.club-layout trix-editor {
    min-height: 150px;
    background-color: var(--sp-color-bg-grey);
    border: 1px solid var(--sp-color-bg-grey);
    border-radius: var(--bs-border-radius);
    padding: 12px;
}

.photographer-layout trix-editor:focus,
.club-layout trix-editor:focus {
    background-color: var(--sp-color-bg-surface);
    border-color: var(--sp-color-border-focus);
    box-shadow: var(--sp-shadow-ring);
}

.photographer-layout trix-toolbar,
.club-layout trix-toolbar {
    background-color: var(--sp-color-bg-surface);
    border: 1px solid var(--sp-color-border-default);
    border-radius: var(--bs-border-radius);
    padding: 4px;
    margin-bottom: 8px;
}

/* Deux crans de plus que la feuille de Trix, chargée APRÈS la nôtre : à spécificité égale, son
   filet #CCC l'emportait. */
trix-toolbar .trix-button-row .trix-button-group {
    margin-bottom: 0;
    border: none;
}

trix-toolbar .trix-button {
    border: none;
    border-radius: 4px;
}

trix-toolbar .trix-button:hover {
    background-color: var(--sp-color-bg-grey);
}

trix-toolbar .trix-button.trix-active {
    background-color: var(--sp-color-border-default);
}

/* Organizer mention box */

.organizer-mention-box {
    max-height: 120px;
    overflow-y: auto;
}

/* La tuile cochée d'un dépôt prend l'anneau orange (fiche photo-gallery, state `selected`) : la
   sélection se lit sur l'objet pris, pas seulement sur sa case — blanche à filet clair, celle-ci
   se perd sur une photographie. */
.photo-pick:has(.photo-pick-input:checked) .ratio{
    outline: 3px solid var(--sp-color-accent-selected);
    outline-offset: 2px;
}

/* Étape « Album » du dépôt (DESIGNAPP, « Le parcours a cinq étapes nommées ») : une carte par
   journée, dépliée quand c'est elle qu'on choisit. Sélection ink, comme tout le parcours. */
.album-days{
    display: flex;
    flex-direction: column;
    gap: var(--sp-space-3);
}

.album-day{
    border: 1px solid var(--sp-color-border-on-white);
    border-radius: var(--sp-radius-xl);
    padding: var(--sp-space-3) var(--sp-space-4);
}

.album-day.is-open{
    border-color: var(--sp-color-action-primary);
}

.album-day-head{
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-space-3);
}

.album-day-label{
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: var(--sp-space-2);
    min-width: 0;
    cursor: pointer;
}

.album-day-name{
    font-weight: var(--sp-font-weight-bold);
}

.album-day-meta{
    font-size: var(--sp-font-size-label);
    color: var(--sp-color-text-muted);
}

.album-day-controls{
    display: flex;
    align-items: center;
    gap: var(--sp-space-2);
    flex-shrink: 0;
}

.album-day-panel{
    margin-top: var(--sp-space-3);
    padding-top: var(--sp-space-3);
    border-top: 1px solid var(--sp-color-border-on-white);
}

.album-day-hint{
    font-size: var(--sp-font-size-label);
    color: var(--sp-color-text-muted);
    margin-bottom: var(--sp-space-3);
}

/* La ligne d'un album est une option (fiche radio, « La même anatomie sert les options »), à
   ceci près que son libellé est un élément à part : la ligne peut porter un « Supprimer », qui
   n'aurait rien à faire dans un <label>. */
.album-row .album-row-label{
    cursor: pointer;
}

.album-row-lock{
    display: inline-flex;
    vertical-align: -2px;
    margin-left: var(--sp-space-1);
}

/* Panneau Albums (DESIGNAPP, maquette ALBUMS) : une journée est une carte crème qui se déplie.
   Dépliée, elle se cerne de brun et sa liste s'ouvre dessous dans un cadre au filet crème. */
.album-panel{
    display: flex;
    flex-direction: column;
    gap: var(--sp-space-4);
}

.album-group-head{
    display: flex;
    align-items: flex-start;
    gap: var(--sp-space-2);
    min-height: 63px;
    padding: 11px var(--sp-space-3) 11px var(--sp-space-4);
    border: 1px solid transparent;
    border-radius: var(--sp-radius-lg);
    background-color: var(--sp-color-bg-cream);
    box-shadow: var(--sp-shadow-sm);
}

.album-group-head:has(.album-group-toggle[aria-expanded="true"]){
    border-color: var(--sp-color-border-brown);
    border-radius: var(--sp-radius-md);
    box-shadow: none;
}

.album-group-toggle{
    display: flex;
    align-items: flex-start;
    gap: var(--sp-space-2);
    flex: 1;
    min-width: 0;
    padding: 0;
    border: 0;
    background: none;
    text-align: left;
    color: var(--sp-color-text-default);
}

/* Chevron de 12px calé sur la ligne du titre ; déplié, il pointe vers le bas */
.album-group-chevron{
    display: inline-flex;
    flex-shrink: 0;
    align-items: center;
    height: 22px;
    padding-top: 3px;
    transition: transform .2s ease;
}

.album-group-toggle[aria-expanded="true"] .album-group-chevron svg{
    transform: rotate(90deg);
}

.album-group-text{
    display: flex;
    flex-direction: column;
    gap: 1px;
    min-width: 0;
    padding-top: 3px;
}

.album-group-title{
    font-size: var(--sp-font-size-h4);
    font-weight: var(--sp-font-weight-title);
    line-height: 19px;
    letter-spacing: var(--sp-font-tracking-tight);
}

.album-group-meta{
    font-size: var(--sp-font-size-meta);
    font-weight: var(--sp-font-weight-body);
    line-height: 16px;
    letter-spacing: var(--sp-font-tracking-meta);
    color: var(--sp-color-text-meta);
}

.album-group-meta strong{
    font-weight: var(--sp-font-weight-title);
}

.album-group-head .filter-row-switch{
    padding-top: 2px;
}

.filter-row-meta{
    display: block;
    font-size: var(--sp-font-size-meta);
    color: var(--sp-color-text-muted);
}

/* La liste : cadre au filet crème à 9px de sa journée, noms alignés sur la date (34px),
   lignes de 39px, filet d'un demi-pixel entre deux */
.album-group-list .filter-list{
    margin-top: 9px;
    padding: var(--sp-space-3) var(--sp-space-3) 7px 36px;
    border: 1px solid var(--sp-color-border-cream);
    border-radius: var(--sp-radius-md);
}

.album-panel .filter-row,
.album-panel .filter-list-single .filter-row + .filter-row:has(> [type="checkbox"]){
    align-items: flex-start;
    min-height: 39px;
    padding: 0;
}

.album-panel .filter-row + .filter-row{
    margin-top: var(--sp-space-2);
    padding-top: var(--sp-space-2);
    border-top: 0.5px solid var(--sp-color-border-default);
    min-height: 47px;
}

.album-panel .filter-row-label{
    display: flex;
    flex-direction: column;
    gap: var(--sp-space-1);
}

.album-panel .filter-row-name{
    font-size: var(--sp-font-size-h4);
    font-weight: var(--sp-font-weight-title);
    line-height: 19px;
}

.album-panel .filter-row-meta{
    font-weight: var(--sp-font-weight-body);
    line-height: 16px;
    letter-spacing: var(--sp-font-tracking-meta);
    color: var(--sp-color-text-meta);
}

.album-panel .filter-row-check:not(:checked){
    border-color: var(--sp-color-border-on-white);
    background-color: var(--sp-color-border-on-white);
}

.filter-row--child,
.album-panel .filter-row--child{
    padding-left: var(--sp-space-4);
}

/* Une journée à venir : fermée, écrite en clair (maquette : D3CDC3), interrupteur absent */
.album-group--future .album-group-toggle,
.album-group--future .album-group-meta,
.album-group--future .filter-row-name,
.album-group--future .filter-row-meta{
    color: var(--sp-color-border-cream);
}

.album-delete{
    background: none;
    border: 0;
    padding: 0;
    font: inherit;
    color: inherit;
    text-decoration: underline;
}

/* Un album qu'on VA créer : le pointillé dit l'attente (DESIGNAPP, « une zone AU REPOS n'est
   pas une zone EN ATTENTE »), et il est orange parce qu'il ouvre le seul geste de l'étape qui
   crée quelque chose. */
.album-create{
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--sp-space-2);
    width: 100%;
    margin-top: var(--sp-space-4);
    padding: var(--sp-space-3);
    border: 1px dashed var(--sp-color-accent-selected);
    border-radius: var(--sp-radius-lg);
    background: transparent;
    color: var(--sp-color-accent-selected);
    font-size: var(--sp-font-size-label);
    font-weight: var(--sp-font-weight-bold);
}

.album-create:hover,
.album-create:focus-visible{
    background-color: var(--sp-color-bg-cream);
}

/* Un album (ou un évènement) protégé : la demande de mot de passe prend la place de la frise
   (fiche timeline, maquette « Mot de passe ») — 23px d'un élément à l'autre */
.album-unlock{
    display: flex;
    flex-direction: column;
    gap: 23px;
    max-width: 420px;
    padding: 18px 18px 0;
    border-radius: var(--sp-radius-lg);
    background-color: var(--sp-color-bg-default);
    box-shadow: var(--sp-shadow-sm);
}

.album-unlock-title{
    margin: 0;
    font-size: var(--sp-font-size-h3);
    font-weight: var(--sp-font-weight-title);
    line-height: 24px;
    letter-spacing: var(--sp-font-tracking-tighter);
    color: var(--sp-color-text-default);
}

.album-unlock-recap{
    position: relative;
    overflow: hidden;
    border-radius: var(--sp-radius-lg);
    color: var(--sp-color-text-inverse);
}

.album-unlock-cover{
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.album-unlock-recap-body{
    position: relative;
    display: flex;
    flex-direction: column;
    gap: 6px;
    padding: 14px;
    background-color: var(--sp-color-overlay-scrim);
}

.album-unlock-sport,
.album-unlock-path{
    display: flex;
    align-items: center;
    gap: var(--sp-space-1);
    font-size: var(--sp-font-size-meta);
    line-height: 16px;
    letter-spacing: var(--sp-font-tracking-meta);
}

.album-unlock-sport{
    font-weight: var(--sp-font-weight-title);
}

.album-unlock-path{
    flex-wrap: wrap;
    gap: 6px;
    font-weight: var(--sp-font-weight-body);
}

.album-unlock-event{
    font-size: var(--sp-font-size-h4);
    font-weight: var(--sp-font-weight-title);
    line-height: 19px;
    letter-spacing: var(--sp-font-tracking-tight);
}

.album-unlock-album{
    display: inline-flex;
    align-items: center;
    gap: var(--sp-space-2);
    height: 30px;
    padding: 0 9px;
    border-radius: var(--sp-radius-md);
    font-size: var(--sp-font-size-body);
    font-weight: var(--sp-font-weight-title);
    line-height: 18px;
    letter-spacing: var(--sp-font-tracking-tight);
    color: inherit;
}

.album-unlock-notice{
    margin: 0;
    font-size: var(--sp-font-size-label);
    font-weight: var(--sp-font-weight-prose);
    line-height: 17px;
    letter-spacing: var(--sp-font-tracking-tight);
    color: var(--sp-color-text-default);
}

.album-unlock-form{
    display: flex;
    flex-direction: column;
    gap: var(--sp-space-2);
}

.album-unlock-field{
    position: relative;
    display: flex;
    align-items: center;
}

.album-unlock-field-icon{
    position: absolute;
    left: 14px;
    color: var(--sp-color-text-brown);
    pointer-events: none;
}

.album-unlock-field .form-control{
    height: 46px;
    padding: var(--sp-space-1) var(--sp-space-4) var(--sp-space-1) 42px;
    border-color: var(--sp-color-border-cream);
    border-radius: var(--sp-radius-md);
    font-weight: var(--sp-font-weight-body);
    letter-spacing: var(--sp-font-tracking-tight);
}

.album-unlock-field .form-control::placeholder{
    font-size: var(--sp-font-size-body);
    color: var(--sp-color-text-brown);
}

.album-unlock-error{
    margin: 0;
    font-size: var(--sp-font-size-meta);
    color: var(--sp-color-feedback-danger);
}

/* Le pied : filet à fond perdu, un seul bouton pleine largeur de 42px */
.album-unlock-foot{
    margin: 8px -18px 0;
    padding: var(--sp-space-6);
    border-top: 1px solid var(--sp-color-border-on-white);
}

.album-unlock-foot .btn{
    width: 100%;
    min-height: 42px;
    padding-top: 0;
    padding-bottom: 0;
    border-radius: var(--sp-radius-lg);
    font-size: var(--sp-font-size-body);
    font-weight: var(--sp-font-weight-title);
    line-height: 20px;
}

/* Le quota est un CADRE, comme les astuces qui lui font face (DESIGNAPP) : filet, radius.2xl,
   aucun aplat — la maquette le dessine ainsi dans le parcours de dépôt COMME sur le tableau de
   bord, où il est le seul bloc de sa colonne à ne pas être une carte pleine. La
   maquette lui donne un filet gris FROID là où elle en donne un chaud aux astuces, pour un même
   rôle sur un même fond ; c'est elle qui fait foi ici, on la suit à la lettre. */
.quota-card{
    --bs-card-spacer-y: var(--sp-space-4);
    --bs-card-spacer-x: var(--sp-space-6);
    background-color: transparent;
    box-shadow: none;
    border: var(--bs-border-width) solid var(--sp-color-border-on-white);
    border-radius: var(--sp-radius-2xl);
    padding-bottom: 14px;
}

/* Ce qui borne le dépôt, dans la colonne gauche : les photos déjà en ligne contre le plafond.
   Jauge Progress variant `quota` (fiche progress) : remplissage ink sur piste grise, comme la
   maquette — l'orange est déjà pris, à trois centimètres de là, par le bouton de dépôt. Le rayon
   de 4px de la maquette et notre `radius.full` donnent le même dessin sur une barre de 8. */
.quota-progress{
    height: 8px;
    border-radius: var(--sp-radius-full);
    background-color: var(--sp-color-bg-grey-strong);
}

.quota-progress .progress-bar{
    border-radius: var(--sp-radius-full);
    background-color: var(--sp-color-bg-dark);
}

.quota-progress--alert .progress-bar{
    background-color: var(--sp-color-feedback-danger);
}

/* Le compte se lit en 13/16 bold (maquette) : le nombre porte, l'unité accompagne. */
.quota-figures{
    display: flex;
    justify-content: space-between;
    gap: var(--sp-space-3);
    margin-top: var(--sp-space-2);
    font-size: var(--sp-font-size-meta);
    font-weight: var(--sp-font-weight-bold);
    line-height: 16px;
    letter-spacing: var(--sp-font-tracking-meta);
    color: var(--sp-color-text-muted);
}

.quota-figures > span:last-child{
    color: var(--sp-color-text-meta);
}

.quota-figures strong{
    color: var(--sp-color-text-default);
}

/* Étape « Dossards » : le badge qui recommande, avec son étoile. */
.bib-recommended{
    display: inline-flex;
    align-items: center;
    gap: var(--sp-space-1);
}

.bib-fee{
    font-size: var(--sp-font-size-body);
}

/* Étape « Visibilité » de la création : une option réservée se voit, désactivée, avec sa mention. */
.visibility-row--locked .option-row-label{
    opacity: .55;
}

.visibility-pro{
    display: inline-flex;
    align-items: center;
    gap: var(--sp-space-1);
    margin-left: var(--sp-space-2);
    padding: 2px var(--sp-space-2);
    border: 1px solid var(--sp-color-border-on-white);
    border-radius: var(--sp-radius-full);
    font-size: var(--sp-font-size-meta);
    color: var(--sp-color-text-muted);
}

/* Vue photo : le temps restant en ligne, jauge Progress variant default (fiche progress) —
   piste pêche, remplissage orange, 8px, sous le titre de sa ligne d'information. */
.photo-lifetime{
    height: 8px;
    margin-top: var(--sp-space-2);
    margin-right: 40px;
    max-width: 320px;
    border-radius: var(--sp-radius-full);
    background-color: var(--sp-color-accent-soft);
}

.photo-lifetime .progress-bar{
    border-radius: var(--sp-radius-full);
    background-color: var(--sp-color-accent-selected);
}

/* =====================================================================================
   Retours client V2 (RETOUR_SPICTO_V2) : les valeurs que le client a données en clair.
   Ce qui suit renvoie à chaque fois à la fiche du DS concernée ; ce qui n'y est pas
   encore (bouton xs, compteur d'onglet, chevron de chip) y est signalé comme retour.
   ===================================================================================== */

/* --- Page login (maquette « Page login ») ------------------------------------------- */
/* Sur mobile, la page entière est la surface : la carte se fond dans le crème de la page. */
@media (max-width: 991.98px) {
    .login-card{
        --bs-card-bg: transparent;
        --bs-card-spacer-x: var(--sp-space-4);
        --bs-card-spacer-y: var(--sp-space-4);
        box-shadow: none;
    }
}

/* Valeurs de la maquette « Page login » (Figma 1806:10438) : en-tête de 77px, titre 28px
   semibold serré, accroche brune, étiquette 16px, champ et boutons de 52px au rayon xl. */
.login-head{
    min-height: 77px;
    margin-bottom: 14px;
}

.login-head .brand{
    width: 123px;
    height: 23px;
}

.login-title{
    font-size: var(--sp-font-size-h2);
    font-weight: var(--sp-font-weight-title);
    letter-spacing: var(--sp-font-tracking-tighter);
    line-height: 1.2;
    margin-bottom: 23px;
}

.login-toggle{
    margin-bottom: 23px;
}

.login-hint{
    margin-bottom: var(--sp-space-4);
    color: var(--sp-color-text-brown);
    font-size: var(--sp-font-size-body);
    font-weight: var(--sp-font-weight-title);
    letter-spacing: var(--sp-font-tracking-tight);
}

.login-label{
    margin-bottom: var(--sp-space-4);
    font-size: var(--sp-font-size-16);
    font-weight: var(--sp-font-weight-title);
    letter-spacing: var(--sp-font-tracking-tight);
}

.login-input{
    height: 52px;
    padding-left: var(--sp-space-4);
    border-color: var(--sp-color-border-cream);
    border-radius: var(--sp-radius-xl);
    font-size: var(--sp-font-size-label);
    font-weight: var(--sp-font-weight-body);
}

.login-input::placeholder{
    color: var(--sp-color-text-brown);
    letter-spacing: var(--sp-font-tracking-tight);
}

.login-card .btn-marketing{
    height: 52px;
    border-radius: var(--sp-radius-xl);
    font-size: var(--sp-font-size-body);
    font-weight: var(--sp-font-weight-title);
    letter-spacing: var(--sp-font-tracking-tight);
}

.login-help{
    color: var(--sp-color-text-default);
}

/* Desktop (maquette LOGIN 1512) : l'accroche en 64/77 sur 621px, sa phrase en 32/39 ; la carte
   fait 579px au rayon 36, gouttière de 48 (19 en haut, 40 en bas), posée sur la photo */
@media (min-width: 992px) {
    .login-pitch{
        max-width: 621px;
    }

    .login-pitch .h1-xl{
        margin-bottom: 10px;
    }

    .login-pitch .lead-xl{
        margin-bottom: 0;
    }

    .login-card{
        --bs-card-spacer-x: var(--sp-space-12);
        width: 579px;
        max-width: 100%;
        margin-left: auto;
        padding-top: 19px;
        padding-bottom: var(--sp-space-10);
        border: 0;
        border-radius: var(--sp-radius-3xl);
        box-shadow: var(--sp-shadow-float);
    }
}

.login-tm{
    font-size: .45em;
    top: -.9em;
}

/* « ou », un filet border.cream de part et d'autre, brun semibold (Figma) */
.login-or{
    display: flex;
    align-items: center;
    gap: 10px;
    margin: var(--sp-space-3) 0;
    padding: 10px 0;
    color: var(--sp-color-text-brown);
    font-size: var(--sp-font-size-body);
    font-weight: var(--sp-font-weight-title);
    letter-spacing: var(--sp-font-tracking-tight);
}

.login-or::before,
.login-or::after{
    content: '';
    flex: 1;
    border-top: 1px solid var(--sp-color-border-cream);
}

.login-legal{
    font-size: var(--sp-font-size-12);
    font-weight: var(--sp-font-weight-body);
    letter-spacing: var(--sp-font-tracking-tight);
}

.login-legal a{
    color: inherit;
}

/* Le bouton Google au gabarit des autres boutons : 52px, rayon xl, filet fin de .75px
   (Figma 1806:11021), libellé 15px semibold ink, logo de 22px */
.gsi-material-button{
    height: 52px;
    border-radius: var(--sp-radius-xl);
    border-width: .75px;
    font-size: var(--sp-font-size-body);
    font-weight: var(--sp-font-weight-title);
    letter-spacing: var(--sp-font-tracking-tight);
    color: var(--sp-color-text-default);
    border-color: var(--sp-color-grey-700);
    font-family: var(--sp-font-family-base), sans-serif;
}

/* --- Bouton xs (retour client : CTA de section à 26px) ------------------------------- */
/* Plus court que le sm de la fiche button : l'en-tête d'une section de la page évènement
   (« Me prévenir », « Rejoindre ») ne pèse pas un bouton de 32px. À porter dans la fiche. */
/* La puce qui accompagne un titre de section sur la page d'un évènement sans photos (maquette :
   « Publier mes photos », « Me prévenir », « Rejoindre ») : 26px, radius.sm, gouttière 4/8,
   libellé 13/16 medium et glyphe de 14. Elle n'existe que là. */
.btn-xs{
    --bs-btn-padding-x: var(--sp-space-2);
    --bs-btn-padding-y: 4px;
    --bs-btn-font-size: var(--sp-font-size-meta);
    --bs-btn-border-radius: var(--sp-radius-sm);
    gap: 4px;
    min-height: 26px;
    line-height: 16px;
    /* 13px : c'est la taille de la méta, `.btn` pose tight pour tout le monde. */
    letter-spacing: var(--sp-font-tracking-meta);
}

/* Le nombre qui suit un titre de section (« Photographes (3) ») : un cran plus petit */
.sec-header-title-count{
    font-size: var(--sp-font-size-label);
    font-weight: var(--sp-font-weight-body);
    color: var(--sp-color-text-muted);
}

/* --- Page évènement : le hero sur mobile (retour client) ------------------------------ */
@media (max-width: 991.98px) {
    /* 180px de haut au minimum, coin 16px, ombre 0 0 4 à 25 %, gouttière 16px, et un voile qui
       va de 32 % en haut à plein en bas : la photo se lit en haut, le texte en bas. La hauteur
       suit le contenu (retour du 06/11) : un titre sur deux lignes poussait le sport sous le
       bouton retour. */
    .event-highlighted-header--page{
        height: auto;
        min-height: 180px;
        border-radius: var(--sp-radius-lg);
        box-shadow: var(--sp-shadow-photo);
    }

    .event-highlighted-header--page::after{
        display: none;
    }

    /* En flux et étiré : le scrim fait la hauteur de la carte et la pousse quand le texte
       déborde ; le haut reste réservé aux actions de coin (space.16, comme sur desktop). */
    .event-highlighted-header--page .event-highlighted-scrim{
        position: relative;
        flex: 1 1 auto;
        justify-content: flex-end;
        padding: var(--sp-space-16) var(--sp-space-4) var(--sp-space-4);
        background: linear-gradient(to bottom, rgba(0, 0, 0, .32) 0%, rgba(0, 0, 0, 1) 100%);
    }

    /* Lieu, état, date : la ligne se replie plutôt que de se tronquer — avec ses points
       séparateurs à 8px (retour client) une plage de dates n'y tenait plus, et « … » à la
       place de la date ne dit rien */
    .event-highlighted-header--page .event-highlighted-meta{
        white-space: normal;
    }

    /* Le retour se distingue des actions : disque clair sur la photo */
    .event-highlighted-header--page .event-hero-back{
        background: rgba(255, 255, 255, .92);
        border-color: transparent;
        color: var(--sp-color-text-default);
    }

    .event-highlighted-header--page.mb-4{
        margin-bottom: var(--sp-space-3) !important;
    }
}

/* Le « … » du hero : son menu s'ancre au groupe de verre, pas à un bouton nu */
.glass-group .dropdown{
    display: inline-flex;
}

/* Liens de l'organisateur dans la Dialog « Informations » : des chips (fiche chip) */
.event-info-links a{
    display: inline-flex;
    align-items: center;
    height: 32px;
    padding: 0 var(--sp-space-3);
    border-radius: var(--sp-radius-md);
    background-color: var(--sp-color-bg-cream);
    color: var(--sp-color-text-default);
    font-size: var(--sp-font-size-meta);
}

/* --- Frise (fiche timeline) ------------------------------------------------------------ */
/* Le compteur : 24px de haut, 12px de texte ; sous un filtre, « 3 / 40 » d'une seule couleur,
   seul le numérateur en gras (retour client). */
.timeline-count{
    display: inline-flex;
    align-items: center;
    gap: .3em;   /* en flex, l'espace du texte ne compte plus : « 14 Photos », pas « 14Photos » */
    height: 24px;
    font-size: var(--sp-font-size-12);
}

.timeline-count-total{
    color: inherit;
}

/* Le bouton qui déplie la journée, sous sa grille */
.timeline-more{
    margin-top: var(--sp-space-3);
}

/* L'extrémité de la frise respire (retour client) */
.timeline-item:last-child{
    padding-bottom: var(--sp-space-4);
}

/* Glyphes de fin plus épais (retour client) : 14px, `check-bold` */
.timeline-end-glyph{
    width: 14px;
    height: 14px;
    margin-top: calc((1lh - 14px) / 2);
}

/* L'encart d'attente : 65px de haut, une ligne de texte, texte brun sur le crème et un
   pointillé chaud plus espacé (retour client). 24px au-dessus et au-dessous du texte (maquette
   NO_PHOTOS) : sur deux lignes, l'encart fait 82px. */
.event-empty-panel,
.timeline-awaiting{
    min-height: 65px;
    padding: var(--sp-space-6) var(--sp-space-4);
    border: 0;
    /* Tirets de 4 sur 4, comme la maquette (composant NO_PHOTOS) */
    background-image: repeating-linear-gradient(90deg, var(--sp-color-border-cream) 0 4px, transparent 4px 8px),
        repeating-linear-gradient(180deg, var(--sp-color-border-cream) 0 4px, transparent 4px 8px),
        repeating-linear-gradient(90deg, var(--sp-color-border-cream) 0 4px, transparent 4px 8px),
        repeating-linear-gradient(180deg, var(--sp-color-border-cream) 0 4px, transparent 4px 8px);
    background-size: 100% 1px, 1px 100%, 100% 1px, 1px 100%;
    background-position: 0 0, 100% 0, 0 100%, 0 0;
    background-repeat: no-repeat;
}

.event-empty-panel-text,
.timeline-awaiting{
    color: var(--sp-color-text-brown);
    font-size: var(--sp-font-size-label);
    line-height: 17px;
}

/* Le message d'une journée ou d'une sélection vide tient dans 275px (NO_PHOTOS) ; celui de
   l'écran « sans photos » garde sa ligne (295px dans la maquette) */
.event-empty-panel-text > span,
.timeline-awaiting > span{
    display: inline-block;
    max-width: 275px;
}

/* Carte d'un photographe inscrit : une pilule (maquette), le « Moi » centré à droite */
.event-photographer-card{
    border-radius: var(--sp-radius-full);
    padding: var(--sp-space-2) var(--sp-space-4) var(--sp-space-2) var(--sp-space-2);
}

.event-photographer-card--me{
    background-color: var(--sp-color-bg-sunken);
    border-color: transparent;
}

.event-photographer-me{
    top: 50%;
    transform: translateY(-50%);
    right: var(--sp-space-4);
}

/* --- Rail Live et section « En attente » (retour client) ------------------------------- */
/* Mobile : tuiles cernées du halo photographique, et 4px réservés au-dessus pour que le
   défilement ne le rogne pas. Desktop : la carte blanche les détache, seul le survol les
   élève (fiche event-rail). */
@media (max-width: 991.98px) {
    .event-rail{
        margin-top: -4px;
        padding-top: 4px;
    }

    .event-rail .event-highlighted:not(:focus-visible){
        box-shadow: var(--sp-shadow-photo);
    }
}

/* Le haut de la tuile respire : les chips ne touchent plus le bord */
.event-rail .event-highlighted-top{
    padding: var(--sp-space-4);
}

.event-rail .event-highlighted-scrim{
    gap: var(--sp-space-1);
}

/* Le point d'un badge temporel se centre sur son mot */
.event-highlighted .badge{
    display: inline-flex;
    align-items: center;
}

/* Pastilles en nuances de gris (maquette) : l'accent reste à la chip et au badge de date */
.rail-dot{
    background-color: var(--sp-color-border-on-white);
}

.rail-dot.active{
    background-color: var(--sp-color-text-muted);
}

/* Le titre de section en ink plein (« Le Live », ALMOST BLACK sur la maquette) */
.sec-header-title{
    color: var(--sp-color-text-default);
}

/* Sur mobile, le rail et la rangée de chips vont bord à bord (retour client) : ils sortent
   des gouttières du conteneur et les reprennent en retrait interne, pour que la première
   carte s'aligne sur le contenu et que la dernière file jusqu'au bord. */
@media (max-width: 991.98px) {
    .event-rail-section,
    .tab-bar-block .filter-chips{
        margin-left: calc(var(--bs-gutter-x, 1.5rem) * -.5);
        margin-right: calc(var(--bs-gutter-x, 1.5rem) * -.5);
    }

    .event-rail,
    .tab-bar-block .filter-chips{
        padding-left: calc(var(--bs-gutter-x, 1.5rem) * .5);
        padding-right: calc(var(--bs-gutter-x, 1.5rem) * .5);
        scroll-padding-left: calc(var(--bs-gutter-x, 1.5rem) * .5);
    }
}

/* « En attente de photo » : un filet coiffe la section, les lignes se resserrent, et la
   dernière ne porte pas de filet — l'encart publicitaire suit (retour client) */
.awaiting-header{
    padding-top: var(--sp-space-4);
    border-top: 1px solid var(--sp-color-border-default);
}

.awaiting-list .list-item{
    padding-top: var(--sp-space-3);
    padding-bottom: var(--sp-space-3);
}

.awaiting-list .list-item-grid > .col:last-child .list-item{
    border-bottom: 0;
}

/* --- Liquid glass (retour client, DESIGNAPP « verre dépoli ») ------------------------------
   Le verre existant (flou, saturation, liseré) reçoit deux choses : une LENTILLE — le fond
   se déforme légèrement sous la surface, par le filtre SVG #spicto-liquid-glass posé sur une
   couche à part, que les moteurs sans filtre en backdrop ignorent sans rien perdre — et un
   RELIEF : une arête claire en haut à gauche, un reflet bas, une ombre qui décolle. */
.badge-glass,
.btn-glass,
.glass-group,
.event-highlighted .badge-live{
    position: relative;
    isolation: isolate;
    overflow: hidden;
}

.badge-glass::before,
.btn-glass::before,
.glass-group::before,
.event-highlighted .badge-live::before{
    content: '';
    position: absolute;
    inset: 0;
    z-index: -1;
    border-radius: inherit;
    backdrop-filter: url(#spicto-liquid-glass);
    -webkit-backdrop-filter: url(#spicto-liquid-glass);
    pointer-events: none;
}

/* Le liseré (glass.overlay.rim) : 1px de lumière posé en masque sur le bord — arête haute
   vive, flancs éteints, arête basse rallumée à droite */
.badge-glass::after,
.btn-glass::after,
.glass-group::after,
.event-highlighted .badge-live::after{
    content: '';
    position: absolute;
    inset: 0;
    padding: 1px;
    border-radius: inherit;
    background: var(--sp-glass-overlay-rim);
    -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    -webkit-mask-composite: xor;
    mask: linear-gradient(#000 0 0) content-box exclude, linear-gradient(#000 0 0);
    pointer-events: none;
}

/* L'échéance qui ALERTE (cinq jours ou moins) reste un verre, teinté du rouge clair (retour
   client : « rouge liquid glass ») : même flou, même liseré, même décollement que le compteur
   d'en face — seul le fond change. Coins de 8px, comme le badge de date. */
.event-highlighted .badge-danger{
    position: relative;
    isolation: isolate;
    overflow: hidden;
    background-color: var(--sp-glass-overlay-danger);
    backdrop-filter: blur(var(--sp-glass-overlay-blur));
    -webkit-backdrop-filter: blur(var(--sp-glass-overlay-blur));
    box-shadow: var(--sp-glass-overlay-shadow);
}

.event-highlighted .badge-danger::before{
    content: '';
    position: absolute;
    inset: 0;
    z-index: -1;
    border-radius: inherit;
    backdrop-filter: url(#spicto-liquid-glass);
    -webkit-backdrop-filter: url(#spicto-liquid-glass);
    pointer-events: none;
}

.event-highlighted .badge-danger::after{
    content: '';
    position: absolute;
    inset: 0;
    padding: 1px;
    border-radius: inherit;
    background: var(--sp-glass-overlay-rim);
    -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    -webkit-mask-composite: xor;
    mask: linear-gradient(#000 0 0) content-box exclude, linear-gradient(#000 0 0);
    pointer-events: none;
}

.event-highlighted .event-highlighted-top .badge.badge-danger,
.event-highlighted .event-highlighted-sport-line .badge.badge-danger{
    border: 0;
}

/* Le badge temporel orange est un APLAT plein : il garde le liseré, en pêche, et le
   décollement de la superposition ; pas de flou ni de lentille derrière un aplat. */
.event-highlighted .badge-live{
    background-color: var(--sp-color-accent-selected);
    box-shadow: var(--sp-glass-overlay-lift);
}

.event-highlighted .badge-live::before{
    content: none;
}

.event-highlighted .badge-live::after{
    background: var(--sp-glass-overlay-rim-warm);
}

.event-highlighted .badge-live svg{
    color: var(--sp-color-accent-soft);
}

/* Le liseré se pose au bord même du badge : pas de bordure transparente entre les deux */
.event-highlighted .event-highlighted-top .badge.badge-live,
.event-highlighted .event-highlighted-sport-line .badge.badge-live{
    border: 0;
}

.btn-glass,
.glass-group{
    box-shadow: var(--sp-glass-overlay-lift);
}

/* Le menu « … » du groupe sort de la pilule : l'overflow du verre ne doit pas le rogner */
.glass-group:has(.dropdown-menu.show){
    overflow: visible;
}

/* --- Recherche plein écran sur mobile (arbitrage client) --------------------------------
   Le conteneur du champ se déploie sur toute la fenêtre : la tête porte le champ et sa croix,
   une rangée de chips choisit la famille de résultats, la liste prend le reste et défile. */
@media (max-width: 991.98px) {
    .search-fullscreen-open{
        position: fixed;
        inset: 0;
        z-index: 1200;
        /* une grille : le champ et la croix sur la première ligne, les chips sur la seconde —
           sans déplacer le champ, dont les contrôleurs ne survivraient pas à un déplacement */
        display: grid;
        grid-template-columns: minmax(0, 1fr) auto;
        grid-template-rows: auto auto 1fr;
        column-gap: var(--sp-space-2);
        align-items: center;
        align-content: start;
        height: 100dvh;
        padding: var(--sp-space-3) var(--sp-space-4) 0;
        background-color: var(--sp-color-bg-default);
        overflow: hidden;
    }

    /* Sur le crème de l'écran, le verre n'a rien à filtrer (fiche search-bar) — et son
       backdrop-filter ferait de la barre le bloc conteneur du panneau fixe, qui s'y écraserait */
    .search-fullscreen-open > .search-bar{
        grid-column: 1;
        grid-row: 1;
        min-width: 0;
        background: var(--sp-color-bg-surface);
        backdrop-filter: none;
        -webkit-backdrop-filter: none;
        border: none;
        box-shadow: var(--sp-shadow-sm);
    }

    .search-fullscreen-close{
        grid-column: 2;
        grid-row: 1;
    }

    .search-fullscreen-tabs{
        grid-column: 1 / -1;
        grid-row: 2;
    }

    .search-fullscreen-close{
        display: inline-flex;
        align-items: center;
        justify-content: center;
        flex: 0 0 auto;
        width: var(--sp-control-icon-button);
        height: var(--sp-control-icon-button);
        padding: 0;
        border: 0;
        border-radius: var(--sp-radius-full);
        background-color: var(--sp-color-bg-surface);
        box-shadow: var(--sp-shadow-sm);
        color: var(--sp-color-text-default);
    }

    /* Les familles en chips (fiche chip) : la retenue en ink plein, comme un onglet filter */
    .search-fullscreen-tabs{
        display: flex;
        gap: var(--sp-space-2);
        padding: var(--sp-space-3) 0;
        overflow-x: auto;
        scrollbar-width: none;
        flex: 0 0 auto;
    }

    .search-fullscreen-tabs::-webkit-scrollbar{
        display: none;
    }

    .search-fullscreen-tab{
        flex: 0 0 auto;
        height: 36px;
        padding: 0 var(--sp-space-3);
        border: 0;
        border-radius: var(--sp-radius-md);
        background-color: var(--sp-color-bg-surface);
        box-shadow: var(--sp-shadow-sm);
        color: var(--sp-color-text-default);
        font-size: var(--sp-font-size-label);
        font-weight: var(--sp-font-weight-body);
        line-height: 17px;
        letter-spacing: var(--sp-font-tracking-tight);
        white-space: nowrap;
    }

    .search-fullscreen-tab.is-active{
        background-color: var(--sp-color-action-primary);
        color: var(--sp-color-text-inverse);
    }

    /* L'invite, et le message d'une famille vide : sous les chips, à la place de la liste —
       sur la ligne du premier titre de groupe, 16px sous les chips */
    .search-fullscreen-hint,
    .search-fullscreen-empty{
        grid-column: 1 / -1;
        grid-row: 3;
        align-self: start;
        padding-top: var(--sp-space-1);
    }

    .search-fullscreen-open .search-bar .ts-dropdown .no-results{
        padding-top: 0;
    }

    /* Tant qu'il n'y a rien à chercher : ni chips ni liste, l'invite seule */
    .search-fullscreen-open[data-search-state="idle"] .search-fullscreen-tabs,
    .search-fullscreen-open[data-search-state="idle"] .search-bar .ts-dropdown,
    .search-fullscreen-open[data-search-state="query"] .search-fullscreen-hint{
        display: none !important;
    }

    /* L'invite remplace les chips : elle se pose sous le champ, à 16px */
    .search-fullscreen-open[data-search-state="idle"] .search-fullscreen-hint{
        grid-row: 2;
        padding-top: var(--sp-space-4);
    }

    /* La liste n'est plus un panneau flottant : elle est la page, et elle défile */
    .search-fullscreen-open .ts-wrapper{
        position: static;
    }

    /* TomSelect pose top/left/width en ligne : on les écrase, la liste EST l'écran */
    .search-fullscreen-open .search-bar .ts-dropdown{
        position: fixed;
        left: 0 !important;
        right: 0 !important;
        /* sous la rangée de chips : gouttière, champ, puis la rangée et ses 12px de part et d'autre */
        top: calc(var(--sp-space-3) + 44px + var(--sp-space-3) + 36px + var(--sp-space-3)) !important;
        bottom: 0 !important;
        width: auto !important;
        height: auto !important;
        max-height: none !important;
        margin: 0;
        border-radius: 0;
        box-shadow: none;
        background: transparent;
        overflow-y: auto;
        padding: var(--sp-space-1) var(--sp-space-4) var(--sp-space-8);
    }

    .search-fullscreen-open .search-bar .ts-dropdown .ts-dropdown-content{
        max-height: none;
        padding: 0;
    }

    .search-fullscreen-open .search-suggestions{
        padding-left: 0;
        padding-right: 0;
    }

    /* Le premier titre de groupe se pose à 16px des chips, quelle que soit la famille */
    .search-fullscreen-open .search-suggestions-title--options{
        padding: 0;
    }

    .search-fullscreen-open .ts-dropdown:not(:has(.option)) .search-suggestions{
        padding-top: 0;
    }

    /* Une famille choisie : les autres se retirent */
    .search-fullscreen-open:not([data-search-category="all"]):not([data-search-category="events"]) .ts-dropdown-content,
    .search-fullscreen-open:not([data-search-category="all"]):not([data-search-category="events"]) .search-suggestions-title--options,
    .search-fullscreen-open[data-search-category="events"] .search-suggestions-section:not([data-category="events"]),
    .search-fullscreen-open[data-search-category="locations"] .search-suggestions-section:not([data-category="locations"]),
    .search-fullscreen-open[data-search-category="photographers"] .search-suggestions-section:not([data-category="photographers"]),
    .search-fullscreen-open[data-search-category="sports"] .search-suggestions-section:not([data-category="sports"]){
        display: none;
    }

    .search-fullscreen-open:not([data-search-category="all"]):not([data-search-category="events"]) .search-suggestions{
        border-top: 0;
        padding-top: 0;
    }
}

/* --- Cotes de la maquette mobile (Figma UI_V2, frames HOMEPAGE_LIVE_LIST_VIEW 1312:1221 et
   GALLERY EVENT 4116:14459). Figma n'a livré que la structure de ces deux frames : les
   tailles et les espacements. Polices et couleurs restent celles du DS. ------------------ */
@media (max-width: 991.98px) {
    /* Barre haute de 44px : logo 90×17 à gauche, actions de 36px à 12px l'une de l'autre */
    .topbar-front{
        min-height: 44px;
    }

    .topbar-actions{
        gap: var(--sp-space-3);   /* 12px entre avatar, menu et panier (Figma) */
    }

    .topbar-actions .btn-circle{
        width: 36px;
        height: 36px;
        min-width: 36px;
        min-height: 36px;
    }

    /* La recherche : 44px de haut, 12px au-dessus et au-dessous */
    .tab-bar-search{
        margin: var(--sp-space-3) 0;
    }

    /* Onglets jointifs, 10px sous la recherche. La pilule active prend le creux SOUTENU
       (retour client : BROWN_BORDER_LIGHT), le même que sur desktop. */
    .tab-bar-nav{
        --bs-nav-pills-link-active-bg: var(--sp-color-bg-sunken-strong);
        padding-top: 10px;
        gap: 0;
        /* Quand les compteurs allongent les onglets, la rangée défile au doigt au lieu de
           couper « À venir » (retour client) ; un onglet ne se comprime jamais sous son mot. */
        overflow-x: auto;
        scrollbar-width: none;
    }

    .tab-bar-nav::-webkit-scrollbar{
        display: none;
    }

    .tab-bar-block .tab-bar-nav .nav-item{
        flex: 1 0 auto;
    }

    /* Chips : 12px au-dessus, 14 en dessous */
    .tab-bar-block .filter-chips{
        padding-bottom: 2px;
    }

    /* Hero : disques de 40px, glyphes de 20 */
    .event-highlighted-header--page .event-hero-back,
    .event-highlighted-header--page .glass-group-item{
        width: 40px;
        height: 40px;
        min-width: 40px;
        min-height: 40px;
    }
}

/* Le chevron d'une chip : 10×6 sur la maquette */
.chip-filter-chevron svg{
    width: 10px;
    height: 10px;
}

/* Séparateur de méta (retour client) : le point s'écarte de 8px de ce qu'il sépare — l'espace
   d'une fonte n'en donnait que quatre, et « Dias, 44 · 25 Sept » se lisait d'un bloc. */
.dot-sep{
    display: inline-block;
    margin: 0 var(--sp-space-2);
}

/* « En attente de photo » : glyphe de 14 à 6px du titre, rangées dont le filet part du
   texte (88px : vignette 72 + gouttière 16), cloche de 14 */
.awaiting-header .sec-header-title{
    gap: 6px;
}

.awaiting-list .list-item .btn-circle svg{
    width: 14px;
    height: 14px;
}

/* --- Aperçu photo (retour client) : la carte garde sa hauteur pendant le chargement, et le
   dit ; une ombre la décolle de la page ------------------------------------------------ */
.photo-stage{
    box-shadow: var(--sp-shadow-photo);
}

.photo-stage.is-loading{
    background-color: var(--sp-color-bg-sunken);
}

.photo-stage.is-loading::after{
    content: '';
    position: absolute;
    top: 50%;
    left: 50%;
    width: 28px;
    height: 28px;
    margin: -14px 0 0 -14px;
    border: 3px solid var(--sp-color-border-cream);
    border-top-color: var(--sp-color-accent-selected);
    border-radius: var(--sp-radius-full);
    animation: photo-stage-spin .8s linear infinite;
}

@keyframes photo-stage-spin{
    to { transform: rotate(360deg); }
}

@media (prefers-reduced-motion: reduce) {
    .photo-stage.is-loading::after{
        animation: none;
    }
}

/* --- Frise : l'en-tête compact (retour client, « Scroll ») ---------------------------------
   Une pilule fixée sous le haut de l'écran, portée par une ombre : la journée qu'on regarde,
   et la flèche qui remonte. Elle n'existe que défilée. */
.timeline-sticky{
    position: fixed;
    top: var(--sp-space-3);
    left: 50%;
    z-index: 1030;
    display: flex;
    align-items: center;
    gap: var(--sp-space-2);
    padding: var(--sp-space-1) var(--sp-space-1) var(--sp-space-1) var(--sp-space-4);
    transform: translateX(-50%);
    border-radius: var(--sp-radius-full);
    background-color: var(--sp-color-bg-surface);
    box-shadow: var(--sp-shadow-lg);
    font-size: var(--sp-font-size-label);
    font-weight: var(--sp-font-weight-title);
    color: var(--sp-color-text-default);
    white-space: nowrap;
}

.timeline-sticky-top{
    width: 32px;
    height: 32px;
    min-width: 32px;
    min-height: 32px;
    background-color: var(--sp-color-bg-sunken);
    color: var(--sp-color-text-default);
}

.timeline-sticky-top:hover{
    background-color: var(--sp-color-action-primary);
    color: var(--sp-color-action-primary-text);
}

/* --- Filtre photographes : deux groupes (retour client) --------------------------------- */
.filter-group-title{
    margin: 0;
    padding: var(--sp-space-2) 0 var(--sp-space-1);
    font-size: var(--sp-font-size-meta);
    font-weight: var(--sp-font-weight-title);
    color: var(--sp-color-text-brown);
}

.filter-group-title--next{
    margin-top: var(--sp-space-2);
    border-top: 1px solid var(--sp-color-border-default);
    padding-top: var(--sp-space-3);
}

/* Un inscrit sans photo ne se coche pas : sa ligne se lit, elle ne se règle pas */
.filter-row--pending .filter-row-label{
    cursor: default;
}

.filter-row + .filter-group-title{
    border-top: 0;
}

/* --- Panneau Dossard (maquette CASE_DOSSARD, fiche timeline) : le champ propose, la carte
   sombre retient, la ligne « Voir … Avant et après » élargit ------------------------------ */
/* Le corps déborde la gouttière pour que l'ombre de la carte de suggestions ne soit pas
   rognée par son défilement */
.event-bib-search{
    display: flex;
    flex-direction: column;
    margin: 0 calc(-1 * var(--sp-space-6));
    padding: 7px var(--sp-space-6) 0;
}

.event-bib-search > *{
    flex-shrink: 0;
}

.bib-search-title{
    display: flex;
    align-items: center;
    min-height: 28px;
    margin: 0 0 var(--sp-space-1);
    font-size: var(--sp-font-size-h4);
    font-weight: var(--sp-font-weight-title);
    line-height: 19px;
    letter-spacing: var(--sp-font-tracking-tight);
    color: var(--sp-color-text-default);
}

.bib-search-field .form-control{
    height: 50px;
    padding-left: 42px;
    padding-right: var(--sp-space-4);
    font-weight: var(--sp-font-weight-body);
    letter-spacing: var(--sp-font-tracking-tight);
}

.bib-search-field .form-control::placeholder{
    font-size: var(--sp-font-size-body);
    color: var(--sp-color-text-brown);
}

.bib-search-field .input-search-icon{
    left: 14px;
    color: var(--sp-color-text-brown);
}

/* Les suggestions : une carte blanche, une ligne de 40px par dossard, filet en retrait de 52px */
.bib-suggestions{
    display: flex;
    flex-direction: column;
    gap: var(--sp-space-3);
    margin-top: var(--sp-space-2);
    padding: var(--sp-space-4);
    border-radius: var(--sp-radius-2xl);
    background-color: var(--sp-color-bg-surface);
    box-shadow: var(--sp-shadow-lg);
}

.bib-suggestion{
    position: relative;
    display: flex;
    align-items: center;
    gap: var(--sp-space-4);
    min-height: 40px;
    padding: 0;
    border: 0;
    background: none;
    text-align: left;
    color: var(--sp-color-text-default);
}

.bib-suggestion + .bib-suggestion::before{
    content: '';
    position: absolute;
    top: calc(var(--sp-space-3) / -2);
    left: 52px;
    right: var(--sp-space-1);
    border-top: 0.5px solid var(--sp-color-border-default);
}

.bib-suggestion:focus-visible{
    outline: 0;
    border-radius: var(--sp-radius-md);
    box-shadow: var(--sp-shadow-ring);
}

.bib-suggestion-tile{
    display: inline-flex;
    flex: 0 0 36px;
    align-items: center;
    justify-content: center;
    height: 36px;
    border-radius: var(--sp-radius-md);
    background-color: var(--sp-color-accent-soft);
    color: var(--sp-color-accent-selected);
}

.bib-suggestion-body,
.bib-card-body{
    display: flex;
    flex: 1;
    flex-direction: column;
    min-width: 0;
}

.bib-suggestion-body{
    gap: 5px;
}

.bib-suggestion-number,
.bib-card-number{
    font-size: var(--sp-font-size-h4);
    font-weight: var(--sp-font-weight-title);
    line-height: 19px;
    letter-spacing: var(--sp-font-tracking-tight);
}

.bib-suggestion-count,
.bib-card-count{
    font-size: var(--sp-font-size-meta);
    font-weight: var(--sp-font-weight-body);
    line-height: 16px;
    letter-spacing: var(--sp-font-tracking-meta);
}

.bib-suggestions-empty{
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--sp-space-2);
    min-height: 65px;
    margin: 0;
    border: 1px dashed var(--sp-color-border-default);
    border-radius: var(--sp-radius-lg);
    font-size: var(--sp-font-size-meta);
    line-height: 16px;
    color: var(--sp-color-text-brown);
}

/* Le dossard retenu : carte sombre de 63px, tuile pêche de 39 dans une case de 51 */
.bib-selected{
    display: flex;
    flex-direction: column;
    gap: var(--sp-space-2);
    margin: 25px 0 0;
}

.bib-card{
    display: flex;
    align-items: center;
    gap: var(--sp-space-3);
    min-height: 63px;
    padding: 6px var(--sp-space-6) 6px 6px;
    border-radius: var(--sp-radius-lg);
    background-color: var(--sp-color-bg-dark);
    color: var(--sp-color-text-inverse);
}

.bib-card-tile{
    display: inline-flex;
    flex: 0 0 51px;
    align-items: center;
    justify-content: center;
    height: 51px;
}

.bib-card-tile > span{
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 39px;
    height: 39px;
    border-radius: var(--sp-radius-sm);
    background-color: var(--sp-color-accent-soft);
    color: var(--sp-color-accent-selected);
}

.bib-card-body{
    gap: 2px;
}

/* La croix garde une cible de 44px sans élargir la carte */
.bib-card-remove{
    display: inline-flex;
    flex: 0 0 auto;
    align-items: center;
    justify-content: center;
    width: var(--sp-control-icon-button);
    height: var(--sp-control-icon-button);
    margin: 0 -16px;
    padding: 0;
    border: 0;
    border-radius: var(--sp-radius-full);
    background: none;
    color: inherit;
}

.bib-card-remove:focus-visible{
    outline: 0;
    box-shadow: var(--sp-shadow-ring);
}

/* « Voir [10 Photos] Avant et après ⓘ » : 15/18, liste compacte de 40px */
.bib-around{
    display: flex;
    align-items: center;
    gap: var(--sp-space-2);
    min-height: 40px;
    margin-top: 25px;
    font-size: var(--sp-font-size-body);
    font-weight: var(--sp-font-weight-body);
    line-height: 18px;
    letter-spacing: var(--sp-font-tracking-tight);
    color: var(--sp-color-text-default);
}

.bib-around[hidden],
.bib-selected[hidden],
.bib-suggestions[hidden]{
    display: none;
}

.bib-around label{
    margin: 0;
}

.bib-around-field{
    position: relative;
    display: inline-flex;
}

/* Le chevron du système (16px, au trait fin), retourné : celui de Bootstrap est trop gras */
.bib-around-chevron{
    position: absolute;
    top: 50%;
    right: 10px;
    display: inline-flex;
    transform: translateY(-50%) rotate(180deg);
    pointer-events: none;
    color: var(--sp-color-text-default);
}

.bib-around .bib-around-select{
    width: auto;
    height: 40px;
    min-height: 40px;
    padding: var(--sp-space-1) 33px var(--sp-space-1) 10px;
    border: 1px solid var(--sp-color-border-cream);
    border-radius: var(--sp-radius-sm);
    background-image: none;
    font-size: var(--sp-font-size-body);
    font-weight: var(--sp-font-weight-title);
    line-height: 18px;
    letter-spacing: var(--sp-font-tracking-tight);
    color: var(--sp-color-text-default);
}

.bib-around-info{
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: 0;
    background: none;
    color: var(--sp-color-text-meta);
}

.bib-around-info:focus-visible{
    outline: 0;
    border-radius: var(--sp-radius-full);
    box-shadow: var(--sp-shadow-ring);
}

/* --- Fidélité maquette Figma UI_V2 : valeurs relevées dans le CSS des frames (groupes
   MOBILE_HOME et DESKTOP). Échelle typo de la maquette : 20/24 à -0.03em, 16/19 et 15/18 à
   -0.02em, 13/16 et 12/15 à -0.01em. ------------------------------------------------------ */

/* Gouttière d'écran : 16px, contenu de 343px sur 375 (layout.screen-pad) */
@media (max-width: 991.98px) {
    .container, .container-fluid, .container-lg{
        --bs-gutter-x: calc(var(--sp-layout-screen-pad) * 2);
    }
}

/* Onglets : 16/19 semibold, inactifs en brun, pilule de 31px (6px dessus et dessous, 18px de
   côté), glyphe de 14 à 4px du mot — sur les deux supports (fiche tabs) */
.tab-bar-nav .nav-link{
    min-height: 31px;
    padding: 6px 18px;
    gap: var(--sp-space-1);
    font-size: var(--sp-font-size-h4);
    font-weight: var(--sp-font-weight-title);
    line-height: 19px;
    letter-spacing: var(--sp-font-tracking-tight);
    color: var(--sp-color-text-brown);
}

/* En-tête de section */
.sec-header-title{
    line-height: 24px;
    letter-spacing: var(--sp-font-tracking-tighter);
}

.sec-header-link{
    font-size: var(--sp-font-size-body);
    line-height: 18px;
    letter-spacing: var(--sp-font-tracking-tight);
}

/* Carte mise en avant : sport et méta en 13/16, titre en 20/24 */
.event-highlighted-sport{
    font-size: var(--sp-font-size-meta);
    font-weight: var(--sp-font-weight-body);
    line-height: 16px;
    letter-spacing: var(--sp-font-tracking-meta);
}

.event-highlighted-title{
    line-height: 24px;
    letter-spacing: var(--sp-font-tracking-tighter);
}

.event-highlighted-meta{
    line-height: 16px;
    letter-spacing: var(--sp-font-tracking-meta);
}

.event-rail .event-highlighted-scrim{
    gap: 6px;
}

/* Badge de date : 22px ; compteur : pilule de 24px en 12/15 semibold, glyphe de 14 */
.event-highlighted .badge{
    gap: 2px;
    line-height: 16px;
    letter-spacing: var(--sp-font-tracking-meta);
}

.event-highlighted-top .badge:not(.badge-glass),
.event-highlighted-top .event-highlighted-date{
    height: 22px;
    padding: 0 8px 0 5px;
}

/* La pilule en 600 12/15 est celle du compteur de photos (et de la visibilité d'une galerie
   gérée). L'échéance garde sa forme et sa typo de badge de date dans son ton verre : coins de
   8, 500 13/16, comme sa version rouge (maquette, « Clear Glass » de la carte). */
.event-highlighted-top .badge-glass:not(.event-highlighted-date){
    height: 24px;
    padding: 0 9px;
    gap: 3px;
    border-radius: var(--sp-radius-full);
    font-size: var(--sp-font-size-12);
    font-weight: var(--sp-font-weight-title);
    line-height: 15px;
    letter-spacing: var(--sp-font-tracking-tight);
}

.event-highlighted-top .badge-glass svg{
    width: 14px;
    height: 14px;
}

/* Tuile du choix d'évènement au dépôt (maquette EVENT_SELECT) : coins à 16px, voile haut pour
   les pictos de visibilité, bouton 13/16 medium, mention grise sous la tuile. */
.event-highlighted-wrap--deposit{
    height: auto;
}

.event-highlighted-deposit::after{
    background: linear-gradient(180deg, rgba(0, 0, 0, .6111) 0%, rgba(0, 0, 0, 0) 26.44%, rgba(0, 0, 0, 0) 49.52%, rgba(0, 0, 0, .97) 100%);
}

.event-highlighted-deposit .event-highlighted-top{
    padding: 16px;
}

/* Le badge « Privée » (retour du 27/10) : centré dans la rangée des actions d'un en-tête, ou en
   bas à droite d'une carte pendant le dépôt, à fin filet blanc (visuel 34). */
.badge-glass.event-visibility-badge--center{
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
}

/* En bureau, les pilules nommées occupent le centre : le badge reprend sa place dans la rangée. */
@media (min-width: 992px) {
    .event-highlighted-header--page .badge-glass.event-visibility-badge--center{
        position: relative;
        top: auto;
        left: auto;
        transform: none;
        margin-right: auto;
    }
}

.event-visibility-icon{
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    border-radius: 50%;
    color: var(--sp-color-text-inverse);
    background-color: rgba(30, 28, 26, .55);
    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .25);
    -webkit-backdrop-filter: blur(8px);
    backdrop-filter: blur(8px);
}

/* Galerie privée en bureau : en bas à droite du héros, à la taille des pilules voisines (retour du 29/10). */
.event-hero-visibility{
    position: absolute;
    pointer-events: none;
    right: 24px;
    bottom: 24px;
    z-index: 2;
}

.event-highlighted-header--page:has(.event-hero-visibility) .event-highlighted-meta{
    padding-right: 120px;
}

.badge-glass.event-visibility-badge--corner{
    position: absolute;
    right: 16px;
    bottom: 16px;
    z-index: 2;
    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .6), var(--sp-glass-overlay-shadow);
}

.event-highlighted:has(.event-visibility-badge--corner) .event-highlighted-meta{
    padding-right: 76px;
}

.event-highlighted-wrap--deposit .event-highlighted-action{
    top: 16px;
    right: 16px;
}

.event-highlighted-deposit .event-highlighted-when{
    font-weight: 500;
}

.event-highlighted-note{
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 5px;
    margin: 8px 0 0;
    color: #757575;
    font-size: 13px;
    font-weight: 500;
    line-height: 16px;
    letter-spacing: -0.01em;
}

/* Pastilles du rail : 4px d'écart, la courante en brun */
.event-rail-section .rail-dots{
    gap: var(--sp-space-1);
}

.rail-dot.active{
    background-color: var(--sp-color-text-brown);
}

/* Rail mobile : carte de 313px sur 343, 18px entre deux cartes, 24px sous le texte */
@media (max-width: 991.98px) {
    .event-rail{
        gap: 18px;
    }

    .event-rail > *{
        flex-basis: calc(100% - 30px);
    }

    .event-rail .event-highlighted-scrim{
        padding-bottom: var(--sp-space-6);
    }
}

/* Ligne de liste : nom en 16/19, détails en 13/16, 6px puis 8px entre les rôles */
.list-item-title{
    line-height: 19px;
    letter-spacing: var(--sp-font-tracking-tight);
}

.list-item-detail,
.list-item-meta{
    line-height: 16px;
    letter-spacing: var(--sp-font-tracking-meta);
}

.list-item-body{
    gap: 6px;
}

.list-item-detail + .list-item-meta{
    margin-top: 2px;
}

/* Tête d'accueil mobile : recherche de 44px, chips à 12px du filet des onglets. Sous les
   chips, la rangée de la maquette (EVENT_FILTER des quatre onglets : 14px de marge basse, SANS
   filet — son contour de 1px n'a pas de couleur, le CSS de la maquette n'en porte aucun) puis
   8px avant la première section (Content_homepage) : le titre à 22px des chips, le même sur
   Live, Récent, Passé et À venir. Le seul filet de la tête est celui des onglets. */
@media (max-width: 991.98px) {
    .search-bar{
        height: 44px;
    }

    .search-bar .ts-control{
        padding-top: 10px !important;
        padding-bottom: 10px !important;
    }

    .tab-bar-nav{
        margin-bottom: var(--sp-space-2);
    }

    .tab-bar-block{
        margin-bottom: var(--sp-space-2);
    }

    .tab-bar-block .filter-chips{
        padding-bottom: 14px;
    }

    /* « En attente de photo » en tête de page : à 22px des chips, sans filet, comme toute
       première section. Elle garde le sien quand elle suit le rail ou une publicité (retour
       client). */
    .container-home .awaiting-header:first-child{
        margin-top: 0 !important;
        padding-top: 0;
        border-top: 0;
    }

    /* Placeholder et loupe dans le beige de la maquette (BROWN_BORDER) ; le placeholder en
       15/18 medium, la loupe à 16 (retour client) */
    .search-bar .input-group-text,
    .search-bar .ts-control input::placeholder{
        color: var(--sp-color-border-cream);
    }

    /* Le champ garde 16px (sans quoi iOS zoome au focus, cf. la règle plus haut) : c'est le
       placeholder seul qui descend à 15/18 medium. TomSelect réserve à droite la place d'une
       flèche que cette barre n'a pas : sans la reprendre, le placeholder se coupait à « un Sp ». */
    .search-bar .ts-control input{
        font-weight: var(--sp-font-weight-body);
        letter-spacing: var(--sp-font-tracking-tight);
    }

    .search-bar .ts-control input::placeholder{
        font-size: var(--sp-font-size-body);
    }

    .search-bar .ts-wrapper .ts-control{
        padding-right: var(--sp-space-4) !important;
    }

    .search-bar .input-group-text svg{
        width: 16px;
        height: 16px;
    }
}

/* Listes de l'accueil : le texte part du haut de la vignette, la cloche s'aligne sur le nom
   et sur le bord du contenu */
.awaiting-list .list-item,
[data-infinite-scroll-target="grid"] .list-item{
    align-items: flex-start;
}

.awaiting-list .list-item > .btn-circle,
[data-infinite-scroll-target="grid"] .list-item > .btn-circle{
    margin-top: -13px;
    margin-right: -14px;
}

@media (max-width: 991.98px) {
    /* Le rail commence 18px sous son titre, la liste 20px sous le sien */
    .sec-header:has(+ .event-rail-section){
        margin-bottom: 18px;
    }

    .awaiting-header{
        margin-bottom: var(--sp-space-2);
    }
}

/* --- Panneaux de filtres (Figma FILTER_PAGE) : gouttière de 18px, titre à 16px du bord haut,
   liste à 17px du titre. Plus de poignée (retour client) : elle coûtait de la hauteur à un
   panneau qui n'en a jamais trop, et la croix comme le voile suffisent à le refermer. ------ */
@media (max-width: 991.98px) {
    .filter-panel{
        gap: 17px;
        padding: var(--sp-space-4) 18px var(--sp-space-6);
    }

    .filter-panel-head{
        height: 25px;
    }

    .filter-panel-foot{
        margin-left: -18px;
        margin-right: -18px;
    }

    .event-bib-search{
        margin: 0 -18px;
        padding: 6px 18px 0;
    }

    /* Résumé du calendrier : même fond perdu, et 17 + 7 = 24px sous le titre */
    .calendar-summary{
        margin-left: -18px;
        margin-right: -18px;
        padding: 7px 18px calc(var(--sp-space-6) - 1px);
    }

    /* Le bouton principal prend la largeur de son libellé, « Effacer » le reste */
    .filter-panel-foot .btn-marketing{
        flex: 0 0 auto;
        padding-left: var(--sp-space-3);
        padding-right: var(--sp-space-3);
        white-space: nowrap;
    }

    /* Lignes de 42px filet compris, glyphe dans une case de 24 à 6px du libellé */
    .filter-row{
        gap: 6px;
        min-height: 41px;
    }

    .filter-row-icon{
        justify-content: center;
        width: 24px;
    }

    .filter-row-head{
        gap: var(--sp-space-1);
        min-height: 25px;
        padding: 0;
        margin-bottom: 10px;
    }
}

.filter-panel-foot{
    border-top-color: var(--sp-color-border-on-white);
}

.filter-panel-foot .btn{
    line-height: 18px;
}

.filter-row-label{
    line-height: 18px;
    letter-spacing: var(--sp-font-tracking-tight);
}

.filter-row-head .filter-row-label{
    font-size: var(--sp-font-size-h4);
    line-height: 19px;
}

/* Switch de 36×20 (pastille de 16), ferré à droite sur la colonne des cases : Bootstrap le
   décale de 2.5em vers la gauche pour un libellé qui n'existe pas ici */
.filter-row-switch .form-check-input{
    float: none;
    width: 36px;
    height: 20px;
    margin: 0;
}

/* Liste à cocher sous son en-tête (Prix, Albums, Photographes) : 12px de l'en-tête au premier
   libellé, rangées au pas de 42px filet compris */
.filter-list-single .filter-row-head{
    margin-bottom: var(--sp-space-1);
}

.filter-list-single .filter-row + .filter-row:has(> [type="checkbox"]){
    min-height: 42px;
}

/* Le pied est une surface pleine : la liste défile derrière lui sans transparaître. Il descend
   jusqu'au bord du panneau, il en reprend donc les coins du bas (16px en Dropdown, 0 en Sheet) */
.filter-panel-foot{
    position: relative;
    z-index: 1;
    background-color: inherit;
    border-bottom-left-radius: inherit;
    border-bottom-right-radius: inherit;
}

.filter-panel-form{
    background-color: inherit;
    border-radius: inherit;
}

/* Glyphe de 16 dans sa case de 24 (Figma : 24 moins 4 de retrait) */
.filter-row:not(.filter-row-head) .filter-row-icon svg{
    width: 16px;
    height: 16px;
}

/* Liste à choix unique (« Trier par ») : options de 25px à 8px l'une de l'autre, sans filet,
   libellé en regular ; radio de 20px au trait gris foncé, coché = anneau et point orange.
   Ne vaut que pour des radios : une liste à cocher (Photographes, Albums, Prix) garde ses
   rangées de 42px filet compris. */
.filter-list-single .filter-row:has(> [type="radio"]){
    min-height: 25px;
    padding: 0;
}

.filter-list-single .filter-row:has(> [type="radio"]) + .filter-row{
    margin-top: var(--sp-space-2);
    border-top: 0;
}

.filter-list-single .filter-row:has(> [type="radio"]) .filter-row-label{
    font-weight: var(--sp-font-weight-prose);
}

/* Ces options n'ont ni marge ni filet : sans les 24px de la gouttière, la dernière butait sur
   le filet du pied, comme Dates et Localisation. */
.filter-list-single:has(> .filter-row > [type="radio"]){
    padding-bottom: var(--sp-space-6);
}

/* Lignes-cartes du panneau Photographes (maquette CASE_PHOTOGRAPH) : 63px, avatar de 51, la
   carte cochée passe en crème soutenu ; en-tête 15/18 medium, « 1 sélectionné » à droite du titre */
.filter-panel-aside{
    margin-left: auto;
    font-size: var(--sp-font-size-body);
    font-weight: var(--sp-font-weight-body);
    line-height: 18px;
    letter-spacing: var(--sp-font-tracking-tight);
    color: var(--sp-color-text-default);
}

.filter-list-cards .filter-row-head{
    margin-bottom: var(--sp-space-3);
}

.filter-list-cards .filter-row-head .filter-row-label{
    font-size: var(--sp-font-size-body);
    font-weight: var(--sp-font-weight-body);
    line-height: 18px;
}

/* Carte non cochée : filet #DCDAD1 (EVENT_LIST, BROWN_BORDER_MEDIUM) ; celle d'un inscrit
   « en attente » garde le filet clair (#EEE9DD) */
.filter-list-cards .filter-row--card,
.filter-list-cards .filter-row--card + .filter-row--card{
    gap: var(--sp-space-3);
    min-height: 63px;
    padding: 5px var(--sp-space-3) 5px 5px;
    border: 1px solid #DCDAD1;
    border-radius: var(--sp-radius-lg);
    background-color: var(--sp-color-bg-surface);
}

.filter-list-cards .filter-row--card.filter-row--pending{
    border-color: var(--sp-color-border-default);
}

.filter-list-cards .filter-row--card + .filter-row--card{
    margin-top: var(--sp-space-3);
}

.filter-list-cards .filter-row--card:has(:checked){
    border-color: var(--sp-color-bg-sunken);
    background-color: var(--sp-color-bg-sunken);
}

/* Avatar rond de 51 (CASE_PHOTOGRAPH : Ellipse) */
.filter-row-avatar{
    flex: 0 0 51px;
    width: 51px;
    height: 51px;
    border-radius: 50%;
    object-fit: cover;
}

.filter-row--card .filter-row-label{
    display: flex;
    flex-direction: column;
    gap: 5px;
    min-width: 0;
}

.filter-row--card .filter-row-name{
    font-size: var(--sp-font-size-h4);
    font-weight: var(--sp-font-weight-title);
    line-height: 19px;
}

.filter-row--card .filter-row-meta{
    font-size: var(--sp-font-size-meta);
    font-weight: var(--sp-font-weight-body);
    line-height: 16px;
    letter-spacing: var(--sp-font-tracking-meta);
    color: var(--sp-color-text-muted);
}

/* Case au repos sur une ligne-carte blanche : un aplat gris, sans filet (fiche checkbox) */
.filter-row--card .filter-row-check:not(:checked){
    border-color: var(--sp-color-border-on-white);
    background-color: var(--sp-color-border-on-white);
}

/* « → En attente de photo » : à 32px du premier groupe, cartes sans case, estompées */
.filter-list-cards .filter-group-title--next{
    display: flex;
    align-items: center;
    gap: var(--sp-space-1);
    margin: var(--sp-space-8) 0 var(--sp-space-3);
    padding: 0;
    border: 0;
    font-size: var(--sp-font-size-body);
    font-weight: var(--sp-font-weight-body);
    line-height: 18px;
    letter-spacing: var(--sp-font-tracking-tight);
    text-transform: none;
    color: var(--sp-color-text-default);
}

.filter-list-cards .filter-row--pending{
    opacity: .6;
}

/* Sous un en-tête à interrupteur (« Toutes »), les cases se rangent en retrait d'un cran */
.filter-row--indent{
    margin-left: var(--sp-space-4);
}

.filter-row-check[type="radio"]{
    width: 20px;
    height: 20px;
    border: 2.5px solid var(--sp-color-border-control-strong);
    background-color: transparent;
}

.filter-row-check[type="radio"]:checked{
    border-color: var(--sp-color-accent-selected);
    background-color: transparent;
    background-image: radial-gradient(circle, var(--sp-color-accent-selected) 6px, transparent 6.5px);
}

/* Rien à effacer et rien à valider : le pied disparaît, comme sur la maquette */
.filter-panel-foot:has(> .btn:only-child:disabled){
    display: none;
}

@media (max-width: 991.98px) {
    .filter-panel:has(.filter-panel-foot > .btn:only-child:disabled){
        padding-bottom: var(--sp-space-10);
    }
}

/* --- Galerie mobile (Figma GALLERY_EVENT) ------------------------------------------------ */
@media (max-width: 991.98px) {
    /* Repère de 7px à 14px du bord, photos à 36px : grille de 324px, tuiles de 102,67px à
       8px l'une de l'autre, au rayon de 8 */
    .timeline{
        margin-left: -2px;
        margin-right: -1px;
    }

    .timeline-item{
        grid-template-columns: 7px 1fr;
        gap: 15px;
    }

    .timeline .photo-gallery{
        --bs-gutter-x: var(--sp-space-2);
        --bs-gutter-y: var(--sp-space-2);
    }

    .timeline .photo-gallery .ratio-1x1,
    .timeline .photo-gallery a,
    .timeline .photo-gallery-more-overlay{
        border-radius: var(--sp-radius-sm);
    }

    /* Hero : retour en disque gris clair translucide, groupe d'actions de 78×40 */
    .event-highlighted-header--page .event-hero-back{
        background-color: var(--sp-glass-button-bg-back);
        box-shadow: var(--sp-glass-overlay-lift);
    }

    .event-highlighted-header--page .glass-group{
        padding: 0 3px;
        border: 0;
    }

    .event-highlighted-header--page .glass-group-item{
        width: 36px;
        min-width: 36px;
        height: 38px;
        min-height: 38px;
    }
}

/* Journée : date en 16/19, compteur de 24px au rayon de 6, écrit en gris foncé */
.timeline-label{
    font-size: var(--sp-font-size-h4);
    line-height: 19px;
    letter-spacing: var(--sp-font-tracking-tight);
}

/* Badge d'état de l'agenda des tableaux de bord : -1 % d'interlettrage (maquette DASHBOARD). */
#photographer-dashboard .badge.timeline-label,
#club-dashboard .badge.timeline-label{
    letter-spacing: -0.01em;
}

.timeline-count{
    padding: 0 var(--sp-space-1);
    border-radius: var(--sp-radius-xs);
    color: var(--sp-color-text-meta);
    line-height: 15px;
    letter-spacing: var(--sp-font-tracking-tight);
}

.timeline-count strong{
    color: inherit;
}

.timeline-meta{
    font-weight: var(--sp-font-weight-body);
    line-height: 16px;
    letter-spacing: var(--sp-font-tracking-meta);
    color: var(--sp-color-text-meta);
}

/* --- Frise de la page évènement (Figma GALLERY_EVENT 2119:7002 mobile, GALLERY 2434:7251
   desktop) -------------------------------------------------------------------------------
   Limité à la page évènement : le profil photographe a sa propre maquette. */

/* Rail et pastilles en #D3CDC3 (DOT TIMELINE, TIP TIMELINE) ; seule la journée courante
   reste orange */
.event-page .timeline-item:not(.timeline-item--current) .timeline-dot{
    background-color: var(--sp-color-border-cream);
}

.event-page .timeline-item:not(:last-child) .timeline-marker::before{
    height: calc(100% + var(--timeline-gap));
    background-color: var(--sp-color-border-cream);
}

/* Le rail s'éteint toujours en dégradé vers le nœud de fin (retour client) */
.event-page .timeline-item:nth-last-child(2) .timeline-marker::before{
    background: linear-gradient(to bottom, var(--sp-color-border-cream) 60%, transparent);
}

/* D'une journée à la suivante : 16 sous le dernier bloc (« Voir plus », encart d'attente) et
   14 au-dessus de la date (SPACER) — 30. Jusqu'au texte de fin : 16 + 7 + 3,5 (ligne de 28
   centrée dans 29), arrondi à 27. Le rail suit l'écart. */
.event-page .timeline-item{
    --timeline-gap: 30px;
}

.event-page .timeline-item:not(:last-child){
    padding-bottom: var(--timeline-gap);
}

.event-page .timeline-item:has(+ .timeline-item--end){
    --timeline-gap: 27px;
}

/* La méta collée sous la date ; les photos 12px dessous en mobile, 20 en desktop. La rangée
   remet sa gouttière au-dessus des tuiles : la marge la décompte. */
.event-page .timeline-meta{
    margin-top: 0;
}

.event-page .timeline-gallery{
    margin-top: calc(12px - var(--bs-gutter-y));
}

/* « Voir plus » : 16 sous les photos, et 5px plus à gauche qu'elles — la maquette l'aligne sur
   la colonne du rail (7 + 10), pas sur la grille (3 + 19) */
.event-page .timeline-more{
    margin-top: var(--sp-space-4);
    margin-left: -5px;
    width: calc(100% + 5px) !important;   /* l'utilitaire w-100 */
}

/* Journée en attente : « Me prévenir » en pastille de 25 (Number : 7 8, creux crème, 600 12/15
   gris foncé, cloche de 10×11), l'encart 16 dessous */
.event-page .timeline-item:has(.timeline-notify){
    --timeline-header-h: 25px;
}

.event-page .btn.timeline-notify{
    --bs-btn-color: var(--sp-color-text-meta);
    --bs-btn-bg: var(--sp-color-bg-sunken);
    --bs-btn-border-color: var(--sp-color-bg-sunken);
    --bs-btn-hover-color: var(--sp-color-text-meta);
    --bs-btn-hover-bg: var(--sp-color-bg-sunken-strong);
    --bs-btn-hover-border-color: var(--sp-color-bg-sunken-strong);
    --bs-btn-active-color: var(--sp-color-text-meta);
    --bs-btn-active-bg: var(--sp-color-bg-sunken-strong);
    --bs-btn-active-border-color: var(--sp-color-bg-sunken-strong);
    height: 25px;
    padding: 0 7px;   /* + le filet de 1 : 8 */
    gap: var(--sp-space-1) !important;   /* l'utilitaire gap-2 */
    letter-spacing: var(--sp-font-tracking-tight);
}

/* Le glyphe de la cloche fait 10,5 dans une boîte de 12 : la boîte rendue à 10, la pastille
   retombe à 97 */
.event-page .timeline-notify svg{
    width: 12px;
    height: 12px;
    margin: 0 -1px;
}

.event-page .timeline-awaiting{
    margin-top: var(--sp-space-4);
    letter-spacing: var(--sp-font-tracking-tight);
}

/* L'encart qui referme une journée de photos (PUB_GROUP) : entre deux filets #EEE9DD, 14px de part
   et d'autre de chacun ; il part 1px avant la colonne des photos (rail 7 + 14). 14px sous les
   photos, 30 sous « Voir plus » (16 de sa rangée + 14), puis 28 jusqu'à la journée suivante
   (14 + le SPACER de 14) et 25 jusqu'au texte de fin (14 + 7 + 3,5, arrondi comme plus haut). */
.event-page .timeline-ad{
    margin: 14px 0 0 -1px;
    padding: 14px 0;
    border-top: 1px solid #EEE9DD;
    border-bottom: 1px solid #EEE9DD;
}

.event-page .timeline-day:has(.timeline-more) + .timeline-ad{
    margin-top: 30px;
}

/* Bannière intercalée dans la grille toutes les N lignes (retour client « Publicité ») : une
   pleine largeur entre deux lignes de vignettes, basse — jamais une tuile dans une carte. */
.timeline-grid-ad{
    flex: 0 0 100%;
    max-width: 100%;
}

.timeline-grid-ad-box{
    padding: 6px 0;
}

.timeline-grid-ad .ad-slot{
    min-height: 0;
}

.event-page .timeline-item:has(.timeline-ad){
    --timeline-gap: 28px;
}

.event-page .timeline-item:has(.timeline-ad):has(+ .timeline-item--end){
    --timeline-gap: 25px;
}

/* 320×100 en mobile, 931×250 en desktop (PUBLICITE) */
@media (max-width: 991.98px) {
    .event-page .timeline-ad .ad-slot{
        max-width: 320px;
    }
}

@media (min-width: 992px) {
    .event-page .timeline-ad .ad-slot{
        min-height: 250px;
    }
}

/* Le libellé long de « Voir plus » ne sert qu'au desktop de la page évènement */
.timeline-more-long{
    display: none;
}

@media (min-width: 992px) {
    /* Rail de 7px, photos à 22px du bord de la carte (TIMELINE 3 + 19), comme en mobile */
    .event-page .timeline-item{
        grid-template-columns: 7px 1fr;
        gap: 15px;
    }

    .event-page .timeline-gallery{
        margin-top: calc(20px - var(--bs-gutter-y));
    }

    /* Méta de journée en 500 15/18 */
    .event-page .timeline-meta{
        font-size: var(--sp-font-size-body);
        line-height: 18px;
        letter-spacing: var(--sp-font-tracking-tight);
    }

    /* « Voir 310 photos supplémentaires » et son chevron, à 7px du trait : la boîte de 13 en
       ajoute 1,6 devant le glyphe */
    .event-page .timeline-more-short{
        display: none;
    }

    .event-page .timeline-more-long{
        display: inline-flex;
        align-items: center;
        gap: 5px;
    }

    .event-page .timeline-more-chevron{
        transform: rotate(180deg);
    }
}

/* Tuile « +N » : 24/29 regular sur un voile à 45 % */
.photo-gallery-more-overlay{
    background-color: var(--sp-glass-overlay-tile-veil);
    font-size: var(--sp-font-size-figure);
    font-weight: var(--sp-font-weight-prose);
    line-height: 29px;
    letter-spacing: var(--sp-font-tracking-tighter);
}

/* --- Page photo (Figma PHOTO PAGE) ----------------------------------------------------- */

/* Barre posée sur la photo. Mobile : verre clair de 37px ; desktop : verre sombre de 45px */
.photo-stage-bar .btn-glass,
.photo-stage-actions{
    background-image: none;
    border: 0;
}

@media (max-width: 991.98px) {
    .photo-stage-bar .btn-glass,
    .photo-stage-actions{
        background-color: var(--sp-glass-button-bg-light);
    }

    .photo-stage-bar .btn-glass{
        width: 37px;
        height: 37px;
        min-width: 37px;
        min-height: 37px;
    }

    .photo-stage-actions{
        height: 37px;
        padding: 0 3px;
    }

    .photo-stage-action{
        width: 34px;
        min-width: 34px;
        height: 37px;
        min-height: 37px;
    }
}

@media (min-width: 992px) {
    .photo-stage-bar .btn-glass{
        width: 45px;
        height: 45px;
    }

    .photo-stage-actions{
        height: 45px;
    }
}

.photo-stage-title{
    font-size: var(--sp-font-size-h4);
    line-height: 19px;
    letter-spacing: var(--sp-font-tracking-tight);
    text-shadow: var(--sp-glass-overlay-text-shadow);
}

.photo-stage-date{
    line-height: 16px;
    letter-spacing: var(--sp-font-tracking-meta);
    color: var(--sp-color-text-inverse);
    opacity: .82;
    text-shadow: var(--sp-glass-overlay-text-shadow);
}

/* Compteur : pilule de 28px ; la position en 16px, le total en 13px, même graisse (fiche badge) ;
   points de 7px, le courant en blanc */
.photo-stage-counter{
    height: 28px;
    padding: 0 10px;
    border-radius: var(--sp-radius-full);
    background-color: var(--sp-glass-button-bg);
    font-size: var(--sp-font-size-h4);
    font-weight: var(--sp-font-weight-title);
    line-height: 16px;
    letter-spacing: var(--sp-font-tracking-tight);
}

.photo-stage-counter-total{
    font-size: var(--sp-font-size-meta);
    letter-spacing: var(--sp-font-tracking-meta);
}

.photo-stage-dots{
    gap: var(--sp-space-1);
    filter: drop-shadow(0 0 9px #000);
}

.photo-stage-dot{
    width: 7px;
    height: 7px;
    background-color: var(--sp-color-text-inverse);
    opacity: .8;
}

.photo-stage-dot.is-active{
    background-color: var(--sp-color-text-inverse);
    opacity: 1;
}

/* Mini galerie : la courante porte une ombre, ses voisines restent entières */
.photo-filmstrip{
    padding-block: 0;
}

.photo-filmstrip-item{
    opacity: 1;
}

.photo-filmstrip-item.is-current{
    box-shadow: var(--sp-shadow-knob);
}

/* Mobile : la courante un cran plus grande — 82 pour 79 à 375px (maquette). Une PART de la
   ligne, pas une taille fixe : à 82px figés elle devenait la plus petite sur un écran large. */
@media (max-width: 991.98px) {
    .photo-filmstrip-item{
        flex-grow: 79;
    }

    .photo-filmstrip-item.is-current{
        flex-grow: 82;
    }
}

@media (max-width: 991.98px) {
    /* 16px entre la photo, la mini galerie et le bouton */
    div:has(> .photo-frame),
    .photo-filmstrip{
        margin-bottom: var(--sp-space-4) !important;
    }

    /* Achat : pilule de 48px en 16/19 semibold, partage en disque crème de 48px à 12px */
    .photo-actions,
    .photo-actions > .d-flex{
        gap: var(--sp-space-3) !important;
    }

    .photo-actions .btn{
        min-height: 48px;
    }
}

.photo-actions form .btn{
    font-size: var(--sp-font-size-h4);
    font-weight: var(--sp-font-weight-title);
    line-height: 19px;
}

.photo-actions .btn-circle{
    width: 48px;
    height: 48px;
    background-color: var(--sp-color-bg-sunken);
    border-color: var(--sp-color-bg-sunken);
}

/* Onglets de la fiche : ceux de l'accueil */
.photo-tabs .nav-link{
    padding: 6px 18px;
    font-size: var(--sp-font-size-h4);
    font-weight: var(--sp-font-weight-title);
    line-height: 19px;
    letter-spacing: var(--sp-font-tracking-tight);
    color: var(--sp-color-text-brown);
}

/* Lignes d'information : titre en 15/18 semibold, méta en 14/17 gris foncé */
.info-row-title{
    font-weight: var(--sp-font-weight-title);
    line-height: 18px;
    letter-spacing: var(--sp-font-tracking-tight);
}

.info-row-meta,
.info-row-sep{
    font-size: var(--sp-font-size-label);
    line-height: 17px;
    letter-spacing: var(--sp-font-tracking-tight);
    color: var(--sp-color-text-meta);
}

/* « Encore 12 jours en ligne » : la phrase en regular, seul le décompte en gras */
.info-row-title:has(> strong){
    font-weight: var(--sp-font-weight-prose);
}

.info-row-title strong{
    font-weight: var(--sp-font-weight-bold);
}

/* Le titre d'un évènement : 16/19 à -3 %, un cran au-dessus des autres titres de la liste */
.info-row-title--event{
    font-size: var(--sp-font-size-h4);
    line-height: 19px;
    letter-spacing: var(--sp-font-tracking-tighter);
}

/* --- Vue photo mobile, reprise sur la maquette MOBILE_PHOTO_PAGE (photo payante 2520:4344,
   photo offerte 2520:5339) --------------------------------------------------------------- */
/* Le titre posé sur la photo : 16/19 à -3 % */
.photo-stage-title{
    letter-spacing: var(--sp-font-tracking-tighter);
}

/* Une action du menu « … » : 10px du glyphe au libellé */
.menu-overlay-item{
    gap: 10px;
}

@media (max-width: 991.98px) {
    /* Le ruban défilant (retour client) garde la courante un cran plus grande, 82 pour 78,67 à
       375px (MINI GALERIE) : sa réserve de 6px pour l'ombre se décompte aussi dessous, sans quoi
       le bouton d'achat tombait à 22px des vignettes au lieu de 16. */
    .photo-filmstrip.photo-filmstrip--scroll .photo-filmstrip-item{
        flex-basis: calc((100% - 3 * var(--sp-space-2) - 3.33px) / 4);
    }

    .photo-filmstrip.photo-filmstrip--scroll .photo-filmstrip-item.is-current{
        flex-basis: calc((100% - 3 * var(--sp-space-2) - 3.33px) / 4 + 3.33px);
    }

    .photo-filmstrip.photo-filmstrip--scroll{
        margin-bottom: calc(var(--sp-space-4) - 6px) !important;
    }

    /* L'évènement (EVENT, 34px) : la méta à 2px du titre, la ligne suivante 13px sous elle */
    .info-row:has(.info-row-title--event){
        padding-bottom: 13px;
    }

    .info-row-title--event + .info-row-meta{
        margin-top: 2px;
    }

    /* Photo offerte : la publicité entre deux filets #EEE9DD, à 16px de part et d'autre de
       chacun (DETAILS : DIVIDER, PUBLICITE, DIVIDER) ; les filets courent à 18px des bords */
    .photo-side-top > .photo-detail-ad{
        margin-left: 2px;
        margin-right: 2px;
        padding: var(--sp-space-4) 0;
        border-top: 1px solid #EEE9DD;
        border-bottom: 1px solid #EEE9DD;
    }

    .photo-side-top > .photo-detail-ad > .ad-slot{
        margin: 0 -2px;
    }
}

/* Desktop : le ruban défilant garde aussi la courante de 175 pour 163 (PHOTO DESKTOP) ; à côté
   du panneau du dossard, ses six vignettes restent égales */
@media (min-width: 992px) {
    .photo-page-below:not(:has(> .bib-others)) > .photo-filmstrip.photo-filmstrip--scroll .photo-filmstrip-item{
        flex-basis: calc((100% - 6 * var(--sp-space-4)) / (6 + 175 / 163));
    }

    .photo-page-below:not(:has(> .bib-others)) > .photo-filmstrip.photo-filmstrip--scroll .photo-filmstrip-item.is-current{
        flex-basis: calc((100% - 6 * var(--sp-space-4)) / (6 + 175 / 163) * 175 / 163);
    }

    /* Avec annonce : 5 vignettes sous la photo, 1,5 fois plus grandes (retour du 06/11) */
    .photo-page-row:has(.photo-detail-ad) .photo-page-below > .photo-filmstrip.photo-filmstrip--scroll .photo-filmstrip-item{
        flex-basis: calc((100% - 4 * var(--sp-space-4)) / (4 + 175 / 163));
    }

    .photo-page-row:has(.photo-detail-ad) .photo-page-below > .photo-filmstrip.photo-filmstrip--scroll .photo-filmstrip-item.is-current{
        flex-basis: calc((100% - 4 * var(--sp-space-4)) / (4 + 175 / 163) * 175 / 163);
    }
}

/* --- Login mobile (Figma LOGIN & MENU MOBILE) : gouttière de 24px, champ de 52px, second
   choix du sélecteur sur une ligne ------------------------------------------------------ */
@media (max-width: 991.98px) {
    .login-card{
        --bs-card-spacer-x: var(--sp-space-6);
    }
}

.login-card .form-control.login-input{
    height: 52px;
    min-height: 52px;
}

.login-toggle .toggle-btn:not(.active){
    padding-left: var(--sp-space-2);
    padding-right: var(--sp-space-2);
    white-space: nowrap;
}

.login-title{
    line-height: 34px;
}

.login-hint,
.login-or{
    line-height: 18px;
}

.login-label{
    line-height: 19px;
}

.login-legal{
    line-height: 15px;
}

/* --- Menu mobile (Figma MOBILE_MENU) : entrées de 40px en 15/18, rubriques de 30px en
   13/16, pas de filet sur le bord du panneau -------------------------------------------- */
.mobile-menu{
    border-left: 0;
}

.mobile-menu-section a{
    line-height: 18px;
    letter-spacing: var(--sp-font-tracking-tight);
}

.mobile-menu-heading{
    line-height: 16px;
    letter-spacing: var(--sp-font-tracking-meta);
}

.mobile-menu-user-name{
    line-height: 24px;
}

.mobile-menu-space-links a{
    line-height: 18px;
}

/* --- Modale « Prévenez-moi » (Figma NOTIFICATION) : titre en 20/24, textes en 15/18
   regular, vignette de 66px, mention en 10/12 -------------------------------------------- */
.modal-title{
    line-height: 24px;
    letter-spacing: var(--sp-font-tracking-tighter);
}

.dialog-body > p:not(.dialog-note),
.dialog-form > p{
    font-weight: var(--sp-font-weight-prose);
    line-height: 18px;
    letter-spacing: var(--sp-font-tracking-tight);
    color: var(--sp-color-text-default);
}

.dialog-recap .list-item .list-item-thumb{
    width: 66px;
    height: 66px;
}

@media (max-width: 991.98px) {
    .modal-fullscreen-md-down .modal-header{
        padding-top: 18px;
    }
}

/* Décompte d'un en-tête de section : 15/18 en ink (« 5 Évènements ») — le nombre en 500, le mot
   en 600 (maquette, sur tous les onglets de l'accueil comme sur le profil) */
.sec-header-count{
    font-size: var(--sp-font-size-body);
    line-height: 18px;
    letter-spacing: var(--sp-font-tracking-tight);
    color: var(--sp-color-text-default);
}

.sec-header-count strong{
    font-weight: var(--sp-font-weight-title);
}

/* Listes de l'accueil : rangées de 72px à 12px du filet (pas de 97px), cloche de 16 */
[data-infinite-scroll-target="grid"] .list-item{
    padding-top: var(--sp-space-3);
    padding-bottom: var(--sp-space-3);
}

.awaiting-list .list-item > .btn-circle svg,
[data-infinite-scroll-target="grid"] .list-item > .btn-circle svg{
    width: 16px;
    height: 16px;
}

/* Titre du hero desktop : 40/48 (Figma GALLERY desktop), 6px entre sport, titre et méta */
@media (min-width: 992px) {
    .event-highlighted-header h1.event-highlighted-title{
        line-height: 48px;
    }

    .event-highlighted-header .event-highlighted-scrim{
        gap: 6px;
    }
}

/* Desktop (Figma DESKTOP) : placeholder de recherche en 15/18 brun, tuiles de galerie au
   rayon de 16 */
@media (min-width: 992px) {
    .search-bar .ts-control input{
        font-size: var(--sp-font-size-body);
        font-weight: var(--sp-font-weight-body);
        letter-spacing: var(--sp-font-tracking-tight);
    }

    .search-bar .ts-control input::placeholder{
        color: var(--sp-color-text-brown);
    }

    .timeline .photo-gallery .ratio-1x1,
    .timeline .photo-gallery a,
    .timeline .photo-gallery-more-overlay{
        border-radius: var(--sp-radius-lg);
    }
}

/* Chip de filtre : libellé en 14/17 (son ombre unique est shadow.sm) */
.chip-filter{
    line-height: 17px;
}

/* --- Accueil desktop (Figma HOMEPAGE DESKTOP, frame de 1708) ----------------------------- */

/* À droite d'un titre de section : « 34 évènements couverts · Voir tout › » */
.sec-header-aside{
    display: flex;
    align-items: center;
    gap: var(--sp-space-2);
}

/* « 34 évènements couverts » : le nombre en 700/16, les mots en 500/15 (maquette HOMEPAGE
   DESKTOP) */
.sec-header-aside .sec-header-count{
    font-size: var(--sp-font-size-body);
    line-height: 19px;
}

.sec-header-aside .sec-header-count strong{
    font-size: var(--sp-font-size-h4);
    font-weight: var(--sp-font-weight-bold);
}

/* Le point médian n'existe qu'avec le décompte, donc sur desktop */
@media (min-width: 992px) {
    .sec-header-aside .sec-header-count + .sec-header-link::before{
        content: '';
        flex-shrink: 0;
        width: 2px;
        height: 2px;
        margin-right: var(--sp-space-2);
        border-radius: var(--sp-radius-full);
        background-color: var(--sp-color-text-default);
    }
}

.sec-header-link{
    display: inline-flex;
    align-items: center;
}

.sec-header-link svg{
    margin-left: var(--sp-space-2);
}

@media (min-width: 992px) {
    /* Contenu de 1130px ; 36px entre deux sections, 17px sous un titre */
    .container.container-home{
        max-width: calc(var(--sp-layout-content-home) + var(--bs-gutter-x));
    }

    .container-home .tab-bar-block{
        margin-bottom: 36px;
    }

    .container-home .sec-header{
        margin-bottom: 17px;
    }

    .container-home .sec-header-title{
        font-size: var(--sp-font-size-h2-dense);
        line-height: 29px;
    }

    .container-home .awaiting-header{
        margin-top: 36px !important;
        padding-top: 0;
        border-top: 0;
    }

    /* Carte blanche au rayon de 24 ; le rail y pose des tuiles de 310px à 24px */
    .container-home .section-surface{
        border-radius: var(--sp-radius-2xl);
        box-shadow: var(--sp-shadow-sm);
    }

    .container-home .section-surface.event-rail-section{
        padding-top: 28px;
        padding-bottom: var(--sp-space-6);
    }

    .container-home .event-rail{
        gap: var(--sp-space-6);
        padding-bottom: 0;
    }

    .container-home .event-rail > *{
        flex: 0 0 310px;
    }

    .container-home .event-rail .event-highlighted-top{
        padding-bottom: 0;
    }

    /* Liste en trois colonnes à 42px, première rangée à 47px du bord de la carte */
    .container-home .section-surface.awaiting-list{
        padding: 35px var(--sp-space-6) var(--sp-space-4);
    }

    .container-home .awaiting-list .list-item-grid{
        --bs-gutter-x: 42px;
    }
}

/* Barre haute desktop (Figma TOP BAR) : bandeau de 61px plus soutenu que la page, filet bas,
   50px de marge, recherche de 44px ; connecté : nom, avatar et chevron ouvrent le menu */
@media (min-width: 992px) {
    header.container-fluid:has(> .topbar-front){
        padding-left: var(--sp-layout-topbar-pad-desktop);
        padding-right: var(--sp-layout-topbar-pad-desktop);
        background-color: var(--sp-color-bg-band);
        border-bottom: 1px solid var(--sp-color-border-default);
        /* l'écart sous le bandeau vaut pour toutes les pages, pas seulement l'accueil */
        margin-bottom: var(--sp-space-5);
    }

    .topbar-front{
        min-height: var(--sp-layout-topbar-h-desktop);
        padding-top: 0 !important;
        padding-bottom: 0 !important;
    }

    .topbar-front .search-bar{
        height: 44px;
        box-shadow: none;
    }

    .topbar-front .search-bar .input-group-text{
        color: var(--sp-color-text-brown);
    }
}

.topbar-user{
    align-items: center;
    gap: 10px;
    max-width: 260px;
    padding: 0;
    border: 0;
    background: none;
    color: var(--sp-color-text-default);
}

.topbar-user-name{
    font-size: var(--sp-font-size-h4);
    font-weight: var(--sp-font-weight-title);
    line-height: 19px;
    letter-spacing: var(--sp-font-tracking-tight);
}

.topbar-user-chevron{
    display: inline-flex;
    transform: rotate(180deg);
}

.topbar-user:focus-visible{
    outline: none;
    box-shadow: var(--sp-shadow-ring);
    border-radius: var(--sp-radius-sm);
}

/* --- Panneau Localisation (Figma CASE_LOCATION) : champ en pilule de 46px au filet crème,
   loupe et invite en brun ; curseur écrit en méta, bornes en ink ------------------------- */
.filter-location-label{
    font-size: var(--sp-font-size-h4);
    line-height: 19px;
    letter-spacing: var(--sp-font-tracking-tight);
}

.filter-location-field .form-control{
    height: 46px;
    border-color: var(--sp-color-border-cream);
    font-weight: var(--sp-font-weight-body);
    letter-spacing: var(--sp-font-tracking-tight);
}

.filter-location-field .form-control::placeholder,
.filter-location-icon{
    color: var(--sp-color-text-brown);
}

.slider-label,
.slider-value{
    font-size: var(--sp-font-size-meta);
    line-height: 17px;
    letter-spacing: var(--sp-font-tracking-meta);
}

.slider-value{
    font-weight: var(--sp-font-weight-bold);
}

.slider-bounds{
    font-size: var(--sp-font-size-12);
    font-weight: var(--sp-font-weight-body);
    line-height: 17px;
    letter-spacing: var(--sp-font-tracking-tight);
    color: var(--sp-color-text-default);
}

/* --- Profil photographe (maquettes MOBILE_PROFILE et PROFILE DESKTOP) -------------------- */

/* Carte d'identité : 208px, cernée d'un halo, voile de 40 % à mi-hauteur au noir plein en bas */
.card-photo--profile{
    min-height: 208px;
    border-radius: var(--sp-radius-lg);
    box-shadow: var(--sp-shadow-photo);
}

.card-photo--profile .card-photo-scrim{
    padding: var(--sp-space-4) 26px;
    background: linear-gradient(180deg, rgba(0, 0, 0, .4) 40.87%, #000 100%);
}

/* Le portrait et le nom décollent de la photo (maquette MOBILE_PROFILE) : ombres 0 4 20, portrait
   à 10 % et opacité 92 %, nom à 18 %. */
.card-photo--profile .avatar{
    box-shadow: 0 4px 20px rgba(0, 0, 0, .1);
}

.card-photo--profile .avatar img{
    opacity: .92;
}

.card-photo--profile .card-photo-identity h1{
    margin: var(--sp-space-2) 0 0 !important;
    text-shadow: 0 4px 20px rgba(0, 0, 0, .18);
    font-size: var(--sp-font-size-h3);
    font-weight: var(--sp-font-weight-title);
    line-height: 24px;
    letter-spacing: var(--sp-font-tracking-tighter);
}

.card-photo--profile .card-photo-meta{
    font-size: var(--sp-font-size-label);
    font-weight: var(--sp-font-weight-body);
    line-height: 17px;
    letter-spacing: var(--sp-font-tracking-tight);
}

/* Les chiffres sur une ligne chacun : valeur 15/18, libellé 12/15 */
.card-photo--profile .card-photo-stats{
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: var(--sp-space-3);
    /* Bande de 45px (Clear Glass), à 16px des bords de la carte et non aux 26 de l'identité,
       chiffres centrés dans ses 6/9px de marge : ils remontent de 6px et s'élargissent de 10 */
    min-height: 45px;
    margin-left: -10px;
    margin-right: -10px;
    padding: 6px 9px;
}

.card-photo--profile .stat-block-value{
    font-size: var(--sp-font-size-body);
    line-height: 18px;
    letter-spacing: var(--sp-font-tracking-tight);
}

.card-photo--profile .stat-block-label{
    font-size: var(--sp-font-size-12);
    font-weight: var(--sp-font-weight-body);
    line-height: 15px;
    letter-spacing: var(--sp-font-tracking-tight);
    white-space: nowrap;
}

.card-photo--profile .stat-block-glyphs{
    gap: 6px;
    height: 18px;
}

.card-photo--profile .stat-block-glyphs svg{
    width: 15px;
    height: 15px;
}

/* Nœud d'agenda ou d'activité du PROFIL (les tableaux de bord gardent la leur) : la date en
   puce brune 13/16 semibold, la phrase en 14/17 */
.profile-pane .timeline--agenda .timeline-label{
    display: inline-flex;
    align-items: center;
    gap: 3px;
    padding: 3px 6px;
    border-radius: var(--sp-radius-sm);
    background-color: var(--sp-color-bg-sunken);
    font-size: var(--sp-font-size-meta);
    font-weight: var(--sp-font-weight-title);
    line-height: 16px;
    letter-spacing: var(--sp-font-tracking-meta);
    color: var(--sp-color-text-brown);
}

/* L'évènement d'un nœud d'agenda : vignette de 56px, et la cloche remonte sur la ligne de la
   date, en disque crème de 24px (maquette) */
.profile-pane .timeline--agenda .list-item{
    position: relative;
    padding-bottom: 0;
}

/* Un nœud ne porte qu'un évènement : le filet de ligne n'y sépare rien */
.profile-pane .timeline--agenda .list-item::after{
    content: none;
}

.profile-pane .timeline--agenda .list-item .list-item-thumb{
    flex: 0 0 56px;
    width: 56px;
    height: 56px;
}

.profile-pane .timeline--agenda .list-item .list-item-action{
    position: absolute;
    min-height: 0;
    padding: 0;
    top: calc(-1 * (var(--sp-space-2) + var(--timeline-agenda-header) / 2 + 12px));
    right: 0;
    z-index: 2;
    width: 24px;
    height: 24px;
    min-width: 0;
    margin: 0;
    border-radius: var(--sp-radius-full);
    background-color: var(--sp-color-bg-sunken);
    color: var(--sp-color-text-brown);
}

.profile-pane .timeline--agenda .list-item .list-item-action svg{
    width: 14px;
    height: 14px;
}

.activity-line{
    margin: 0 0 var(--sp-space-2);
    font-size: var(--sp-font-size-label);
    font-weight: var(--sp-font-weight-prose);
    line-height: 17px;
    letter-spacing: var(--sp-font-tracking-tight);
    color: var(--sp-color-text-default);
}

/* L'évènement d'une activité en bold, comme le nom dans « Activités récentes de Charles »
   (maquette PROFILE, mobile et desktop) */
.activity-line a{
    font-weight: var(--sp-font-weight-bold);
    text-decoration: none;
    color: inherit;
}

/* Aperçu d'une activité : trois vignettes de 80px à 8px, puis ce qui reste en clair */
.activity-preview{
    display: flex;
    align-items: center;
    gap: var(--sp-space-2);
}

.activity-preview-thumb{
    flex: 0 1 80px;
    aspect-ratio: 1;
    overflow: hidden;
    border-radius: var(--sp-radius-md);
}

.activity-preview-thumb img{
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.activity-preview-more{
    padding: 10px;
    font-size: var(--sp-font-size-body);
    font-weight: var(--sp-font-weight-prose);
    line-height: 18px;
    letter-spacing: var(--sp-font-tracking-tight);
    color: var(--sp-color-text-caption);
    text-decoration: none;
}

/* Desktop : contenu de 1100px, colonne d'identité de 394px, 24px entre les deux */
@media (min-width: 992px) {
    .container.profile-page{
        max-width: calc(var(--sp-layout-content-profile) + var(--bs-gutter-x));
    }

    .profile-page > .row{
        --bs-gutter-x: var(--sp-space-6);
        flex-wrap: nowrap;
    }

    .profile-page > .row > .col-lg-4{
        flex: 0 0 calc(394px + var(--bs-gutter-x));
        width: calc(394px + var(--bs-gutter-x));
        max-width: 42%;
    }

    .profile-page > .row > .col-lg-8{
        flex: 1 1 0;
        width: auto;
        min-width: 0;
    }
}

@media (max-width: 991.98px) {
    /* Trois onglets en colonnes égales, l'actif en pastille de 31px, filet dessous */
    .profile-tabs{
        flex-wrap: nowrap;
        gap: var(--sp-space-6);
        width: auto;
        margin: 0 6px;
        padding: var(--sp-space-4) 0 10px;
    }

    .profile-tabs .nav-item{
        display: flex;
        flex: 1 1 0;
        justify-content: center;
    }

    .profile-tabs .nav-link{
        height: 31px;
        padding: 6px 18px;
        border-radius: var(--sp-radius-md);
    }

    /* Un seul volet à la fois, posé à même le fond : ni carte, ni en-tête de section */
    .profile-pane:not(.active){
        display: none;
    }

    .profile-pane.card{
        margin-bottom: 0 !important;
        padding: 0;
        border: 0;
        border-radius: 0;
        background: none;
        box-shadow: none;
    }

    .profile-pane-lead{
        margin: 0;
        padding: var(--sp-space-6) 0;
        font-size: var(--sp-font-size-body);
        font-weight: var(--sp-font-weight-prose);
        line-height: 18px;
        letter-spacing: var(--sp-font-tracking-tight);
        color: var(--sp-color-text-default);
    }

    .profile-pane-lead strong{
        font-weight: var(--sp-font-weight-bold);
    }

    #profile-photos .photo-filter-bar{
        margin-top: var(--sp-space-4);
    }
}

/* --- Galerie évènement (retour client, septembre 2026) -------------------------------------
   Le hero, ses actions, les panneaux Albums et Photographes, la frise et l'encart d'attente. */

/* Hero : le scrim respire comme la carte de l'accueil (6px entre sport, titre et méta), le
   chevron du retour se centre dans son disque à 18, la double icône fait 40 comme lui, et le
   hero laisse 20px au contenu qui suit. */
.event-highlighted-header--page .event-highlighted-scrim{
    gap: 6px;
}

.event-highlighted-header--page .event-hero-back svg{
    width: 18px;
    height: 18px;
}

@media (max-width: 991.98px) {
    .event-highlighted-header--page .glass-group-item{
        width: 40px;
        min-width: 40px;
        height: 40px;
        min-height: 40px;
    }

    .event-highlighted-header--page.mb-4{
        margin-bottom: var(--sp-space-5) !important;
    }

    /* Les chips de la galerie vont bord à bord, comme celles de l'accueil */
    .photo-filter-bar .filter-chips{
        margin-left: calc(var(--bs-gutter-x, 1.5rem) * -.5);
        margin-right: calc(var(--bs-gutter-x, 1.5rem) * -.5);
        padding-left: calc(var(--bs-gutter-x, 1.5rem) * .5);
        padding-right: calc(var(--bs-gutter-x, 1.5rem) * .5);
        scroll-padding-left: calc(var(--bs-gutter-x, 1.5rem) * .5);
    }
}

/* Le « … » : ses deux entrées s'espacent (retour client) */
.menu-overlay.show{
    gap: var(--sp-space-4);
}

/* La pastille d'annonce d'une chip : 6px, et 8px jusqu'au mot (retour client) */
.chip-dot{
    width: 6px;
    height: 6px;
    margin-right: var(--sp-space-1);
}

/* Le cadenas d'un album protégé dans la méta d'une journée */
.timeline-meta-lock{
    vertical-align: -1px;
}

/* En-têtes « Photos » et « Photographes » : 16px jusqu'à leur carte, le décompte en 15/500
   centré sur la ligne du titre (retour client) */
.event-page .row .sec-header{
    margin-bottom: var(--sp-space-4);
}

.sec-header-title-count{
    align-self: center;
    font-size: var(--sp-font-size-body);
}

/* L'encart d'attente : un pointillé tracé en SVG, qui suit les coins arrondis — quatre dégradés
   répétés s'arrêtaient net dans les angles (retour client, « pointillé problème dans les
   angles »). Trait de 2 dont la moitié est rognée par le bord : un pointillé d'1px. */
.event-empty-panel,
.timeline-awaiting{
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'%3E%3Crect width='100%25' height='100%25' fill='none' rx='16' ry='16' stroke='%23D3CDC3' stroke-width='2' stroke-dasharray='4 4'/%3E%3C/svg%3E");
    background-size: 100% 100%;
    background-position: 0 0;
}

/* Cartes des photographes inscrits (maquette) : le nom en 16/600, la méta en 13/500 estompée,
   et le « Moi » sur crème */
.event-photographer-card .list-item-meta{
    font-weight: var(--sp-font-weight-body);
    color: var(--sp-color-text-muted);
}

/* Panneau Albums : ombre des journées plus légère, chevron plus épais */
.album-group-head{
    box-shadow: 0 1px 2px rgba(0, 0, 0, .05);
}

.album-group-chevron svg{
    width: 14px;
    height: 14px;
}

/* Panneau Photographes : la carte cochée passe sur le crème du panneau (retour client :
   « background cream ») ; le nombre de photos en semibold */
.filter-list-cards .filter-row--card:has(:checked){
    border-color: var(--sp-color-bg-cream);
    background-color: var(--sp-color-bg-cream);
}

.filter-row--card .filter-row-meta strong{
    font-weight: var(--sp-font-weight-title);
}

/* Le rail de la frise s'éteint en dégradé vers le nœud de fin (retour client) */
.timeline-item:nth-last-child(2) .timeline-marker::before{
    background: linear-gradient(to bottom, var(--sp-color-border-default) 60%, transparent);
}

/* L'en-tête compact de la frise passe en verre (retour client) : il survole des photos */
.timeline-sticky{
    background-color: var(--sp-glass-overlay-pill);
    backdrop-filter: blur(var(--sp-glass-blur));
    -webkit-backdrop-filter: blur(var(--sp-glass-blur));
    border: var(--sp-glass-search-border);
    box-shadow: var(--sp-glass-overlay-lift);
}

/* La demande de mot de passe d'un album, en panneau ancré (retour client) : la carte perd son
   fond et sa gouttière, le panneau les porte ; « Annuler » et « Valider » se partagent le pied */
.album-unlock-sheet .album-unlock{
    max-width: none;
    padding: 0;
    background: none;
    box-shadow: none;
    gap: var(--sp-space-4);
}

.album-unlock-sheet .album-unlock-foot{
    display: flex;
    gap: 10px;
    margin: 0 calc(-1 * var(--sp-space-6)) calc(-1 * var(--sp-space-6));
}

.album-unlock-sheet .album-unlock-foot .btn{
    flex: 1;
}

@media (max-width: 991.98px) {
    .album-unlock-sheet .album-unlock-foot{
        margin-left: -18px;
        margin-right: -18px;
    }
}

@media (min-width: 992px) {
    .album-unlock-anchor .filter-panel{
        min-width: 420px;
        max-width: 480px;
    }
}

/* --- Vue photo (retour client, septembre 2026) ---------------------------------------- */

/* Un seul voile sur la photo, sombre aux deux bouts (maquette) : la barre et le compteur
   n'ont plus chacun leur scrim */
.photo-stage::before{
    content: '';
    position: absolute;
    inset: 0;
    z-index: 1;
    background: var(--sp-glass-photo-veil);
    pointer-events: none;
}

.photo-stage-bar,
.photo-stage-carousel{
    background: none;
}

/* Les actions sur la photo font 40px (retour client), le chevron du retour 18 */
@media (max-width: 991.98px) {
    .photo-stage-bar .btn-glass{
        width: 40px;
        height: 40px;
        min-width: 40px;
        min-height: 40px;
    }

    .photo-stage-actions{
        height: 40px;
    }

    .photo-stage-action{
        height: 40px;
        min-height: 40px;
        width: 36px;
        min-width: 36px;
    }
}

.photo-stage-bar .btn-glass svg{
    width: 18px;
    height: 18px;
}

/* Le compteur, à plat (retour client) : noir à 50 % sous un flou, coins de 8, 28px de haut,
   position en 13/600, total en 10/500, blanc pur — ni liseré, ni lentille, ni ombre */
.photo-stage-counter{
    height: 28px;
    padding: 0 var(--sp-space-2);
    border-radius: var(--sp-radius-sm);
    background-color: var(--sp-glass-button-bg);
    box-shadow: none;
    font-size: var(--sp-font-size-meta);
    font-weight: var(--sp-font-weight-title);
    line-height: 16px;
    color: var(--sp-color-text-inverse);
}

.photo-stage-counter::before,
.photo-stage-counter::after{
    content: none;
}

.photo-stage-counter-total{
    font-size: 10px;
    font-weight: var(--sp-font-weight-body);
    opacity: 1;
}

/* Les points se calent sur le bas du compteur */
.photo-stage-dots{
    top: auto;
    bottom: calc(var(--sp-space-4) + 4px);
    transform: translateX(-50%);
}

/* Le ruban : les voisines reculent à 60 % (retour client) */
.photo-filmstrip .photo-filmstrip-item:not(.is-current):not(:hover):not(:focus-visible){
    opacity: .6;
}

/* Sur mobile, la carte se borne entre 0,8 et 1,25 (retour client) : une panoramique ne laisse
   plus les actions superposées sur une bande, un portrait ne mange plus l'écran. C'est
   l'exception assumée à « la photo n'est jamais rognée » ; la Dialog plein écran la répare. */
@media (max-width: 767.98px) {
    .photo-stage[style*="--photo-ratio"]{
        display: block;
        width: 100%;
        aspect-ratio: clamp(0.8, var(--photo-ratio), 1.25);
    }

    .photo-stage[style*="--photo-ratio"] img{
        width: 100%;
        height: 100%;
        max-width: none;
        object-fit: cover;
    }
}

/* Les CTA d'acquisition : 48px, 15/600, une portée courte et un reflet à peine (retour client).
   Le sélecteur double la classe : « Acheter en HD » vit dans un formulaire, et
   `.photo-actions form .btn` (0,2,1) lui donnait 16px par-dessus cette règle (0,2,0). */
.photo-actions .btn.btn-acquire{
    min-height: 48px;
    font-size: var(--sp-font-size-body);
    font-weight: var(--sp-font-weight-title);
    letter-spacing: var(--sp-font-tracking-tight);
    background-image: var(--sp-glass-cta-sheen);
    box-shadow: var(--sp-shadow-cta);
}

/* Le point entre le libellé et le prix : 3px, rond, blanc */
.photo-price-dot{
    display: inline-block;
    width: 3px;
    height: 3px;
    flex: 0 0 auto;
    border-radius: var(--sp-radius-full);
    background-color: currentColor;
}

/* Le partage : disque de 48 sur le creux crème, glyphe de 16×21 */
.photo-actions .btn-share{
    width: 48px;
    height: 48px;
    min-width: 48px;
    min-height: 48px;
    --bs-btn-bg: var(--sp-color-bg-sunken);
    --bs-btn-border-color: var(--sp-color-bg-sunken);
    --bs-btn-hover-bg: var(--sp-color-bg-sunken);
    --bs-btn-hover-border-color: var(--sp-color-bg-sunken);
}

/* « Dans le panier » : le creux crème, le brun estompé en 16/600, la coche */
.photo-actions .btn-cart-in{
    min-height: 48px;
    --bs-btn-bg: var(--sp-color-bg-sunken);
    --bs-btn-border-color: var(--sp-color-bg-sunken);
    --bs-btn-color: var(--sp-color-text-caption);
    --bs-btn-disabled-bg: var(--sp-color-bg-sunken);
    --bs-btn-disabled-border-color: var(--sp-color-bg-sunken);
    --bs-btn-disabled-color: var(--sp-color-text-caption);
    --bs-btn-disabled-opacity: 1;
    font-size: var(--sp-font-size-16);
    font-weight: var(--sp-font-weight-title);
    letter-spacing: var(--sp-font-tracking-tight);
}

/* Les onglets de la vue photo suivent ceux de l'accueil : pilule active sur le creux soutenu */
.photo-tabs{
    --bs-nav-pills-link-active-bg: var(--sp-color-bg-sunken-strong);
}

/* L'onglet Offres repose sur le violet pâle de la remise (retour client) */
.photo-offers{
    background-color: var(--sp-color-accent-deal-soft);
}

/* Aperçu à 100 % (retour client) : une fenêtre de 220px sur le tirage servi à sa taille, centré */
.photo-zoom-crop{
    position: relative;
    height: 220px;
    margin-bottom: var(--sp-space-4);
    border-radius: var(--sp-radius-lg);
    overflow: hidden;
    background-color: var(--sp-color-bg-sunken);
}

.photo-zoom-crop img{
    position: absolute;
    top: 50%;
    left: 50%;
    width: auto;
    height: auto;
    max-width: none;
    transform: translate(-50%, -50%);
    /* Bord à bord (retour client CL-03) : un carré plus petit que la fenêtre s'agrandit pour la
       couvrir, recadré sans déformation — la fenêtre reste un extrait, la modale montre le 100 %. */
    min-width: 100%;
    min-height: 100%;
    object-fit: cover;
}

.photo-zoom-label{
    position: absolute;
    top: var(--sp-space-3);
    left: var(--sp-space-3);
    z-index: 1;
    padding: 6px var(--sp-space-3);
    background-color: var(--sp-glass-button-bg);
    backdrop-filter: blur(var(--sp-glass-overlay-blur));
    -webkit-backdrop-filter: blur(var(--sp-glass-overlay-blur));
    font-size: var(--sp-font-size-body);
}

/* La photo en grand (retour client) : sur le crème, pleine largeur, sans coin, la croix au-dessus */
.photo-zoom .modal-content{
    background-color: var(--sp-color-bg-default);
    border: 0;
    border-radius: 0;
}

.photo-zoom-head{
    display: flex;
    justify-content: flex-end;
    padding: var(--sp-space-2) var(--sp-space-3);
}

.photo-zoom-close{
    background-color: var(--sp-color-bg-surface);
    box-shadow: var(--sp-shadow-sm);
    color: var(--sp-color-text-default);
}

.photo-zoom-body{
    display: flex;
    align-items: center;
    justify-content: center;
    flex: 1;
    min-height: 0;
    overflow: auto;
}

.photo-zoom-body img{
    display: block;
    width: 100%;
    height: auto;
    max-width: none;
}

/* Plein écran : ni clic droit (nocontext, sur toute la fenêtre), ni appui long qui proposerait
   « Enregistrer l'image » sur iOS — Safari ne passe pas par `contextmenu` (retour client) */
.photo-zoom .modal-content{
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    user-select: none;
}

@media (min-width: 992px) {
    .photo-zoom-body img{
        width: auto;
        max-width: 100%;
        max-height: calc(100vh - 60px);
    }
}

/* L'aperçu de netteté (retour client) : le centre de l'original à 100 %, jamais réduit ;
   le corps défile si l'écran est plus petit que le carré — d'où le centrage par la marge, que
   le défilement atteint des deux côtés, au lieu de celui du flex qui couperait le bord gauche. */
.photo-zoom--actual .photo-zoom-body{
    align-items: flex-start;
    justify-content: flex-start;
}

.photo-zoom--actual .photo-zoom-body img,
.photo-zoom--actual .photo-zoom-body img[src]{
    width: auto;
    max-width: none;
    max-height: none;
    margin: auto;
}

button.photo-zoom-crop{
    display: block;
    width: 100%;
    padding: 0;
    border: 0;
    cursor: zoom-in;
}

/* Le loader Spicto et sa légende brune tant que le carré se découpe (retour client) */
.photo-zoom-pending{
    position: absolute;
    inset: 0;
    display: none;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--sp-space-2);
    color: var(--sp-color-text-brown);
    font-size: var(--sp-font-size-14);
    font-weight: var(--sp-font-weight-500);
}

.photo-zoom-crop.is-loading .photo-zoom-pending{
    display: flex;
}

/* Dans un bouton, le loader s'écrit en span : son rotor doit redevenir un bloc */
.photo-zoom-pending .spicto-loader,
.photo-zoom-pending .spicto-loader-rotor{
    position: relative;
    top: auto;
    left: auto;
    display: block;
    margin: 0;
}

/* --- Profil public (retour client, septembre 2026) ------------------------------------ */

/* Une vignette d'un album protégé : floutée sous un cadenas (photos d'un profil, activités) */
.photo-tile--locked{
    position: relative;
}

.photo-tile--locked img{
    filter: blur(6px);
    transform: scale(1.12);
}

.photo-tile-lock{
    position: absolute;
    top: var(--sp-space-2);
    right: var(--sp-space-2);
    z-index: 1;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    border-radius: var(--sp-radius-full);
    background-color: var(--sp-glass-button-bg);
    color: var(--sp-color-text-inverse);
}

/* La bio se ferme d'une croix, au coin haut droit de sa carte */
.profile-bio{
    position: relative;
    padding-right: var(--sp-space-12);
}

.profile-bio-close{
    position: absolute;
    top: var(--sp-space-1);
    right: var(--sp-space-1);
    width: 36px;
    height: 36px;
    min-width: 36px;
    min-height: 36px;
    color: var(--sp-color-text-default);
}

/* Instagram et partage reprennent la pilule de verre clair de la vue photo, de 40px */
.card-photo--profile .card-photo-actions .glass-group,
.card-photo--profile .card-photo-actions .btn-glass{
    height: 40px;
    background-color: var(--sp-glass-button-bg-light);
    border: 0;
    background-image: none;
}

.card-photo--profile .card-photo-actions .glass-group{
    padding: 0 3px;
}

.card-photo--profile .card-photo-actions .glass-group-item{
    width: 36px;
    height: 40px;
}

.card-photo--profile .card-photo-actions .btn-glass{
    width: 40px;
    min-width: 40px;
    min-height: 40px;
}

/* Moins d'air au-dessus des onglets et sous leur filet (retour client) */
@media (max-width: 991.98px) {
    .profile-page .card-photo--profile.mb-4{
        margin-bottom: var(--sp-space-3) !important;
    }

    .profile-page .profile-bio.mb-4{
        margin-bottom: var(--sp-space-3) !important;
    }

    .profile-tabs{
        padding: var(--sp-space-2) 0 var(--sp-space-2);
        margin-bottom: var(--sp-space-2);
    }
}

/* --- Panier (retour client, septembre 2026) ------------------------------------------- */

/* Sous 992px le panneau couvre l'écran : pas de voile derrière lui, il teintait les barres du
   téléphone en sombre — les « bandes noires » (même remède que le menu). */
@media (max-width: 991.98px) {
    body:has(#offcanvasCart.show) > .offcanvas-backdrop{
        --bs-backdrop-opacity: 0;
    }

    /* Le logotype et la croix remontent : l'en-tête ne garde que 8px au-dessus */
    #offcanvasCart .cart-header{
        padding-top: var(--sp-space-2);
        min-height: 0;
    }
}

/* L'offre reprend la carte de l'onglet Offres, sur son violet pâle ; ses vignettes s'alignent */
.cart-offer .photo-offers{
    background-color: var(--sp-color-accent-deal-soft);
}

.cart-offer .photo-offers-thumb img{
    width: 100%;
    aspect-ratio: 1;
    object-fit: cover;
    border-radius: var(--sp-radius-md);
}

/* --- Menu, connexion, téléchargement (retour client, septembre 2026) ------------------ */

/* L'avatar de la barre haute est un bouton : il ouvre le menu */
.topbar-avatar{
    padding: 0;
    border: 0;
    background: none;
}

/* La sortie du menu : carré arrondi blanc de 36, glyphe épais */
.mobile-menu-logout{
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    padding: 0;
    border: 0;
    border-radius: var(--sp-radius-md);
    background-color: var(--sp-color-bg-surface);
    box-shadow: var(--sp-shadow-sm);
    color: var(--sp-color-text-default);
}

.mobile-menu-space .btn-light.mobile-menu-create{
    margin-bottom: var(--sp-space-4);
}

/* Le verrou de marque dans le bouton « Passer à Spicto Pro » se cale sur le mot */
.mobile-menu-space .btn .pro-lockup{
    vertical-align: middle;
}

/* Retours client d'octobre sur le menu : boutons un peu plus hauts (36 → 40), et le verrou
   Spicto Pro ramené à la hauteur du texte — les cotes du compteur de photos (.quota-card),
   pour un seul verrou réduit dans l'espace pro. */
.mobile-menu-space .btn{
    height: 40px;
}

.mobile-menu-space .btn .pro-lockup-logotype{
    height: 12px;
}

.mobile-menu-space .btn .pro-lockup-seal svg{
    width: 13px;
    height: 13px;
}

.mobile-menu-space .btn .pro-lockup-tier{
    font-size: 10px;
}

/* Sur desktop, le menu n'est plus un panneau de toute la hauteur mais une carte flottante sous
   l'en-tête, plus étroite, au bord droit de la page, ombre 0 4 20 noir 15 % (relevé du
   client) — le même menu que l'accueil, dans l'espace pro aussi. Ni voile ni en-tête : le
   logotype est déjà dans la barre, un clic à côté ou Échap le referme. */
@media (min-width: 992px) {
    /* Élargi au quart de la fenêtre (retour client), jamais sous 425px (340 + 25 %). */
    .mobile-menu.offcanvas-end{
        --bs-offcanvas-width: max(425px, 25vw);
        top: 60px;
        right: 24px;
        bottom: auto;
        height: auto;
        max-height: calc(100dvh - 76px);
        border-radius: var(--sp-radius-xl);
        box-shadow: var(--sp-shadow-suggest);
        overflow: hidden;
    }

    .mobile-menu .offcanvas-header{
        display: none;
    }

    .mobile-menu .offcanvas-body{
        padding-top: var(--sp-space-4);
    }

    body:has(.mobile-menu.show) > .offcanvas-backdrop.show{
        opacity: 0;
    }
}

/* Le bouton du visiteur centre son libellé (retour client) */
.mobile-menu-foot .btn{
    display: inline-flex;
    align-items: center;
    justify-content: center;
    line-height: 18px;
}

/* Connexion : sur desktop les deux options du sélecteur se partagent la largeur, moitié
   chacune, et l'ombre de l'active s'allège (retour client) ; le filet du bouton Google
   s'épaissit à 1,5px. Le partage vaut dès 576px : la tablette reprend la carte du desktop. */
.login-toggle .toggle-btn.active{
    box-shadow: var(--sp-shadow-sm);
}

@media (min-width: 576px) {
    .login-toggle .toggle-btn,
    .login-toggle .toggle-btn.active{
        flex: 1 1 0;
        min-width: 0;
    }
}

/* Sous 360px, la pastille active de 169 et « Club & Associations » d'un seul tenant demandaient
   330px quand la carte en offre 288 : la page débordait de 15px à 320. Les deux boutons se
   partagent la largeur, et un libellé long passe sur deux lignes — la pastille de 52 les loge. */
@media (max-width: 359.98px) {
    .login-toggle .toggle-btn,
    .login-toggle .toggle-btn.active,
    .login-toggle .toggle-btn:not(.active){
        flex: 1 1 0;
        min-width: 0;
        padding-left: var(--sp-space-2);
        padding-right: var(--sp-space-2);
        white-space: normal;
        text-align: center;
        line-height: 16px;
    }
}

.gsi-material-button{
    border-width: 1.5px;
}

/* --- Connexion au plus près de la maquette (Figma 1806:10438 mobile, 2488:21292 desktop) -- */

/* Le conteneur de la page : sans marge sous 576, 24px au-dessus (les px-0 px-sm-4 qu'il
   portait), pleine largeur sur desktop (plus bas). */
.login-container{
    padding-left: 0;
    padding-right: 0;
}

@media (min-width: 576px) {
    .login-container{
        padding-left: var(--sp-space-6);
        padding-right: var(--sp-space-6);
    }
}

/* Mobile : l'en-tête de 77px part du haut de l'écran, comme sous la barre d'état de la
   maquette — la carte ne pose plus 16px au-dessus. */
@media (max-width: 575.98px) {
    .login-card{
        padding-top: 0;
    }
}

/* Tablette (576–991px, sans maquette) : la photo de fond paraît dès 576px, et la carte
   transparente du mobile y laissait le texte sur la photo. Elle reprend la carte du desktop,
   centrée. */
@media (min-width: 576px) and (max-width: 991.98px) {
    .login-card{
        --bs-card-bg: var(--sp-color-bg-surface);
        --bs-card-spacer-x: var(--sp-space-12);
        width: 579px;
        max-width: 100%;
        margin-left: auto;
        margin-right: auto;
        padding-top: 19px;
        padding-bottom: var(--sp-space-10);
        border: 0;
        border-radius: var(--sp-radius-3xl);
        box-shadow: var(--sp-shadow-float);
    }
}

/* En-tête : le logotype à 25px du bord (padding 4px 25px de HEADER_BAR, 1px de plus que le
   contenu), la croix centrée sur la case de 24 de la maquette — son bouton de 44 déborde de
   10px dans la marge. */
.login-head{
    padding-left: 1px;
    padding-right: 1px;
}

.login-help{
    margin-right: -10px;
}

/* Les intervalles de la maquette : 23 sous le titre (la règle h1 des espaces pro, plus
   spécifique, lui en donnait 24), 16 entre la phrase et l'étiquette (en inline-block, celle-ci
   prenait 1px de la ligne de son parent), 12 entre le bouton Google et les mentions. */
.login-card h1.login-title{
    margin-bottom: 23px;
}

.login-label{
    display: block;
}

.login-card .auth-buttons{
    margin-bottom: var(--sp-space-3);
}

/* L'invite du champ : 14/22 medium brune, +0,01em (le gris des espaces pro la recouvrait). Sous
   768px le champ garde ses 16px, qui évitent le zoom d'iOS au focus : seule l'invite prend la
   cote de la maquette. */
.login-card .form-control.login-input::placeholder{
    color: var(--sp-color-text-brown);
    font-size: var(--sp-font-size-label);
    letter-spacing: .01em;
}

/* Bouton Google : logo et libellé groupés au centre, 8px entre eux ; libellé en Inter 600 (il
   demandait Roboto, jamais chargée, et sortait en Arial 500) ; filet #4D4D4F de la maquette, dans
   l'épaisseur de 1,5px du retour client. */
.gsi-material-button{
    border-color: #4D4D4F;
}

.gsi-material-button .gsi-material-button-content-wrapper{
    justify-content: center;
    gap: var(--sp-space-2);
}

.gsi-material-button .gsi-material-button-icon{
    margin-right: 0;
}

.gsi-material-button .gsi-material-button-contents{
    flex-grow: 0;
    font-family: var(--sp-font-family-base), sans-serif;
    font-weight: var(--sp-font-weight-title);
}

@media (min-width: 992px) {
    /* Un voile noir de 49 % côté accroche, qui s'efface vers la droite */
    main.login-backdrop{
        background-image: linear-gradient(270deg, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, .49) 100%), var(--bg-wallpaper);
    }

    /* Pleine largeur : l'accroche à 64px du bord gauche, la carte à 109 du bord droit (au 1512
       de la maquette, au prorata en dessous). La carte à 82px du haut : centrée dans la hauteur
       moins 44px. L'accroche se cale 103px au-dessus du pied de la carte. */
    .login-container{
        max-width: none;
        padding-left: min(64px, 4.233vw);
        padding-right: min(109px, 7.209vw);
        padding-bottom: 44px;
    }

    .login-pitch{
        margin-top: auto;
        margin-bottom: 103px;
    }

    .login-pitch .lead-xl{
        letter-spacing: var(--sp-font-tracking-tight);
    }
}

/* Le sélecteur en deux moitiés égales dès 576px (241,5 + 241,5 sur la carte desktop, retour
   client) : les deux options portent la même gouttière totale — la base flex compte le
   padding, l'option retenue s'élargissait sinon de 32px. L'autre option garde le décalage de
   4px vers la gauche de la maquette (24/32) ; les libellés tiennent sur une ligne même dans
   une moitié étroite (carte de 992px, « Club & Associations » retenu). */
@media (min-width: 576px) {
    .login-toggle .toggle-btn,
    .login-toggle .toggle-btn.active{
        white-space: nowrap;
    }

    .login-toggle .toggle-btn.active{
        padding-left: var(--sp-space-3);
        padding-right: var(--sp-space-3);
    }

    .login-toggle .toggle-btn:not(.active){
        padding-left: var(--sp-space-2);
        padding-right: var(--sp-space-4);
    }
}

/* Le retour en pilule (téléchargement, livraison) : blanc sous une ombre douce, flèche puis mot */
.btn-back-pill{
    display: inline-flex;
    align-items: center;
    gap: var(--sp-space-2);
    height: 40px;
    padding: 0 var(--sp-space-4) 0 var(--sp-space-3);
    border-radius: var(--sp-radius-full);
    --bs-btn-bg: var(--sp-color-bg-surface);
    --bs-btn-border-color: var(--sp-color-bg-surface);
    --bs-btn-hover-bg: var(--sp-color-bg-surface);
    --bs-btn-hover-border-color: var(--sp-color-bg-surface);
    --bs-btn-color: var(--sp-color-text-default);
    --bs-btn-hover-color: var(--sp-color-text-default);
    box-shadow: var(--sp-shadow-md);
    font-size: var(--sp-font-size-body);
    font-weight: var(--sp-font-weight-title);
    letter-spacing: var(--sp-font-tracking-tight);
}

/* Téléchargement offert (maquette PHOTO_PAGE_FREE, 1782:7631) : sur mobile la pilule de retour
   suit l'en-tête à 1px, comme la rangée BUTTONS (padding 1px 16px 0) ; 24px en pied. Desktop
   inchangé, sans maquette. */
.download-page{
    max-width: 680px;
    padding-top: 1px;
    padding-bottom: var(--sp-space-6);
}

@media (min-width: 992px) {
    .download-page{
        padding-top: var(--sp-space-6);
    }
}

.download-title{
    margin: var(--sp-space-4) 0;
    font-size: var(--sp-font-size-h3);
    font-weight: var(--sp-font-weight-title);
    line-height: 24px;
    letter-spacing: var(--sp-font-tracking-tighter);
}

/* L'ombre des photos des pages de téléchargement, portée vers le haut (maquette : PAGE_DOWNLOAD
   et la livraison, 0 -4 5,1 noir 12 %) */
.download-photo{
    margin-bottom: var(--sp-space-4);
    border-radius: var(--sp-radius-2xl);
    overflow: hidden;
    box-shadow: 0 -4px 5.1px rgba(0, 0, 0, .12);
}

.download-photo img{
    display: block;
    width: 100%;
    height: auto;
}

.download-actions{
    margin-bottom: var(--sp-space-4);
}

.download-rule{
    margin: var(--sp-space-4) 0;
    border: 0;
    border-top: .5px solid var(--sp-color-border-default);
    opacity: 1;
}

/* La publicité entre ses deux filets d'un demi-pixel, à 12px de chacun (maquette) : son
   enveloppe par défaut (my-4) l'en écartait de 24. Sans encart, les deux filets gardent leurs
   16px. */
.download-ad{
    margin: var(--sp-space-3) 0;
}

.download-rule:has(+ .download-ad){
    margin-bottom: 0;
}

.download-ad + .download-rule{
    margin-top: 0;
}

/* Le lien de connexion envoyé : la Dialog empile son image, son texte et son bouton */
.dialog--login-sent .dialog-body{
    display: flex;
    flex-direction: column;
    gap: var(--sp-space-4);
}

/* --- Recherche plein écran (retour client, septembre 2026) ---------------------------- */

/* La croix qui vide le champ : à droite dans la barre, un disque de 28 sur le creux crème */
.search-bar{
    position: relative;
}

.search-clear{
    position: absolute;
    top: 50%;
    right: var(--sp-space-2);
    z-index: 2;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    padding: 0;
    border: 0;
    border-radius: var(--sp-radius-full);
    background-color: var(--sp-color-bg-sunken);
    color: var(--sp-color-text-default);
    transform: translateY(-50%);
}

.search-clear[hidden]{
    display: none;
}

/* Rond plein noir à croix blanche (retour client, image 19). Le sélecteur double la classe du
   groupe : la règle Bootstrap des `.input-group` remettait le rayon à zéro, d'où un carré. */
.input-group.search-bar > .search-clear{
    width: 18px;
    height: 18px;
    right: var(--sp-space-3);
    margin: 0;
    border-radius: 50% !important;   /* `.input-group > :not(:first-child)` vise les coins gauches, en plus spécifique */
    background-color: #1E1C1A;
    color: #FFFFFF;
}

.input-group.search-bar > .search-clear svg{
    width: 8px;
    height: 8px;
}

.search-bar:has(.search-clear:not([hidden])) .ts-control{
    padding-right: 44px !important;
}

/* Un glyphe de sport en ink sur blanc (retour client), pour la famille Sports */
.sport-badge-white{
    background-color: var(--sp-color-bg-surface);
    color: var(--sp-color-text-default);
    box-shadow: var(--sp-shadow-sm);
}

/* « et N de plus » : un renvoi texte, orange comme un lien, sous les deux premiers évènements */
.search-more-events{
    display: block;
    padding: var(--sp-space-2) 0 var(--sp-space-3);
    border: 0;
    background: none;
    font-size: var(--sp-font-size-label);
    font-weight: var(--sp-font-weight-body);
    color: var(--sp-color-text-link);
    text-align: left;
}

@media (max-width: 991.98px) {
    /* La barre et sa croix en verre (retour client), comme sur l'accueil. SANS flou sur la
       barre : un `backdrop-filter` en ferait le bloc conteneur du panneau de résultats, qui
       est fixé à l'écran et s'y écraserait — et sur le crème il n'y a rien à flouter. */
    .search-fullscreen-open > .search-bar,
    .search-fullscreen-close{
        background: var(--sp-glass-search-tint), var(--sp-color-bg-surface);
        border: var(--sp-glass-search-border);
        box-shadow: var(--sp-glass-search-shadow);
    }

    .search-fullscreen-close{
        backdrop-filter: blur(var(--sp-glass-blur));
        -webkit-backdrop-filter: blur(var(--sp-glass-blur));
    }

    /* Les familles en 15/500 */
    .search-fullscreen-tab{
        font-size: var(--sp-font-size-body);
        line-height: 18px;
    }

    /* Dans « Meilleurs résultats », les évènements au-delà des deux premiers se replient */
    .search-fullscreen-open[data-search-category="all"] .ts-dropdown-content.search-options--collapsed .option:not(.no-more-results):nth-child(n+3){
        display: none;
    }

    .search-fullscreen-open:not([data-search-category="all"]) .search-more-events{
        display: none;
    }

    /* Une famille ouverte se lit en grand : lieux et sports passent du chip à la ligne, glyphe
       de 40 ; dans « Meilleurs résultats » ils gardent leur petite forme (retour client) */
    .search-fullscreen-open:not([data-search-category="all"]) .search-suggestions-list:not(.search-suggestions-list--rows){
        flex-direction: column;
        align-items: stretch;
    }

    .search-fullscreen-open:not([data-search-category="all"]) .search-suggestions-item{
        gap: var(--sp-space-3);
        padding: var(--sp-space-2) 0;
        border-radius: 0;
        background: none;
        font-size: var(--sp-font-size-16);
        font-weight: var(--sp-font-weight-title);
        line-height: 19px;
    }

    .search-fullscreen-open:not([data-search-category="all"]) .search-suggestions-item .sport-badge{
        width: 40px;
        height: 40px;
    }

    .search-fullscreen-open:not([data-search-category="all"]) .search-suggestions-item .sport-badge svg{
        width: 18px;
        height: 18px;
    }
}

/* La ligne d'un photographe : portrait de 40, nom et méta empilés comme un ListItem */
.search-suggestions-row .avatar{
    width: var(--sp-avatar-md);
    height: var(--sp-avatar-md);
}

.search-suggestions-row-body{
    gap: 2px;
}

/* --- Tableau de bord photographe (retour client, septembre 2026) --------------------------- */

/* Le bandeau de la barre haute est suivi de space.6 (24px), plus des 48px de l'espace pro : le
   contenu commençait un demi-écran plus bas que sur le front (retour client). */
@media (min-width: 992px){
    .photographer-layout #top-bar,
    .club-layout #top-bar{
        margin-bottom: var(--sp-space-6);
    }
}

/* Les bulles se rangent EN LIGNE quand la largeur le permet (fiche message) : chacune garde la
   largeur de sa phrase, la rangée passe à la ligne au-delà. En verre clair — la teinte, le
   liseré et l'ombre de la barre de recherche —, comme des notifications de téléphone posées sur
   le fond (retour client). Le flou reste : dans la pile mobile, c'est lui qui rend les bulles de
   derrière à travers celle de devant. */
.dashboard-messages{
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: var(--sp-space-3);
}

.dashboard-messages .message{
    background: var(--sp-glass-search-tint), var(--sp-color-bg-surface);
    border: var(--sp-glass-search-border);
    box-shadow: var(--sp-glass-search-shadow);
}

/* Desktop : UNE rangée, quel que soit le nombre de bulles (retour client d'octobre) — elles
   gardent la largeur de leur phrase, celles qui ne tiennent pas filent sous un fondu à droite
   et se décalent vers la gauche à chaque fermeture. Le bloc ne grandit plus. La marge basse
   rend son ombre à la bulle, que le débordement masqué couperait. */
@media (min-width: 992px){
    .dashboard-messages{
        flex-wrap: nowrap;
        overflow: hidden;
        padding-bottom: 2px;
    }

    .dashboard-messages.mb-4{
        margin-bottom: calc(var(--sp-space-6) - 2px) !important;
    }

    .dashboard-messages > .message{
        flex: none;
    }

    .dashboard-messages.is-clipped{
        -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 80px), transparent);
        mask-image: linear-gradient(to right, #000 calc(100% - 80px), transparent);
    }
}

/* Pile mobile (fiche message, retour client) : la première bulle devant, les deux suivantes en
   retrait de 8 et 16px, réduites d'un cran, vidées de leur contenu — ce sont des BORDS, pas des
   messages ; les autres attendent, invisibles. « N autres messages » déplie tout. */
@media (max-width: 991.98px){
    .dashboard-messages.is-stacked{
        display: grid;
        grid-template-rows: auto auto;
        row-gap: var(--sp-space-6);
        align-items: stretch;   /* les bulles de derrière prennent la hauteur de celle de devant */
    }

    .dashboard-messages.is-stacked > .message{
        grid-area: 1 / 1;
        width: 100%;
        transform-origin: top center;
        transition: transform .2s ease;
    }

    .dashboard-messages.is-stacked > .message:nth-child(1){
        position: relative;
        z-index: 3;
    }

    .dashboard-messages.is-stacked > .message:nth-child(2){
        z-index: 2;
        transform: translateY(8px) scaleX(.96);   /* la largeur seule se réduit : la hauteur reste, et le bord dépasse de 8px */
    }

    .dashboard-messages.is-stacked > .message:nth-child(3){
        z-index: 1;
        transform: translateY(16px) scaleX(.92);
    }

    .dashboard-messages.is-stacked > .message:nth-child(n+2){
        pointer-events: none;
    }

    /* Le contenu des bulles de derrière ne prend PAS de place : elles s'étirent à la hauteur
       de celle de devant, et seuls leurs bords dépassent. */
    .dashboard-messages.is-stacked > .message:nth-child(n+2) > *{
        display: none;
    }

    .dashboard-messages.is-stacked > .message:nth-child(n+4){
        visibility: hidden;
    }

    .dashboard-messages.is-stacked > .message-stack-more{
        grid-row: 2;
    }
}

/* Le bouton qui déplie la pile : un lien de flux, à la taille de la méta, brun sur crème. */
.message-stack-more{
    align-self: center;
    justify-self: center;
    padding: 0;
    border: 0;
    background: none;
    font-size: var(--sp-font-size-meta);
    font-weight: var(--sp-font-weight-title);
    color: var(--sp-color-text-brown);
    text-decoration: underline;
    text-underline-offset: 3px;
}

/* --- Carte de profil (fiche card, variant photo — retour client) --- */

/* 235px, et le cerne de 4px à 25 % d'une carte photographique (shadow.photo) : sur le fond crème
   de l'espace connecté, la seule carte à porter une image porte aussi la seule ombre. */
.dashboard-view .card-photo{
    min-height: 235px;
    box-shadow: var(--sp-shadow-photo);
}

/* Le nom en 24/29 semibold, la ville en 14 medium (retour client). Le sélecteur dépasse
   `.photographer-layout h1:not(.page-title)` (0,2,1), qui dimensionne tous les h1 de l'espace,
   ET `#photographer-dashboard .h3` (1,1,0), qui ramène les titres de l'écran à 20px. */
#photographer-dashboard .card-photo h1.card-photo-name,
#club-dashboard .card-photo h1.card-photo-name,
.dashboard-view .card-photo h1.card-photo-name{
    font-size: var(--sp-font-size-h2-dense);
    line-height: 29px;
}

.dashboard-view .card-photo-meta{
    font-size: var(--sp-font-size-label);
    font-weight: var(--sp-font-weight-body);
}

/* Les légendes des chiffres : 13 medium, majuscule en tête (retour client). */
.dashboard-view .card-photo .stat-block-label{
    font-size: var(--sp-font-size-meta);
    font-weight: var(--sp-font-weight-body);
    line-height: 16px;
}

/* Espace photographe seulement : en regular depuis le retour d'octobre (« réduire le
   graissage ») — le chiffre au-dessus garde son semibold. Le club garde son medium. */
.photographer-layout.dashboard-view .card-photo .stat-block-label{
    font-weight: var(--sp-font-weight-400);
}

/* « Paramètres » en pill de verre, 32px, engrenage plein après le mot (retour client). */
.card-photo-settings{
    gap: var(--sp-space-2);
    min-height: 32px;
    padding: 0 var(--sp-space-3) 0 var(--sp-space-4);
    font-size: var(--sp-font-size-meta);
    font-weight: var(--sp-font-weight-body);
    display: inline-flex;
    align-items: center;
}

/* La carte et ses deux gestes : 16px entre chaque élément, 16px sous le bloc (retour client —
   « uniformiser l'espace entre les deux boutons et les widgets au-dessus et au-dessous »). */
.dashboard-identity{
    display: grid;
    gap: var(--sp-space-4);
    margin-bottom: var(--sp-space-4);
}

.dashboard-actions{
    gap: var(--sp-space-4);
}

/* Les deux gestes fondateurs : 50px de haut, coin de 16 (retour client, fiche button).
   Libellé et glyphe centrés dans la hauteur : en bloc, le texte restait collé en haut, 12px de
   vide dessous. Texte en 600 16/19 (maquette DASHBOARD 2670:17929), à toutes les largeurs. */
.btn-gesture{
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 50px;
    --bs-btn-border-radius: var(--sp-radius-lg);
    font-size: var(--sp-font-size-h4);
    font-weight: var(--sp-font-weight-title);
    line-height: 19px;
}

/* --- Agenda (fiche timeline, variant agenda — retour client) --- */

/* L'étiquette de journée : 13/16 semibold, brun `text.caption` sur le creux crème — le même
   dessin que les journées de l'onglet Activité (retour client). Ce n'est plus le ton neutral du
   Badge (ink) : sur la frise, la date jalonne, elle ne titre pas. */
.timeline--agenda .timeline-label{
    font-size: var(--sp-font-size-meta);
    font-weight: var(--sp-font-weight-title);
    line-height: 16px;
    color: var(--sp-color-text-caption);
}

/* Le rail s'éteint après le dernier nœud : un dégradé vers la transparence jusqu'au pied de la
   ligne, au lieu de s'arrêter net sur la pastille (retour client). */
.timeline--agenda .timeline-item:last-child .timeline-marker::before{
    content: "";
    position: absolute;
    left: 50%;
    top: calc(var(--timeline-agenda-header) / 2);
    height: calc(100% - var(--timeline-agenda-header) / 2);
    width: 1px;
    transform: translateX(-50%);
    background: linear-gradient(to bottom, var(--sp-color-border-default), transparent);
}

/* --- Cagnotte (fiche progress — retour client) --- */

/* La légende passe en medium, seul le montant garde le semibold : « Encore **12,50 €** avant
   votre prochain virement » (retour client). */
.progress-gauge-legend{
    font-weight: var(--sp-font-weight-body);
}

.progress-gauge-legend strong{
    font-weight: var(--sp-font-weight-title);
}

/* --- Quota « Photos déposées » (retour client, page de dépôt ET tableau de bord) --- */

#photographer-dashboard .quota-card .quota-title,
#club-dashboard .quota-card .quota-title,
.quota-card .quota-title .pro-seal{
    margin-left: 2px;
}

.quota-card .quota-title{
    font-size: var(--sp-font-size-h4);
    line-height: 19px;
    letter-spacing: -0.02em;
    margin-bottom: 0;
}

/* Le compte en 13 medium gris, numérateurs en bold — celui des restantes un cran plus sombre
   (retour client). Moins d'air sous la barre. */
.quota-figures{
    margin-top: 6px;
    font-weight: var(--sp-font-weight-body);
}

.quota-figures > span:last-child{
    color: var(--sp-color-text-muted);
}

.quota-figures strong{
    font-weight: var(--sp-font-weight-bold);
    color: var(--sp-color-text-muted);
}

.quota-figures > span:last-child strong{
    color: var(--sp-color-text-meta);
}

/* « Passez à » en 12 bold, le verrou Spicto Pro un cran plus petit, la promesse en 13 medium
   (retour client). */
.quota-card .pro-mention > strong{
    font-size: var(--sp-font-size-12);
    font-weight: var(--sp-font-weight-bold);
}

.quota-card .pro-lockup-logotype{
    height: 12px;
}

.quota-card .pro-lockup-seal svg{
    width: 13px;
    height: 13px;
}

.quota-card .pro-lockup-tier{
    font-size: 10px;
}

.quota-card .pro-mention-claim{
    font-size: var(--sp-font-size-meta);
    font-weight: var(--sp-font-weight-body);
}

/* --- Mes photos, Blog (retour client) --- */

/* Les légendes de la grille de chiffres : 12/16 medium, majuscule en tête. */
.stat-grid .stat-block-label{
    font-size: var(--sp-font-size-12);
    font-weight: var(--sp-font-weight-body);
}

/* Le texte de l'encart Blog : 14/20 medium, un texte qu'on lit. */
.card-sunken-text{
    font-size: var(--sp-font-size-label);
    font-weight: var(--sp-font-weight-body);
    line-height: 20px;
}

/* --- Lignes de transaction (DESIGNAPP — retour client) --- */

/* La valeur de tête de la méta en semibold, pas en bold de navigateur (retour client, DESIGNAPP). */
.transaction-row-detail strong{
    font-weight: var(--sp-font-weight-title);
}

/* Un filet entre les lignes (retour client). Les lignes se suivent à 0 — c'est leur padding qui
   fait l'écart de part et d'autre du trait : 16px depuis le retour d'octobre (« l'ensemble est
   trop serré »), et un filet plus clair, BROWN_BORDER_LIGHT, moins présent que le gris. */
.transaction-row + .transaction-row{
    margin-top: 0;
    border-top: 1px solid var(--sp-color-brown-border-light);
}

.transaction-row{
    padding-top: var(--sp-space-4);
    padding-bottom: var(--sp-space-4);
    border-radius: 0;
}

.transaction-row:first-child{
    padding-top: var(--sp-space-2);
}

.transaction-row:last-child{
    padding-bottom: var(--sp-space-2);
}

/* Date en 15 semibold, heure en 15 regular (retour client) */
.transaction-row-time{
    font-weight: var(--sp-font-weight-400);
}

/* Un peu d'air entre la date et sa ligne de détail (retour client) */
.transaction-row-detail{
    margin-top: var(--sp-space-1);
}

/* Le point médian prend de l'air de chaque côté (retour client) */
.transaction-row-sep{
    margin: 0 var(--sp-space-1);
}

/* Un transfert en cours est déjà une sortie : rouge comme les autres (retour client, maquette
   « - 123,49 € »), le point « en transit » de la pastille dit qu'il n'est pas arrivé. */
.transaction-row--pending .transaction-row-amount--out{
    color: var(--sp-color-transaction-amount-out);
}

/* La nature du mouvement dans la pastille : vente en glyphe ORANGE sur pêche, virement en
   glyphe `bank` vert-sarcelle sur menthe (retour client). La teinte classe, jamais le signe. */
.transaction-row-tile{
    position: relative;
}

.transaction-row-tile--sale{
    color: var(--sp-color-accent-selected);
}

.transaction-row-tile--payout{
    background-color: var(--sp-color-transaction-payout-bg);
    color: var(--sp-color-transaction-payout-glyph);
}

/* Un virement en cours : un point ink au coin de la pastille, portant la double flèche — l'argent
   est parti d'ici, il n'est pas encore arrivé là (retour client). Cerné de blanc pour se
   détacher de la menthe. */
.transaction-row-pending-dot{
    position: absolute;
    top: -4px;
    right: -4px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 14px;
    height: 14px;
    border-radius: var(--sp-radius-full);
    background-color: var(--sp-color-bg-dark);
    color: var(--sp-color-text-inverse);
    box-shadow: 0 0 0 2px var(--sp-color-bg-surface);
}

/* Le lien de téléchargement d'une vente, à copier (retour client) : un lien de flux en méta,
   sous la ligne de détail. */
.transaction-row-delivery{
    margin-top: 2px;
}

.transaction-row-link{
    display: inline-flex;
    align-items: flex-start;
    gap: var(--sp-space-1);
    text-align: left;
    padding: 0;
    border: 0;
    background: none;
    font-size: var(--sp-font-size-meta);
    font-weight: var(--sp-font-weight-body);
    line-height: 16px;
    color: var(--sp-color-text-meta);
    text-decoration: underline;
    text-underline-offset: 2px;
}

.transaction-row-link:hover{
    color: var(--sp-color-text-default);
}

/* --- Mes évènements, modification (retour client, septembre 2026) ------------------------ */

/* Un filet sous la barre de filtres : il sépare ce qui règle la page de ce qu'elle montre. */
.filter-bar-rule{
    margin: 0 0 var(--sp-space-6);
    border: 0;
    border-top: 1px solid var(--sp-color-border-default);
    opacity: 1;
}

/* Sur les tuiles de gestion et la carte de profil, le verre au repos prend le rendu qu'il avait
   au survol (retour client) : plus de voile noir, la lentille et le liseré seuls. Le survol
   répond alors par un voile clair. */
.event-highlighted-action--bar .btn-glass,
.dashboard-view .card-photo .btn-glass,
.card-photo--banner .btn-glass{
    background-color: transparent;
}

.event-highlighted-action--bar .btn-glass:hover,
.event-highlighted-action--bar .btn-glass:focus-visible,
.dashboard-view .card-photo .btn-glass:hover,
.dashboard-view .card-photo .btn-glass:focus-visible,
.card-photo--banner .btn-glass:hover,
.card-photo--banner .btn-glass:focus-visible{
    background-color: var(--sp-glass-button-bg-light);
}

/* Les albums d'un évènement, sur l'écran de modification : une ligne par album, le nom en
   graisse de titre, la journée en méta, un filet entre les lignes. */
.album-summary-row{
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--sp-space-3);
    padding: var(--sp-space-2) 0;
}

.album-summary-row + .album-summary-row{
    border-top: 1px solid var(--sp-color-border-on-white);
}

.album-summary-name{
    display: inline-flex;
    align-items: center;
    gap: var(--sp-space-1);
    min-width: 0;
    font-weight: var(--sp-font-weight-title);
}

.album-summary-meta{
    flex-shrink: 0;
    font-size: var(--sp-font-size-meta);
    color: var(--sp-color-text-meta);
}

/* --- Paramètres du compte (retour client, septembre 2026) --------------------------------- */

/* Sur la carte couchée : le sous-titre en 15 medium (retour client), les liens à 20px. */
.card-photo--banner .card-photo-meta{
    font-size: var(--sp-font-size-body);
    font-weight: var(--sp-font-weight-body);
}

.card-photo-links{
    gap: var(--sp-space-3);
}

/* Le logo Instagram est blanc comme le reste de la carte : un lien y garde la couleur du texte. */
.card-photo-link,
.card-photo-link:hover{
    color: var(--sp-color-text-inverse);
}

/* Le point entre Instagram et les sports : 4px de chaque côté, moins que le point médian d'une
   méta — ici il sépare deux glyphes, pas deux mots (retour client). */
.card-photo-links-sep{
    margin: 0 calc(var(--sp-space-1) - var(--sp-space-3));
    color: var(--sp-color-text-inverse);
}

/* La banque des textures de couverture : des tuiles d'image en grille, cinq par rangée sur
   desktop, trois sur mobile ; la tuile choisie porte une coche orange au coin et un liseré. */
.cover-grid{
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--sp-space-3);
}

@media (min-width: 992px){
    .cover-grid{
        grid-template-columns: repeat(5, minmax(0, 1fr));
    }
}

.cover-tile{
    position: relative;
    aspect-ratio: 1;
    margin: 0;
    border-radius: var(--sp-radius-md);
    background-color: var(--sp-color-bg-sunken);
    background-position: center;
    background-size: cover;
    cursor: pointer;
    box-shadow: var(--sp-shadow-sm);
    transition: box-shadow .15s ease;
}

.cover-tile:hover{
    box-shadow: var(--sp-shadow-md);
}

/* Choisie : un filet GREY_DARK de 4px, la coche orange en coin (maquette). */
.cover-tile:has(input:checked){
    box-shadow: inset 0 0 0 4px #464646, var(--sp-shadow-sm);
}

.cover-tile:has(input:focus-visible){
    box-shadow: var(--sp-shadow-ring);
}

.cover-tile-check{
    position: absolute;
    top: -6px;
    right: -6px;
    display: none;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    border-radius: var(--sp-radius-full);
    background-color: var(--sp-color-accent-selected);
    color: var(--sp-color-text-inverse);
    box-shadow: 0 0 0 2px var(--sp-color-bg-surface);
}

.cover-tile:has(input:checked) .cover-tile-check{
    display: inline-flex;
}

/* --- Mes photos : la page d'un évènement et ses dépôts (retour client, septembre 2026) ------ */

/* Le retour, en lien de flux avec son chevron : ink, 14 medium, sans soulignement. */
.back-link{
    display: inline-flex;
    align-items: center;
    gap: var(--sp-space-1);
    font-size: var(--sp-font-size-label);
    font-weight: var(--sp-font-weight-body);
    color: var(--sp-color-text-default);
    text-decoration: none;
}

.back-link:hover{
    color: var(--sp-color-text-default);
    text-decoration: underline;
}

/* En tête : le titre à gauche, le compte total et le CTA à droite. */
.deposit-page-head{
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-space-4);
    flex-wrap: wrap;
}

.deposit-total{
    font-size: var(--sp-font-size-label);
    padding: var(--sp-space-2) var(--sp-space-3);
}

/* À la hauteur du bouton de dépôt voisin, 36px (retour client) */
.deposit-page-head .deposit-total{
    display: inline-flex;
    align-items: center;
    /* Le flex mange l'espace entre le nombre et « photos déposées » (retour client) */
    gap: 4px;
    height: 36px;
    padding-top: 0;
    padding-bottom: 0;
    /* Maquette (« 1,267 photos déposées ») : 15px, GREY_DARK. */
    font-size: 15px;
    color: #464646;
}

/* Le chevron entre la journée et l'album d'un résumé de dépôt : celui du jeu d'icônes, à 6px
   de part et d'autre (retour client : « le bon chevron », « plus d'espace »). */
.summary-chevron{
    display: inline-flex;
    align-items: center;
    margin: 0 6px;
    vertical-align: -1px;
}

/* Les dépôts en onglets : rang en semibold, date en méta dessous ; le courant sur le creux
   crème (maquette). La rangée défile si elle déborde. */
.deposit-tabs{
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--sp-space-4);
}

.deposit-tabs-nav{
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-space-2);
    min-width: 0;
}

.deposit-tab{
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: var(--sp-space-2) var(--sp-space-3);
    border-radius: var(--sp-radius-md);
    color: var(--sp-color-text-default);
    text-decoration: none;
}

.deposit-tab:hover{
    background-color: var(--sp-color-bg-cream);
}

.deposit-tab.is-current{
    background-color: var(--sp-color-bg-sunken);
}

.deposit-tab-title{
    font-size: var(--sp-font-size-label);
    font-weight: var(--sp-font-weight-title);
    line-height: 18px;
}

.deposit-tab-meta{
    font-size: var(--sp-font-size-12);
    color: var(--sp-color-text-muted);
    line-height: 15px;
}

/* Les trois cartes de décision : album, monétisation, dossard. */
.deposit-info-grid{
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: var(--sp-space-3);
}

.deposit-info-head{
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-space-2);
    margin-bottom: var(--sp-space-2);
}

.deposit-info-title{
    font-size: var(--sp-font-size-label);
    font-weight: var(--sp-font-weight-title);
}

.deposit-info-text{
    font-size: var(--sp-font-size-meta);
    color: var(--sp-color-text-meta);
}

/* La barre de sélection : un bandeau gris, le décompte à gauche avec sa croix, les deux gestes
   à droite. Collée sous la barre haute quand la grille défile. */
.selection-bar{
    position: sticky;
    top: var(--sp-space-2);
    z-index: 3;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-space-3);
    flex-wrap: wrap;
    padding: var(--sp-space-2) var(--sp-space-3);
    border-radius: var(--sp-radius-md);
    background-color: var(--sp-color-bg-grey);
}

.selection-bar-clear{
    display: inline-flex;
    align-items: center;
    gap: var(--sp-space-2);
    padding: var(--sp-space-1) 0;
    border: 0;
    background: none;
    font-size: var(--sp-font-size-label);
    font-weight: var(--sp-font-weight-title);
    color: var(--sp-color-text-default);
}

.selection-bar-actions{
    display: flex;
    align-items: center;
    gap: var(--sp-space-2);
    flex-wrap: wrap;
}

/* La grille des photos : des tuiles carrées, une coche ronde au coin — blanche à filet quand la
   tuile est libre, orange quand elle est prise. */
.photo-manage-grid{
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
    gap: var(--sp-space-3);
}

.photo-manage-tile{
    position: relative;
    display: block;
    margin: 0;
    cursor: pointer;
}

.photo-manage-tile .ratio{
    display: block;
    border-radius: var(--sp-radius-md);
    overflow: hidden;
}

.photo-manage-check{
    position: absolute;
    top: var(--sp-space-2);
    left: var(--sp-space-2);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    border-radius: var(--sp-radius-full);
    border: 2px solid var(--sp-color-bg-surface);
    background-color: rgba(255, 255, 255, .55);
    color: transparent;
    box-shadow: var(--sp-shadow-sm);
}

.photo-manage-tile:has(.photo-pick-input:checked) .photo-manage-check{
    background-color: var(--sp-color-accent-selected);
    border-color: var(--sp-color-accent-selected);
    color: var(--sp-color-text-inverse);
}

.photo-manage-tile:has(.photo-pick-input:focus-visible) .ratio{
    box-shadow: var(--sp-shadow-ring);
}

/* L'avertissement dans la Dialog de déplacement : l'encart d'avis sur le creux crème, son
   glyphe en ambre — la couleur de l'avertissement, jamais en aplat (DESIGN, « Feedback »). */
.notice--warning{
    background-color: var(--sp-color-bg-sunken);
}

.notice--warning .notice-glyph{
    color: var(--sp-color-feedback-warning);
}

/* --- Le parcours de dépôt (retour client, septembre 2026) --------------------------------- */

/* Étiquette FILAIRE : un contour gris, pas d'aplat — « Par défaut » sur un album, « Étape 1 sur
   5 » sur la frise (retour client). 20px de haut, 12 medium, coin 4. */
.badge-outline{
    display: inline-flex;
    align-items: center;
    height: 20px;
    padding: 0 var(--sp-space-2);
    border: 1px solid var(--sp-color-text-muted);
    border-radius: 4px;
    background: transparent;
    color: var(--sp-color-text-muted);
    font-size: var(--sp-font-size-12);
    font-weight: var(--sp-font-weight-body);
    line-height: 1;
}

/* Un bouton de 45px : celui qui dépose, celui qui crée l'album, celui qui termine (retour client). */
.btn-tall{
    min-height: 45px;
    font-weight: var(--sp-font-weight-title);
}

/* Le choix de l'évènement : titre 20 semibold, sous-titre 15 medium, champ de 50px (retour client). */
.deposit-search .deposit-search-title{
    font-size: var(--sp-font-size-h3);
    font-weight: var(--sp-font-weight-title);
    line-height: 24px;
}

.deposit-search-sub{
    font-size: var(--sp-font-size-body);
    font-weight: var(--sp-font-weight-body);
    color: var(--sp-color-text-muted);
}

.deposit-search .input-search .form-control{
    height: 50px;
    min-height: 50px;
}

/* « Je ne le trouve pas, je le crée » : 40px (retour client). Le glyphe en ligne décalait la
   hauteur d'une fraction de pixel ; centré en flex, il ne pèse plus. */
.deposit-search .sec-header .btn{
    display: inline-flex;
    align-items: center;
    min-height: 40px;
    padding-top: 0;
    padding-bottom: 0;
}

/* La carte de l'évènement dans la colonne gauche : coin de 24, « Retour » en 15 semibold, et le
   verre du disque au repos comme au survol (retour client). */
.tunnel-grid .event-highlighted-header--labelled{
    border-radius: var(--sp-radius-2xl);
}

.tunnel-grid .event-back-label{
    font-size: var(--sp-font-size-body);
    font-weight: var(--sp-font-weight-title);
}

.tunnel-grid .event-back .btn-glass{
    background-color: transparent;
}

.tunnel-grid .event-back .btn-glass:hover,
.tunnel-grid .event-back .btn-glass:focus-visible{
    background-color: var(--sp-glass-button-bg-light);
}

/* La carte de transfert (retour client) : fond blanc, 128px environ, « Dépôt X » en 15 semibold
   suivi de la cible en 15 medium gris sombre ; pourcentage et état en medium ; moins d'air
   sous la barre et sous le filet ; la méta en gris texte, point médian à 8px. */
.upload-item{
    min-height: 128px;
    background-color: var(--sp-color-bg-surface);
    border: 1px solid var(--sp-color-border-on-white);
    padding: var(--sp-space-4) var(--sp-space-5) var(--sp-space-3);
}

.upload-item-title{
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: var(--sp-space-2);
}

.upload-item-rank{
    font-weight: var(--sp-font-weight-title);
}

.upload-item-target{
    font-weight: var(--sp-font-weight-body);
    color: var(--sp-color-text-meta);
}

.upload-item-head{
    margin-bottom: var(--sp-space-2);
}

.upload-item-state{
    margin-top: var(--sp-space-1);
}

.upload-item-pct,
.upload-item-status{
    font-weight: var(--sp-font-weight-body);
    color: var(--sp-color-text-muted);
}

.upload-item .card-rule{
    margin: var(--sp-space-2) 0;
}

.upload-item-meta{
    color: var(--sp-color-text-muted);
}

/* Un dépôt fini : « Terminé » en haut à droite, la méta et « Voir » sous le filet. */
.upload-item--done{
    min-height: 0;
}

.upload-item-status--done{
    flex-shrink: 0;
    font-size: var(--sp-font-size-meta);
    color: var(--sp-color-text-muted);
}

.upload-item-foot{
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-space-3);
}

/* La carte du parcours : l'évènement en 15 semibold et le rang en 15 medium gris sombre dans
   l'en-tête ; « Annuler le dépôt » en 15 medium ; « Suivant » à 40px, « Déposer » à 45 (retour client). */
.sec-header--flow .sec-header-context{
    font-size: var(--sp-font-size-body);
    color: var(--sp-color-text-meta);
}

.sec-header--flow .sec-header-context strong{
    font-weight: var(--sp-font-weight-title);
    color: var(--sp-color-text-default);
}

.upload-flow .flow-link{
    font-size: var(--sp-font-size-body);
    font-weight: var(--sp-font-weight-body);
}

.upload-flow .btn-primary:not(.btn-sm):not(.btn-xs):not(.btn-tall){
    min-height: 40px;
    font-weight: var(--sp-font-weight-title);
}

.upload-flow .btn-marketing:not(.btn-sm):not(.btn-xs){
    min-height: 45px;
    font-weight: var(--sp-font-weight-title);
}

/* Les sous-titres de section du parcours en 14 medium ; celui de l'album en 15 (retour client). */
.upload-flow .sec-note{
    font-size: var(--sp-font-size-label);
    font-weight: var(--sp-font-weight-body);
}

.album-step .card-nested > .sec-note{
    font-size: var(--sp-font-size-body);
}

/* La section Album perd sa bordure (retour client) : ce sont ses journées qui sont des cartes. */
.album-step > form > .card-nested{
    padding: 0;
    border: 0;
}

/* Une journée : nom en 16 semibold, fond crème clair ; allumée, un filet brun ; éteinte, pas de
   filet mais une ombre courte (retour client). Son sous-titre en 14 medium. */
.album-day{
    border-color: transparent;
    background-color: var(--sp-color-bg-default);
    box-shadow: 0 1px 1px rgba(0, 0, 0, .05);
}

.album-day.is-open{
    border-color: var(--sp-color-border-brown);
    box-shadow: none;
}

.album-day-name{
    font-size: var(--sp-font-size-h4);
    font-weight: var(--sp-font-weight-title);
}

.album-day-meta,
.album-day-hint{
    font-weight: var(--sp-font-weight-body);
}

/* Une ligne d'album : nom en 15 semibold, sous-titre en 14 medium, ses actions soulignées en ink. */
.album-row .option-row-name{
    font-weight: var(--sp-font-weight-title);
}

.album-row .option-row-help{
    font-weight: var(--sp-font-weight-body);
}

.album-row-actions{
    display: flex;
    gap: var(--sp-space-3);
    margin-top: 2px;
}

.album-row-action{
    padding: 0;
    border: 0;
    background: none;
    font-size: var(--sp-font-size-label);
    font-weight: var(--sp-font-weight-body);
    color: var(--sp-color-text-default);
    text-decoration: underline;
    text-underline-offset: 2px;
}

.album-rule{
    margin: var(--sp-space-3) 0 0;
    border: 0;
    border-top: 1px solid var(--sp-color-border-on-white);
    opacity: 1;
}

.album-create:hover,
.album-create:focus-visible{
    background-color: var(--sp-color-accent-tint);
}

/* La modale « Nouvel album » : le sous-titre sous le titre, les deux participants de part et
   d'autre d'un « VS », l'œil du mot de passe. */
.dialog-subtitle{
    display: flex;
    align-items: center;
    gap: var(--sp-space-2);
    margin-top: var(--sp-space-1);
    font-size: var(--sp-font-size-body);
    font-weight: var(--sp-font-weight-body);
    color: var(--sp-color-text-muted);
}

.dialog-subtitle-sep{
    display: inline-flex;
}

.match-fields{
    display: flex;
    align-items: center;
    gap: var(--sp-space-3);
}

.match-fields .form-floating{
    flex: 1 1 0;
    min-width: 0;
}

.match-vs{
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    border-radius: var(--sp-radius-sm);
    background-color: var(--sp-color-bg-sunken);
    font-size: var(--sp-font-size-12);
    font-weight: var(--sp-font-weight-bold);
    color: var(--sp-color-text-default);
}

.album-eye-hide{ display: none; }
.is-shown .album-eye-show{ display: none; }
.is-shown .album-eye-hide{ display: inline; }

/* IBAN masqué des paramètres de paiement : l'œil se pose dans le champ, à droite. */
.iban-field > .form-control{ padding-right: 52px; }
.iban-field > .iban-reveal{
    position: absolute;
    top: 27px;
    right: 12px;
    z-index: 3;
    transform: translateY(-50%);
}

/* Monétisation (retour client) : le montant d'une option en 16 bold ; les pastilles de prix en
   15 semibold, filaires au repos ; le gain en bold ; le prix acheteur en 14. */
.upload-flow .option-row-value{
    font-size: var(--sp-font-size-16);
    font-weight: var(--sp-font-weight-bold);
}

.upload-flow .btn-toggle{
    font-size: var(--sp-font-size-body);
    font-weight: var(--sp-font-weight-title);
    --bs-btn-bg: transparent;
    --bs-btn-border-color: var(--sp-color-border-cream);
}

.upload-flow .earnings-figure{
    font-weight: var(--sp-font-weight-bold);
}

.upload-flow small{
    font-size: var(--sp-font-size-label);
}

/* Le barème : paliers en 14, pilule de remise en 13 au coin de 8, « Personnaliser » en 14 semibold. */
.upload-flow .tier-row-threshold,
.upload-flow .tier-row-range{
    font-size: var(--sp-font-size-label);
}

.upload-flow .deal-pill{
    border-radius: var(--sp-radius-sm);
    font-size: var(--sp-font-size-meta);
}

.upload-flow .tier-rows + p .flow-link{
    font-size: var(--sp-font-size-label);
    font-weight: var(--sp-font-weight-title);
}

/* Dossard : le supplément en 20 bold. */
.upload-flow .bib-fee strong{
    font-size: var(--sp-font-size-h3);
}

/* L'étape repliée : « Modifier » au filet gris clair, blanc dessous (retour client). */
.step-recap .btn-neutral{
    --bs-btn-border-color: var(--sp-color-border-on-white);
    --bs-btn-hover-border-color: var(--sp-color-border-on-white);
}

/* La frise : pleine largeur, ses étapes à venir en brun plutôt qu'en gris (contraste), la
   pastille d'étape filaire (retour client). */
.stepper{
    width: 100%;
}

.stepper-step--upcoming{
    color: var(--sp-color-text-brown);
}

/* Le badge « Plus à venir » de l'aperçu prend une ombre portée (retour client). */
.dialog-preview .badge-live{
    box-shadow: var(--sp-shadow-cta);
}

/* --- Création d'évènement et création de profil (retour client, septembre 2026) ---------- */

/* La pastille « VS » d'un match, entre les deux équipes : un carré à coins de 8, ink sur les
   surfaces claires, blanc sur une photographie. Les deux couleurs sont ÉCRITES : une première
   version posait `background: currentColor` sur un texte rendu transparent — currentColor
   devenait transparent avec lui, et la pastille disparaissait des cartes (revue, sept. 2026). */
.vs-badge{
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 1.6em;
    height: 1.35em;
    padding: 0 .35em;
    border-radius: .35em;
    background-color: var(--sp-color-action-primary);
    color: var(--sp-color-text-inverse);
    font-size: .6em;
    font-weight: var(--sp-font-weight-bold);
    line-height: 1;
    letter-spacing: .04em;
    vertical-align: .15em;
}

.event-highlighted-title .vs-badge,
.card-photo .vs-badge{
    background-color: var(--sp-color-bg-surface);
    color: var(--sp-color-text-default);
}

/* L'éditeur de description : la barre réduite à quatre gestes, le compte en pied. */
.description-editor trix-toolbar .trix-button-group:not(.trix-button-group--text-tools):not(.trix-button-group--block-tools){
    display: none;
}

/* La barre de la description se fond dans la carte (retour client : « retirer la bordure autour
   des contrôles, notamment celle en dessous ») : plus de cadre ni de séparateurs entre les
   boutons, seulement leurs pastilles au survol et à l'état actif. */
.description-editor trix-toolbar{
    margin-bottom: var(--sp-space-2);
    padding: 0;
    border: 0;
    background: none;
}

/* Un cran de plus que `trix-toolbar .trix-button:not(:first-child)` de Trix, chargé après nous :
   sans lui, les séparateurs restaient au #CCC d'usine. */
.description-editor trix-toolbar .trix-button-row .trix-button{
    border: 0;
}

.description-editor trix-toolbar .trix-button-row .trix-button-group + .trix-button-group{
    margin-left: var(--sp-space-2);
}

.description-editor trix-toolbar .trix-button--icon-underline{
    text-decoration: underline;
    font-weight: var(--sp-font-weight-bold);
    width: 2.5em;
    /* Trix cache le texte des boutons « icône » (text-indent) : celui-ci n'a que sa lettre, le
       « S » restait invisible — un bouton vide dans la barre. */
    text-indent: 0;
    color: var(--sp-color-text-default);
}

/* Deux fois plus haute (retour client) : le champ, qui porte aussi `.form-control`, prenait les
   54px fixes des champs du formulaire — une ligne à peine. Il grandit ensuite avec le texte. */
.description-editor trix-editor.form-control{
    height: auto;
    min-height: 120px;
}

/* Le cadrage vertical de la couverture : un curseur orange sur piste pêche. */
.cover-focus-range{
    accent-color: var(--sp-color-accent-selected);
}

/* L'espace d'inscription : le fond de page couvre toute la hauteur, quelle que soit celle de la
   carte (retour client — « beaucoup d'espace vide blanc en bas de la page sur desktop »). */
main.bg-wallpaper{
    min-height: 100vh;
    background-size: cover;
    background-position: center;
    background-attachment: fixed;
}

main.bg-wallpaper > .container-fluid{
    min-height: 100vh;
}

/* ============================================================================
   Spicto Pro — la page de l'offre (DESIGNAPP, « Spicto Pro : l'offre est une page » ; maquette
   Figma, retour client, septembre 2026). Deux colonnes : l'argumentaire à gauche, ce qu'on
   décide à droite.
   ============================================================================ */

/* Le héros : verrou, promesse et sous-titre centrés, puis les avantages dans un cadre crème. */
.pro-hero{
    text-align: center;
    padding: var(--sp-space-8) var(--sp-space-6) var(--sp-space-6);
}

/* Le verrou en grand : la seule fois où le logotype dépasse ses 15px d'en-tête — c'est le nom
   du produit qu'on vend, pas un chrome (BRAND, « Verrou »). Les trois pièces grandissent
   ensemble, leurs proportions ne changent pas. */
.pro-hero-lockup{
    display: flex;
    justify-content: center;
    margin-bottom: var(--sp-space-4);
}

.pro-hero-lockup .pro-lockup{
    gap: var(--sp-space-2);
}

.pro-hero-lockup .pro-lockup-logotype{
    height: 28px;
}

.pro-hero-lockup .pro-lockup-seal svg{
    width: 28px;
    height: 28px;
}

.pro-hero-lockup .pro-lockup-tier{
    padding: 2px var(--sp-space-2);
    border-width: var(--sp-border-width-strong);
    border-radius: var(--sp-radius-sm);
    font-size: var(--sp-font-size-16);
    font-weight: var(--sp-font-weight-title);
}

/* Le titre de l'offre est une PROMESSE, pas le titre de l'écran : h3 (20px), centré, sur une
   ligne. L'identifiant est là pour passer devant `.photographer-layout h1:not(.page-title)`
   (0,2,1), qui donne 28px à tout h1 de l'espace — même mécanique que le tableau de bord. */
#pro-offer .pro-hero-title{
    font-size: var(--sp-font-size-h3);
    font-weight: var(--sp-font-weight-title);
    line-height: 26px;
    letter-spacing: var(--sp-font-tracking-tight);
    margin: 0 auto var(--sp-space-2);
    max-width: 40ch;
}

.pro-hero-text{
    font-size: var(--sp-font-size-15);
    color: var(--sp-color-text-default);
    margin: 0 auto var(--sp-space-6);
    max-width: 52ch;
}

/* Le cadre crème des avantages, deux colonnes, un glyphe `accent.seal` devant chaque. */
.pro-benefits{
    text-align: left;
    --bs-card-spacer-x: var(--sp-space-5);
    --bs-card-spacer-y: var(--sp-space-5);
}

.pro-benefits-title{
    font-size: var(--sp-font-size-h4);
    font-weight: var(--sp-font-weight-title);
    line-height: 20px;
    margin-bottom: var(--sp-space-4);
}

.pro-benefits-list{
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--sp-space-3) var(--sp-space-4);
    list-style: none;
    padding: 0;
    margin: 0;
}

.pro-benefits-list li{
    display: flex;
    align-items: center;
    gap: var(--sp-space-2);
    font-size: var(--sp-font-size-15);
    font-weight: var(--sp-font-weight-500);
    line-height: 20px;
    color: var(--sp-color-text-default);
}

.pro-benefits-list svg{
    flex-shrink: 0;
    color: var(--sp-color-accent-seal);
}

@media (max-width: 575.98px) {
    .pro-benefits-list{
        grid-template-columns: minmax(0, 1fr);
    }
}

/* Les cartes illustrées : la photo d'un côté, fondue vers le blanc du texte. Coin `lg`, celui
   des cartes de l'espace connecté (fiche card : un même niveau de surface, un même rayon) — la
   maquette les dessinait à 24, mais seul le héros, qui héberge une carte imbriquée, ouvre plus. */
.pro-feature{
    position: relative;
    display: grid;
    grid-template-columns: 40% minmax(0, 1fr);
    min-height: 150px;
    margin-top: var(--sp-space-4);
    border-radius: var(--sp-radius-lg);
    background-color: var(--sp-color-bg-surface);
    overflow: hidden;
}

.pro-feature--right{
    grid-template-columns: minmax(0, 1fr) 40%;
}

.pro-feature--right .pro-feature-visual{
    order: 2;
}

.pro-feature-visual{
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    background-size: cover;
    background-position: center;
}

/* Le fondu vers le blanc de la carte, du côté du texte : la photo n'a pas de bord. */
.pro-feature-visual::after{
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(to right, transparent 45%, var(--sp-color-bg-surface) 100%);
}

.pro-feature--right .pro-feature-visual::after{
    background: linear-gradient(to left, transparent 45%, var(--sp-color-bg-surface) 100%);
}

.pro-feature-body{
    display: flex;
    flex-direction: column;
    justify-content: center;
    padding: var(--sp-space-6);
}

.pro-feature-title{
    font-size: var(--sp-font-size-h4);
    font-weight: var(--sp-font-weight-title);
    line-height: 22px;
    margin-bottom: var(--sp-space-2);
}

.pro-feature-text{
    font-size: var(--sp-font-size-body);
    line-height: 20px;
    color: var(--sp-color-text-default);
}

/* Ce que l'avantage produit à l'écran, posé sur la photo : le badge glass d'une galerie privée,
   le prix d'une photo. Verre sombre comme tout badge sur photo (fiche badge, ton glass). */
.pro-feature-tag{
    position: relative;
    z-index: 1;
    display: inline-flex;
    align-items: center;
    gap: var(--sp-space-2);
    padding: var(--sp-space-2) var(--sp-space-4);
    border-radius: var(--sp-radius-lg);
    background-color: var(--sp-glass-overlay-bg);
    backdrop-filter: blur(var(--sp-glass-overlay-blur));
    -webkit-backdrop-filter: blur(var(--sp-glass-overlay-blur));
    box-shadow: var(--sp-glass-overlay-shadow);
    color: var(--sp-color-text-inverse);
    font-size: var(--sp-font-size-16);
    font-weight: var(--sp-font-weight-title);
    white-space: nowrap;
}

.pro-feature-tag strong{
    font-weight: 600;
}

.pro-feature-tag .pro-feature-tag-unit{
    margin-left: -6px;
    font-size: 13px;
    font-weight: 500;
    letter-spacing: -0.01em;
}

/* Cotes de la maquette (Spicto Pro, 3138:12769), sans arbitrage DS : promesse 20/24 sur une
   ligne, sous-titre 15/18, avantages en #333333, cartes au coin de 24, 160px, marges 24/32,
   titres 20 semibold, pastille de verre 50px au coin de 16. */
#pro-offer .pro-hero-title{
    line-height: 24px;
    letter-spacing: -0.03em;
    max-width: none;
}

.pro-hero-text{
    line-height: 18px;
    letter-spacing: -0.02em;
}

.pro-benefits-title{
    color: #000000;
    line-height: 19px;
    letter-spacing: -0.02em;
}

.pro-benefits-list li{
    color: #333333;
    line-height: 18px;
    letter-spacing: -0.02em;
}

.pro-feature{
    min-height: 160px;
    border-radius: 24px;
}

.pro-feature-body{
    padding: 24px 32px;
}

.pro-feature-title{
    font-size: 20px;
    line-height: 24px;
    letter-spacing: -0.03em;
}

.pro-feature-text{
    font-weight: 500;
    letter-spacing: -0.02em;
}

.pro-feature-tag{
    height: 50px;
    padding: 0 16px;
    border-radius: 16px;
    box-shadow: 0 8px 40px rgba(0, 0, 0, .2);
    font-size: 20px;
    line-height: 24px;
    letter-spacing: -0.03em;
}

/* La jauge d'un quota sans plafond : la carte « Photos payantes » du dépôt, en verre, à
   l'échelle d'une vignette. */
.pro-feature-quota{
    position: relative;
    z-index: 1;
    width: 190px;
    padding: var(--sp-space-3) var(--sp-space-4);
    border-radius: var(--sp-radius-xl);
    background-color: var(--sp-glass-overlay-bg);
    backdrop-filter: blur(var(--sp-glass-overlay-blur));
    -webkit-backdrop-filter: blur(var(--sp-glass-overlay-blur));
    box-shadow: var(--sp-glass-overlay-shadow);
    color: var(--sp-color-text-inverse);
}

.pro-feature-quota-title{
    display: flex;
    align-items: center;
    gap: 2px;
    font-size: var(--sp-font-size-body);
    font-weight: var(--sp-font-weight-title);
    margin-bottom: var(--sp-space-2);
}

.pro-feature-quota-dot{
    width: 8px;
    height: 8px;
    border-radius: var(--sp-radius-full);
    background-color: var(--sp-color-accent-seal);
}

.pro-feature-quota-bar{
    position: relative;
    height: 6px;
    border-radius: var(--sp-radius-full);
    background-color: rgba(255, 255, 255, .35);
    overflow: hidden;
}

.pro-feature-quota-bar::before{
    content: '';
    position: absolute;
    inset: 0 40% 0 0;
    border-radius: inherit;
    background-color: var(--sp-color-text-inverse);
}

.pro-feature-quota-count{
    font-size: var(--sp-font-size-13);
    margin: var(--sp-space-2) 0 0;
}

.pro-feature-quota-count strong{
    font-weight: var(--sp-font-weight-bold);
}

/* Le sceau, seul : orange `accent.seal`, sans le logotype — ici il illustre le badge que
   l'abonné porte, il ne nomme pas l'offre (le verrou est en tête de page). */
.pro-feature-seal{
    position: relative;
    z-index: 1;
    display: inline-flex;
    color: var(--sp-color-accent-seal);
    filter: drop-shadow(0 4px 12px rgba(0, 0, 0, .25));
}

@media (max-width: 767.98px) {
    .pro-feature,
    .pro-feature--right{
        grid-template-columns: minmax(0, 1fr);
    }

    .pro-feature--right .pro-feature-visual{
        order: 0;
    }

    .pro-feature-visual{
        min-height: 140px;
    }

    .pro-feature-visual::after,
    .pro-feature--right .pro-feature-visual::after{
        background: linear-gradient(to bottom, transparent 55%, var(--sp-color-bg-surface) 100%);
    }

    .pro-feature-body{
        padding: var(--sp-space-2) var(--sp-space-4) var(--sp-space-5);
    }
}

/* La colonne de droite : ce qu'on décide. Ses titres sont hors des cartes, en h3. */
.pro-aside-title{
    font-size: var(--sp-font-size-h3);
    font-weight: var(--sp-font-weight-title);
    line-height: 24px;
    margin: 0 0 var(--sp-space-3);
}

.pro-aside-title + .pro-aside-title,
.pro-cycle + .pro-aside-title,
.pro-payment-note + .pro-aside-title{
    margin-top: var(--sp-space-6);
}

/* Le cycle : deux radios en ligne, un filet, le prix en 24 bold suivi de son unité. */
.pro-cycle-choice{
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-space-3) var(--sp-space-6);
    border: 0;
    padding: 0 0 var(--sp-space-4);
    margin: 0 0 var(--sp-space-4);
    border-bottom: 1px solid var(--sp-color-border-default);
    min-width: 0;
}

.pro-cycle-option{
    display: inline-flex;
    align-items: center;
    gap: var(--sp-space-2);
    margin: 0;
    font-size: var(--sp-font-size-16);
    font-weight: var(--sp-font-weight-500);
    color: var(--sp-color-text-default);
    cursor: pointer;
}

.pro-cycle-option .form-check-input{
    width: 20px;
    height: 20px;
    margin: 0;
    flex-shrink: 0;
}

.pro-cycle-price{
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0 var(--sp-space-3);
}

.pro-cycle-price strong{
    font-size: var(--sp-font-size-24);
    font-weight: var(--sp-font-weight-bold);
    line-height: 29px;
    letter-spacing: var(--sp-font-tracking-tighter);
}

.pro-cycle-unit{
    font-size: var(--sp-font-size-16);
    color: var(--sp-color-text-default);
    margin-left: -8px; /* colle l'unité au montant : « 99,00 €/an » se lit d'un bloc */
}

.pro-cycle-savings{
    margin-left: var(--sp-space-1);
}

/* Cotes de la maquette (Spicto Pro, 3138:12769) : prix 24 semibold noir, unité 12 medium, badge
   d'économie ORANGE_EVENT sur ORANGE_LIGHT, 13 semibold, 24px de haut. */
.pro-cycle-price strong{
    font-weight: 600;
    color: #000000;
}

.pro-cycle-unit{
    font-size: 12px;
    font-weight: 500;
    color: #000000;
}

.deal-pill.pro-cycle-savings{
    display: inline-flex;
    align-items: center;
    height: 24px;
    padding: 4px 6px;
    border-radius: 65px;
    background-color: #FFD3B8;
    color: #FF6204;
    font-size: 13px;
    font-weight: 600;
    line-height: 16px;
    letter-spacing: -0.01em;
}

/* Le paiement : un cadre, pas un choix — la carte que Stancer encaisse. */
.pro-payment{
    display: flex;
    align-items: center;
    gap: var(--sp-space-3);
    min-height: 52px;
    padding: var(--sp-space-2) var(--sp-space-4);
    border: var(--sp-border-width-default) solid var(--sp-color-border-strong);
    border-radius: var(--sp-radius-lg);
    background-color: var(--sp-color-bg-surface);
}

.pro-payment-glyph{
    flex-shrink: 0;
}

.pro-payment-label{
    flex: 1 1 auto;
    min-width: 0;
    font-size: var(--sp-font-size-16);
    font-weight: var(--sp-font-weight-500);
}

.pro-payment-brands{
    display: inline-flex;
    gap: var(--sp-space-1);
}

.pro-payment-brands .badge-light{
    border-radius: var(--sp-radius-sm);
}

.pro-payment-note{
    font-size: var(--sp-font-size-meta);
    color: var(--sp-color-text-muted);
    margin: var(--sp-space-2) 0 0;
}

/* Les conditions : le seul bloc de la page qui vouvoie — du juridique, en 13/19 muted. */
.pro-terms{
    margin-top: var(--sp-space-6);
}

.pro-terms-title{
    font-size: var(--sp-font-size-h4);
    font-weight: var(--sp-font-weight-title);
    line-height: 20px;
    margin-bottom: var(--sp-space-3);
}

.pro-terms p{
    font-size: var(--sp-font-size-13);
    line-height: 19px;
    color: var(--sp-color-text-muted);
    margin-bottom: var(--sp-space-2);
}

.pro-terms a{
    color: var(--sp-color-text-link);
    text-decoration: underline;
}

/* Le seul orange de la page, pleine largeur, 50px : souscrire est un achat. */
.pro-cta{
    min-height: 50px;
    margin-top: var(--sp-space-4);
}

/* ============================================================================
   Les modales de partage et la bulle de message suivent la maquette V2 (retour client,
   septembre 2026 ; fiches dialog et message).
   ============================================================================ */

/* La Dialog `done` (maquette TIPS) : la seule qui ne porte AUCUN champ — donc la seule qui
   n'a pas besoin du crème pour qu'un champ s'y détache. Elle prend le blanc de toute surface
   flottante, cerné d'un filet `border.on-white`, ouvre son coin à 2xl, et serre ses blocs de
   space.3 : ce qu'elle montre est un objet et son lien, pas un formulaire à remplir. */
.modal.dialog--done{
    --bs-modal-bg: var(--sp-color-bg-surface);
    --bs-modal-header-bg: var(--sp-color-bg-surface);
    --bs-modal-border-radius: var(--sp-radius-2xl);
    --bs-modal-inner-border-radius: var(--sp-radius-2xl);
}

.dialog--done .modal-content{
    border: var(--sp-border-width-default) solid var(--sp-color-border-on-white);
}

.dialog--done .dialog-body{
    gap: var(--sp-space-3);
}

/* La tuile garde sa propre hauteur : son `height: 100%` (fait pour remplir une cellule de grille)
   prenait toute la modale plein écran du mobile, et la barre « Voir l'évènement », ancrée au pied
   de la tuile, tombait 300px sous la photo — bouton de verre blanc sur le blanc, illisible. */
.dialog--done .event-highlighted-wrap{
    height: auto;
    flex-shrink: 0;
}

/* « Voir l'évènement » et « Publier mes photos » : exactement la même largeur et la même
   hauteur (retour client), filet simple pour le premier (cf. barre des tuiles de gestion). */
.dialog--done .event-highlighted-action--bar .btn{
    flex: 1 1 0;
    min-height: 30px;
    padding-left: 12px;
    padding-right: 12px;
}

/* Sur le blanc, ce qui tient lieu de champ prend le creux crème : c'est le fond qui le fait
   exister, pas son filet (fiche input). */
.dialog--done .share-link{
    background-color: var(--sp-color-bg-sunken);
    border-color: transparent;
}

@media (min-width: 768px) {
    .modal.dialog--done{
        --bs-modal-width: 509px;
    }
}

/* Le pack visuel : sous le lien, un filet, puis la phrase et le bouton `free` en vis-à-vis.
   Le filet reprend le rythme des blocs, il n'ajoute pas le sien. */
.share-pack-rule{
    margin: 0;
}

.share-pack{
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-space-4);
}

.share-pack-text{
    font-size: var(--sp-font-size-body);
    line-height: 20px;
    color: var(--sp-color-text-default);
}

.share-pack-button{
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    gap: var(--sp-space-2);
    white-space: nowrap;
}

@media (max-width: 575.98px) {
    .share-pack{
        flex-direction: column;
        align-items: stretch;
    }
}

/* La bulle de message aux cotes de la maquette : coin xl (20px), 12px de haut en bas et 24px
   sur les côtés, blocs séparés de space.3. Une bulle est une phrase, pas une carte : elle se
   serre en hauteur et respire sur les côtés. */
.message{
    padding: var(--sp-space-3) var(--sp-space-6);
    border-radius: var(--sp-radius-xl);
    gap: var(--sp-space-3);
}

/* Texte de la bulle (maquette MES PHOTOS) : titre 16 semibold et texte 15 medium en interligne
   100 %, 7px entre eux, le montant en semibold ; croix de 11px centrée sur la ligne du titre. */
.message-title{
    margin: 0 0 7px;
    line-height: 19px;
    letter-spacing: -0.02em;
}

.message-body{
    font-size: 15px;
    font-weight: 500;
    line-height: 18px;
    letter-spacing: -0.02em;
}

.message-body strong{
    font-weight: 600;
}

.message-dismiss{
    margin-top: calc((19px - var(--sp-control-icon-button)) / 2);
}

/* Maquette : la croix (11px) à 24px du bord et 12px du texte. La cible de 44px déborde sur la
   marge des deux côtés plutôt que de repousser le glyphe vers l'intérieur. */
.dashboard-messages .message-dismiss{
    margin-left: calc((11px - var(--sp-control-icon-button)) / 2);
    margin-right: calc((11px - var(--sp-control-icon-button)) / 2);
}

.dashboard-messages .message{
    background: #FFFFFF;
    border: 0;
    box-shadow: 0 1px 1px rgba(0, 0, 0, .1);
}

/* Paramètres › Profil (maquette DASHBOARD 3161:19729) : titre 20 semibold, sous-titre 15 medium
   GREY_DARK à 4px, contenu à 17px, blocs à 25px. */
.settings-block + .settings-block{
    margin-top: 25px;
}

.settings-block-title{
    margin: 0 0 4px;
    font-size: 20px;
    font-weight: 600;
    line-height: 24px;
    letter-spacing: -0.03em;
}

.settings-block-sub{
    margin: 0 0 17px;
    color: #464646;
    font-size: 15px;
    font-weight: 500;
    line-height: 18px;
    letter-spacing: -0.02em;
}

/* Étape Album (maquette DROP 4278:11155) : la journée est une carte crème — fermée, ombre
   0 1 1 à 5 % ; ouverte, filet BROWN_FADE et sa phrase d'aide — et la liste de ses albums une
   boîte à part, filet BROWN_BORDER, 12px dessous. Chevron vers la gauche fermé, vers le bas ouvert. */
.album-day,
.album-day.is-open{
    display: flex;
    flex-direction: column;
    gap: 12px;
    padding: 0;
    border: 0;
    background: none;
    box-shadow: none;
}

.album-day-card{
    padding: 20px 20px 20px 16px;
    border: 1px solid transparent;
    border-radius: 16px;
    background-color: #FAF9F5;
    box-shadow: 0 1px 1px rgba(0, 0, 0, .05);
}

.album-day:not(.is-open) .album-day-card{
    padding: 8px 24px 8px 16px;
}

.album-day:not(.is-open) .album-day-head{
    min-height: 44px;
}

.album-day.is-open .album-day-card{
    border-color: #A29689;
    box-shadow: none;
}

.album-day-card .album-day-hint{
    display: none;
    margin: 8px 0 0;
    color: #757575;
    font-size: 13px;
    font-weight: 500;
    line-height: 16px;
    letter-spacing: -0.01em;
}

.album-day.is-open .album-day-card .album-day-hint{
    display: block;
}

.album-day-panel{
    margin: 0;
    padding: 20px 16px 16px;
    border: 1px solid #D3CDC3;
    border-radius: 16px;
}

/* Journée à venir : ses albums se voient, rien ne s'y sélectionne (retour client). Le texte prend
   le GREY_FADE de la maquette pour un album indisponible. */
.album-day.is-future .album-day-label,
.album-day.is-future .album-day-name,
.album-day.is-future .album-day-meta,
.album-day.is-future .album-day-hint,
.album-day.is-future .album-row .option-row-name,
.album-day.is-future .album-row .option-row-help{
    color: #D1D1D1;
}

.album-day.is-future .form-check-input{
    opacity: .5;
}

.album-day.is-future .album-row-label{
    cursor: default;
}

.album-day .chevron-toggle{
    transform: rotate(180deg);
}

.album-day .chevron-toggle.rotate{
    transform: rotate(-90deg);
}

/* Étape Album, cotes de la maquette : titre 20/600 -3 %, phrase 15/500 -2 %, 26px avant les
   journées ; lignes d'album 15/600 et 13/500, filet à 15px ; radio 15px cerclé #464646. */
.album-step .card-nested > .sec-header{
    margin-bottom: 4px;
}

.album-step .card-nested > .sec-header .sec-header-title{
    font-size: 20px;
    font-weight: 600;
    line-height: 24px;
    letter-spacing: -0.03em;
    color: #000;
}

.album-step .card-nested > .sec-note{
    margin-bottom: 26px !important;
    font-size: 15px;
    font-weight: 500;
    line-height: 18px;
    letter-spacing: -0.02em;
    color: #10110F;
}

.album-days{
    gap: 26px;
}

.album-day-name{
    line-height: 19px;
    letter-spacing: -0.02em;
    color: #1E1C1A;
}

.album-day-meta{
    font-size: 13px;
    font-weight: 500;
    line-height: 16px;
    letter-spacing: -0.01em;
    color: #464646;
}

.album-day-panel .option-row{
    padding: 15px 0;
}

.album-day-panel .option-row:first-of-type{ padding-top: 0; }
.album-day-panel .option-row:last-of-type{ padding-bottom: 0; }

.album-day-panel .option-row + .option-row{
    border-top-color: #EDEAE4;
}

.album-row .option-row-label{
    gap: 2px;
}

.album-row .option-row-name{
    font-size: 15px;
    line-height: 18px;
    letter-spacing: -0.02em;
    color: #1E1C1A;
}

.album-row .option-row-help{
    font-size: 13px;
    font-weight: 500;
    line-height: 16px;
    letter-spacing: -0.01em;
    color: #757575;
}

/* « Créé par @pseudo » : le pseudo en semi-gras, comme dans la maquette. */
.album-row .option-row-help strong{
    font-weight: var(--sp-font-weight-title);
}

.album-row .badge-outline{
    height: 20px;
    padding: 2px 6px 3px 4px;
    border: 1px solid #757575;
    border-radius: 4px;
    font-size: 12px;
    font-weight: 500;
    letter-spacing: -0.02em;
    color: #757575;
}

.upload-flow .option-row .form-check-input[type="radio"]:not([role="switch"]),
.album-day-panel .form-check-input[type="radio"]{
    width: 17px;
    height: 17px;
    margin-top: 1px;
    border: 1px solid #464646;
    background-color: #FFFFFF;
    background-image: none;
}

.upload-flow .option-row .form-check-input[type="radio"]:not([role="switch"]):checked,
.album-day-panel .form-check-input[type="radio"]:checked{
    border-color: #1E1C1A;
    background-color: #FFFFFF;
    background-image: radial-gradient(circle closest-side, #1E1C1A 5.5px, transparent 6px);
}

.album-create{
    height: 40px;
    margin-top: 16px;
    padding: 10px;
    gap: 8px;
    border: 1px dashed #FF6204;
    border-radius: 12px;
    background-color: #FEF0E9;
    color: #FF6204;
    font-size: 13px;
    font-weight: 600;
    line-height: 16px;
    letter-spacing: -0.01em;
}

/* Étape Monétisation, cotes de la maquette (« Modifier les paramètres de monétisation ») :
   cartes à 16/24/18, option 15/500 puis montant 16/700 -4 % et son unité 13/500 #464646,
   notes et aide en 13 ; barème en lignes #F6F6F6 de 44px, remise en pilule #8C78E9. */
.upload-flow .card-nested-fields{
    padding: 16px 24px 18px;
}

.upload-flow .option-row-label{
    gap: 4px;
}

.upload-flow .option-row-name{
    line-height: 18px;
    letter-spacing: -0.02em;
}

.upload-flow .option-row-value{
    font-size: 16px;
    font-weight: 700;
    line-height: 19px;
    letter-spacing: -0.04em;
    color: #1E1C1A;
}

.upload-flow .option-row-unit{
    margin-left: 2px;
    font-size: 13px;
    font-weight: 500;
    letter-spacing: -0.01em;
    color: #464646;
}

.upload-flow .option-row-help{
    font-size: 13px;
    font-weight: 500;
    line-height: 16px;
    letter-spacing: -0.01em;
    color: #757575;
}

.upload-flow .card-nested-fields > .sec-note,
.upload-flow .card-nested-fields .sec-note{
    font-size: 13px;
    font-weight: 500;
    line-height: 16px;
    letter-spacing: -0.01em;
    color: #1E1C1A;
}

.upload-flow [data-photo-upload-pricing-target="saleSection"] > p.mt-3{
    font-size: 15px;
    font-weight: 500;
    line-height: 18px;
    letter-spacing: -0.02em;
}

.upload-flow [data-photo-upload-pricing-target="saleSection"] small{
    display: inline-block;
    margin-top: 4px;
    font-size: 13px;
    line-height: 16px;
    letter-spacing: -0.01em;
    color: #757575;
}

.upload-flow .pro-mention{
    font-size: 13px;
    font-weight: 500;
    line-height: 16px;
    letter-spacing: -0.01em;
    color: #242424;
}

.upload-flow .pro-mention strong,
.upload-flow .pro-mention .flow-link{
    font-size: 13px;
}

.upload-flow .tier-head{
    margin-bottom: 12px;
    font-size: 13px;
    font-weight: 600;
    line-height: 16px;
    letter-spacing: -0.01em;
    color: #757575;
}

.upload-flow .tier-rows{
    gap: 12px;
}

.upload-flow .tier-row{
    min-height: 44px;
    padding: 12px 16px;
    gap: 16px;
    border-radius: 12px;
    background-color: #F6F6F6;
}

.upload-flow .tier-row-label{
    gap: 4px;
}

.upload-flow .tier-row-threshold,
.upload-flow .tier-row-range{
    font-size: 13px;
    line-height: 16px;
    letter-spacing: -0.01em;
    color: #1E1C1A;
}

.upload-flow .tier-row-figures{
    gap: 12px;
}

.upload-flow .tier-row-price{
    font-size: 15px;
    font-weight: 600;
    line-height: 18px;
    letter-spacing: -0.02em;
    color: #1E1C1A;
}

.upload-flow .deal-pill{
    justify-content: center;
    min-width: 100px;
    height: 23px;
    padding: 4px 6px;
    gap: 3px;
    border-radius: 8px;
    background-color: #8C78E9;
    color: #FFFFFF;
    font-size: 12px;
    font-weight: 700;
    line-height: 15px;
    letter-spacing: -0.02em;
}

.upload-flow .deal-pill strong{
    font-weight: 700;
}

.upload-flow .tier-rows + p{
    margin-top: 16px !important;
}

.upload-flow .tier-rows + p .flow-link{
    font-size: 13px;
    font-weight: 600;
    line-height: 16px;
    letter-spacing: -0.01em;
}

/* Profil public, volet Photos (maquette PROFILE PAGE MOBILE, EVENT_FILTER) : les puces tiennent
   sur une rangée qui défile, « Trier par » juste après les sports, 12px sous le filet des onglets
   (la gouttière de la grille et la marge des onglets en donnaient 48). */
@media (max-width: 991.98px) {
    #profile-photos .photo-filter-bar{
        flex-wrap: nowrap !important;
        gap: 8px !important;
        margin-top: -20px;
        margin-bottom: 24px !important;
    }

    #profile-photos .photo-filter-bar .filter-chips{
        flex: 1 1 auto;
        min-width: 0;
    }

    .profile-tabs{
        border-bottom-color: #E1DBCD;
    }
}

/* Desktop : la rangée se déplie, « Trier par » reprend sa place à droite */
@media (min-width: 992px) {
    #profile-photos .photo-filter-bar .filter-chips{
        display: contents !important;
    }

    #profile-photos .photo-filter-bar{
        gap: 8px !important;
    }

    #profile-photos .photo-filter-bar .filter-clear{
        order: 1;
        margin-left: 8px;
    }

    #profile-photos .photo-filter-bar .filter-sort{
        order: 2;
        margin-left: auto;
    }
}

/* Panneaux de filtres mobiles : un seul axe. Figma pose le pied à 24px et le contenu à 18 ; le
   décalage de 6px se voyait sous les libellés, les boutons prennent donc la gouttière de 18. */
@media (max-width: 991.98px) {
    .filter-panel-foot{
        padding-left: 18px;
        padding-right: 18px;
    }
}

/* La croix : son tracé laisse 1,3px de blanc à droite dans sa boîte de 14. Centrée dans son
   bouton, elle ne se décale que de la moitié de sa marge, d'où -2,6 pour rejoindre les contrôles. */
.filter-panel-close svg{
    margin-right: -2.6px;
}

/* Un libellé sur deux lignes garde son radio sur la PREMIÈRE ligne, pas entre les deux ;
   une option d'une ligne ne bouge pas (3,5 + 18 + 3,5 = 25). */
.filter-list-single .filter-row:has(> [type="radio"]){
    align-items: flex-start;
}

.filter-list-single .filter-row:has(> [type="radio"]) .filter-row-label{
    padding: 3.5px 0;
}

.filter-list-single .filter-row:has(> [type="radio"]) .filter-row-check{
    margin-top: 2.5px;
}

/* Profil public, bureau (maquette PROFILE DESKTOP) : cartes crème au rayon 24, ombre 0 2 2 ;
   frise à 7px de pastille et 14 jusqu'au contenu. Agenda : 16px en haut, date à 30px du titre
   sur une rangée de 28, vignette de 72 à 9px sous la rangée, 34px entre deux journées. */
@media (min-width: 992px) {
    .profile-page .profile-pane.card{
        border-radius: 24px;
        background-color: #FAF9F5;
        box-shadow: 0 2px 2px rgba(0, 0, 0, .1);
    }

    .profile-pane .timeline--agenda .timeline-item{
        grid-template-columns: 7px 1fr;
        gap: 14px;
    }

    #profile-agenda{
        padding: 16px 24px 24px;
    }

    #profile-agenda .sec-header{
        margin-bottom: 30px;
    }

    #profile-agenda .timeline--agenda{
        --timeline-agenda-header: 28px;
        margin-bottom: 0 !important;
    }

    #profile-agenda .timeline-item:not(:last-child){
        padding-bottom: 34px;
    }

    #profile-agenda .timeline-item:not(:last-child) .timeline-marker::before{
        height: calc(100% + 34px);
    }

    .profile-pane#profile-agenda .timeline--agenda .list-item{
        padding-top: 1px;
    }

    .profile-pane#profile-agenda .timeline--agenda .list-item .list-item-thumb{
        flex: 0 0 72px;
        width: 72px;
        height: 72px;
    }

    #profile-agenda .list-item-thumb,
    #profile-agenda .list-item-thumb .ratio,
    #profile-agenda .list-item-thumb .thumbnail-wrapper{
        border-radius: 16px;
    }

    #profile-agenda .list-item-thumb .ratio{
        box-shadow: inset 0 0 0 1px #FFFFFF;
    }

    #profile-agenda .d-grid{
        margin-top: 37px;
    }

    #profile-agenda .d-grid .btn{
        min-height: 35px;
        padding: 5px 12px;
        border: 0;
        border-radius: 12px;
        background-color: #EFE9DD;
        font-size: 15px;
        font-weight: 600;
    }
}

/* Onglets mobiles (maquette HOMEPAGE MOBILE, TEMPORAL_SELECTOR) : la rangée en space-between,
   chaque onglet à la mesure de sa pilule — 18px de côté, actif ou non (« Live » inactif y fait
   85px, comme actif). Le premier touche donc la marge gauche, le dernier la droite, quelle que
   soit la largeur de l'écran, et rien ne bouge quand on change d'onglet. Des parts égales
   centraient la pilule dans un quart d'écran : juste à 375px, décollée du bord au-delà.
   8px au-dessus des pilules, 16 jusqu'au filet #E1DBCD. Un onglet ne descend pas sous son
   libellé : quand ils ne tiennent plus (compteurs, écran étroit), la rangée défile. */
@media (max-width: 991.98px) {
    .tab-bar-nav{
        padding-top: 8px;
        padding-bottom: 14px;   /* + la réserve de 1px sous la pilule et le filet : 16 */
        border-bottom-color: #E1DBCD;
    }

    .tab-bar-block .tab-bar-nav .nav-item{
        flex: 0 0 auto;
    }

    /* 18px de côté dès 375px ; en deçà (360px, courant sous Android), le côté se resserre juste
       assez pour que les quatre onglets tiennent sans défiler. 196px : les quatre libellés et le
       glyphe de « Live », sans leurs côtés ; 32 : les marges de l'écran ; 8 côtés à répartir. */
    .tab-bar-block .tab-bar-nav .nav-link,
    .tab-bar-block .tab-bar-nav .nav-link:not(.active){
        padding-left: clamp(8px, (100vw - 32px - 196px) / 8, 18px);
        padding-right: clamp(8px, (100vw - 32px - 196px) / 8, 18px);
    }

    /* Avec les compteurs, les libellés font 276px : à 375, 8px de côté tiennent encore les quatre
       onglets ; plus étroit, 4px au plus bas, puis la rangée défile. */
    .tab-bar-block .tab-bar-nav--counted .nav-link,
    .tab-bar-block .tab-bar-nav--counted .nav-link:not(.active){
        padding-left: clamp(4px, (100vw - 32px - 276px) / 8, 18px);
        padding-right: clamp(4px, (100vw - 32px - 276px) / 8, 18px);
    }
}

/* Le lien étiré de ProfileListItem était un enfant flex : vide, il prenait quand même l'écart de
   16px et poussait l'avatar d'autant. Hors du flux, il couvre toujours la ligne. */
.profile-card > .stretched-link{
    position: absolute;
    inset: 0;
}

/* Photographes d'un évènement, mobile (maquette GALLERY MOBILE EVENT) : « (n) » en ink 15/500
   à une espace du titre, 12px jusqu'aux cartes et entre elles ; carte au rayon 16, 6px de
   marge filet compris, filet #DCDAD1, sans fond ; avatar de 51 à 12px du nom, 4px entre nom et méta. */
@media (max-width: 991.98px) {
    .event-photographers-col:has(> .event-section-card .event-photographer-card) > .sec-header{
        margin-bottom: 12px;
    }

    .event-photographers-col .sec-header-title{
        gap: 5px;
    }

    .event-photographers-col .sec-header-title-count{
        letter-spacing: -0.02em;
        color: #1E1C1A;
    }

    .event-section-card > .d-flex.flex-column{
        gap: 12px !important;
    }

    .event-photographer-card{
        padding: 5px;   /* le filet de la maquette est intérieur : 1 + 5 = ses 6px */
        border-radius: 16px;
    }

    .event-photographer-card:not(.event-photographer-card--me){
        border-color: #DCDAD1;
        background-color: transparent;
    }

    .event-photographer-card .profile-card{
        gap: 12px !important;
    }

    .event-photographer-card .avatar{
        width: 51px;
        height: 51px;
        flex: 0 0 51px;
    }

    .event-photographer-card .list-item-title{
        margin-bottom: 4px !important;
    }
}

/* Panneau Photographes (maquette FILTRE PHOTOGRAPHE) : 26px du titre à « Photos en ligne », et
   20px sous la dernière carte — elle butait sur le filet du pied. */
@media (max-width: 991.98px) {
    .filter-panel:has(.filter-list-cards) .filter-panel-form{
        margin-top: 9px;
    }
}

.filter-list-cards.filter-panel-body{
    padding-bottom: 20px;
}

/* Panneaux de la page évènement : la liste à 16px du titre (CONTENT des panneaux Prix et
   Albums), à 14px pour « Trier par » (gap 14) — le panneau en pose 17 */
@media (max-width: 991.98px) {
    .event-price-list,
    .album-panel.filter-panel-body{
        margin-top: -1px;
    }

    .event-sort-list{
        margin-top: -3px;
    }
}

/* « Trier par » : le critère en 600 15, son détail entre parenthèses en 400 14. Sa hauteur de
   ligne reste sous celle du libellé : à 18, le corps plus petit décalait sa ligne de base et
   la rangée prenait un demi-pixel (25,5). */
.event-sort-detail{
    font-size: var(--sp-font-size-label);
    line-height: 15px;
    letter-spacing: var(--sp-font-tracking-tight);
}

/* Vue photo mobile (maquette PHOTO PAGE EVENT MOBILE) : 16px entre chaque bloc, y compris
   après le bouton et la publicité ; 6px de l'icône au libellé du bouton gratuit. */
@media (max-width: 991.98px) {
    .photo-page-side > .photo-actions,
    .photo-page-side > .mb-4:has(> .ad-slot){
        margin-bottom: 16px !important;
    }
}

.photo-actions .btn-free{
    gap: 6px !important;
}

/* Boutons de verre posés sur la photo, mobile (maquettes PHOTO PAGE EVENT MOBILE et GALLERY
   MOBILE EVENT, hauteur 40 du retour client) : flou de 4, liseré dégradé d'1px, pilule
   d'actions de 78px sans ombre. Vue photo : les deux verres clairs, sans ombre, date en
   GREY_FADE. Page évènement : retour clair ombré (0 4 24 à 10 %), pilule sombre. */
@media (max-width: 991.98px) {
    .photo-stage-bar .btn-glass,
    .photo-stage-bar .photo-stage-actions{
        border: 1px solid transparent;
        background:
            linear-gradient(var(--sp-glass-button-bg-light), var(--sp-glass-button-bg-light)) padding-box,
            var(--sp-glass-menu-rim) border-box;
        backdrop-filter: blur(4px);
        -webkit-backdrop-filter: blur(4px);
        box-shadow: none;
    }

    .photo-stage-bar .photo-stage-actions{
        padding: 0 2px;
    }

    .photo-stage-bar .photo-stage-date{
        color: #D1D1D1;
    }

    .event-highlighted-header--page .event-hero-back.btn-glass{
        border: 1px solid transparent;
        background:
            linear-gradient(var(--sp-glass-button-bg-back), var(--sp-glass-button-bg-back)) padding-box,
            linear-gradient(160deg, #FFFFFF 0%, rgba(255, 255, 255, .02) 50%, #FFFFFF 100%) border-box;
        backdrop-filter: blur(4px);
        -webkit-backdrop-filter: blur(4px);
        box-shadow: 0 4px 24px rgba(0, 0, 0, .1);
    }

    .event-highlighted-header--page .glass-group{
        padding: 0 2px;
        border: 1px solid transparent;
        background:
            linear-gradient(var(--sp-glass-button-bg), var(--sp-glass-button-bg)) padding-box,
            var(--sp-glass-menu-rim) border-box;
        backdrop-filter: blur(4px);
        -webkit-backdrop-filter: blur(4px);
        box-shadow: none;
    }

    .event-highlighted-header--page .glass-group .glass-group-item{
        width: 36px;
        min-width: 36px;
        height: 38px;
        min-height: 38px;
    }
}

/* Accueil bureau (maquette HOMEPAGE DESKTOP) : la barre haute fait 61px filet compris ; la
   pilule « Live » à 24px sous elle et à 16px du filet des onglets. */
@media (min-width: 992px) {
    .topbar-front{
        min-height: calc(var(--sp-layout-topbar-h-desktop) - 1px);
    }

    .tab-bar-block{
        padding-top: 1px;
        padding-bottom: 13px;
    }
}

/* =============================================================================================
   Revue de la maquette écran par écran (sept. 2026) — une section par écran, des sélecteurs
   propres à l'écran : chaque écran a ses cotes, une correction ne doit pas déborder sur un autre.
   ============================================================================================= */

/* --- Accueil mobile (Figma HOMEPAGE_LIVE_CELL_VIEW 2356:11733) ------------------------------- */
@media (max-width: 991.98px) {
    /* Listes de l'accueil : la rangée porte déjà ses 12px de part et d'autre du filet (pas de
       97px, fiche list-item) ; la gouttière verticale de la grille les doublait (pas de 108px). */
    .awaiting-list .list-item-grid,
    .list-item-grid[data-infinite-scroll-target="grid"]:has(.list-item){
        --bs-gutter-y: 0px;
    }

    /* Grille de cartes (Récent, HOMEPAGE_RECENT 1718:7974) : 18px entre les cartes, comme le
       rail, et le titre à 18px de la première — la même respiration que « Le Live » */
    .list-item-grid[data-infinite-scroll-target="grid"]:has(.event-highlighted:not(.event-highlighted-short)){
        --bs-gutter-y: 18px;
    }

    .container-home .sec-header:has(+ .list-item-grid .event-highlighted:not(.event-highlighted-short)){
        margin-bottom: 18px;
    }

    /* Cartes de la grille : 16px de marge, 6px entre sport, nom et lieu, ligne du sport de 18.
       Pas les cartes `short` de « Voir tout », qui ont leur maquette (LIST_VIEW 1312:1221). */
    [data-infinite-scroll-target="grid"] .event-highlighted:not(.event-highlighted-short) .event-highlighted-top{
        padding: var(--sp-space-4);
    }

    [data-infinite-scroll-target="grid"] .event-highlighted:not(.event-highlighted-short) .event-highlighted-scrim{
        gap: 6px;
    }

    [data-infinite-scroll-target="grid"] .event-highlighted:not(.event-highlighted-short) .event-highlighted-sport-line{
        min-height: 18px;
    }

    /* Rail : la ligne du sport fait 20px (pastille de 14×20), le libellé s'y centre */
    .event-rail .event-highlighted-sport-line{
        min-height: 20px;
    }

    /* 12px, le filet sur son propre pixel, 12px : le filet est tracé dans la marge basse */
    .awaiting-list .list-item,
    [data-infinite-scroll-target="grid"] .list-item{
        padding-bottom: 13px;
    }

    /* Le filet de « En attente » à 17px des points du rail (6 sous les points, puis 11) */
    .container-home .event-rail-section + .awaiting-header{
        margin-top: 17px !important;   /* l'utilitaire mt-4 du partiel */
    }

}

/* « En attente de photo » (EVENT_LIST_CLEAN, et NAME_DETAILS sur desktop) : 8px entre chaque
   rôle — titre, détail, méta — sur les deux supports */
.awaiting-list .list-item-body{
    gap: 8px;
}

.awaiting-list .list-item-detail + .list-item-meta{
    margin-top: 0;
}

/* --- Barre haute ---------------------------------------------------------------------------- */
/* L'emplacement du badge panier reste vide tant que le panier l'est : sans cela il prend quand
   même un écart de la rangée, et le compte s'arrête 16px avant la marge de 50px (TOP BAR). */
.topbar-actions > span:not(:has(*)){
    display: none;
}

/* --- Accueil desktop (Figma HOME > DEPOT_ALBUMS 2685:15565) --------------------------------- */
@media (min-width: 992px) {
    /* Colonnes de ListItem au pas de 97px, comme la liste mobile : 12px, filet, 12px. Le filet
       est tracé en haut de l'item à partir de la 2e rangée ; la gouttière verticale l'éloignait
       de 12px de plus (pas de 117px). */
    .container-home .list-item-grid:has(.list-item){
        --bs-gutter-y: 0px;
    }

    .container-home .list-item-grid > .col:not(:nth-child(-n+3)) .list-item{
        padding-top: 13px;
    }

    /* Gouttière de 50px, celle de la barre haute (TOP BAR, marge 0 50) : sous 1230px, le contenu
       s'aligne sur le logo et sur le compte au lieu de coller à 17,5px du bord (2.5rem sur une
       racine à 14px) ; au-delà, il reste centré à 1130px comme sur la maquette. */
    .container.container-home{
        --bs-gutter-x: 100px;
    }

    /* Onglets (TEMPORAL_SELECTOR, 375px) : quatre quarts fixes, pour que rien ne bouge au
       changement d'onglet (la maquette donne à l'actif la mesure de sa pilule et répartit le
       reste, ce qui redistribue toute la rangée à chaque clic). Le 1er se cale à gauche, pilule
       comprise — là où la maquette pose Live —, le dernier à droite, les deux du milieu se
       centrent en laissant leur pilule déborder de leur boîte au lieu de l'élargir. */
    .tab-bar-block .tab-bar-nav .nav-item:first-child{
        justify-content: flex-start;
    }

    .tab-bar-block .tab-bar-nav .nav-item:last-child{
        justify-content: flex-end;
    }

    .tab-bar-block .tab-bar-nav .nav-item .nav-link,
    .tab-bar-block .tab-bar-nav .nav-item .nav-link:not(.active){
        padding-left: 18px;
        padding-right: 18px;
    }

    .tab-bar-block .tab-bar-nav .nav-item:not(:first-child):not(:last-child) .nav-link{
        margin: 0 -18px;
    }
}

/* --- Page évènement mobile (Figma MOBILE_GALLERY_EVENT > EVENT_V1 2180:6221) ---------------- */
@media (max-width: 991.98px) {
    /* Le hero à 10px sous le contenu de la barre haute (barre de 40 sans marge basse sur la
       maquette, de 44 avec 4px ici) ; les chips à 16px sous lui (FILTER, marge 16). La hauteur
       de 180px reste celle du retour client. */
    .event-highlighted-header--page{
        margin-top: 6px;
    }

    .event-highlighted-header--page.mb-4{
        margin-bottom: 12px !important;   /* l'utilitaire mb-4 du gabarit */
    }

    /* Ligne du sport de 18px (SPORT TYPE), 6px au-dessus du titre */
    .event-highlighted-header--page .event-highlighted-sport{
        min-height: 18px;
    }

    /* La frise à 25px sous les chips : 16 de marge de la rangée, puis 9 en tête de contenu */
    main:has(.event-highlighted-header--page) .photo-filter-bar{
        margin-bottom: 21px !important;   /* l'utilitaire mb-3 */
    }
}

/* --- Page évènement desktop (Figma DESKTOP > GALLERY 2434:7251) ------------------------------ */
@media (min-width: 992px) {
    /* Hero : sport, lieu et date en 500 20/24 sous le titre en 40/48 (EVENT INFOS) */
    .event-highlighted-header--page .event-highlighted-sport{
        font-size: 20px;
        font-weight: var(--sp-font-weight-body);
        line-height: 24px;
        letter-spacing: var(--sp-font-tracking-meta);
    }

    .event-highlighted-header--page .event-highlighted-meta,
    .event-highlighted-header--page .event-highlighted-meta .event-highlighted-when{
        font-size: 20px;
        font-weight: var(--sp-font-weight-body);
        line-height: 24px;
        letter-spacing: var(--sp-font-tracking-tighter);
    }

    /* Organisateur, Partager, Nouvelles photos : 500, pas 600 */
    .event-highlighted-header--page .event-highlighted-actions-desktop .btn{
        font-weight: var(--sp-font-weight-body);
    }

    /* Les chips à 16px sous le hero (FILTER, marge 16 0), la galerie 16px sous elles */
    .event-highlighted-header--page.mb-4{
        margin-bottom: 12px !important;   /* l'utilitaire mb-4 du gabarit */
    }

    main:has(.event-highlighted-header--page) .photo-filter-bar{
        margin-bottom: 13px !important;   /* l'utilitaire mb-3 : 4 de rangée + 13 = 16 + le filet */
    }

    /* Frise desktop : la journée en 600 20/24, son compteur en 700 14/17 */
    main:has(.event-highlighted-header--page) .timeline-label{
        font-size: 20px;
        line-height: 24px;
        letter-spacing: var(--sp-font-tracking-tighter);
    }

    main:has(.event-highlighted-header--page) .timeline-count{
        padding: 0 6px;
        border-radius: var(--sp-radius-sm);
        font-size: 14px;
        line-height: 17px;
    }
}

/* --- Profil photographe mobile (Figma MOBILE_PROFILE > EVENT_V1 1972:41853) ----------------- */
@media (max-width: 991.98px) {
    /* La carte à 10px sous le contenu de la barre haute (HERO, marge 10 16 0), comme le hero
       de la page évènement */
    .card-photo--profile{
        margin-top: 6px;
    }
}

/* --- Profil photographe desktop (Figma PROFILE DESKTOP > GALLERY 2488:25280) ---------------- */
@media (min-width: 992px) {
    /* La carte d'identité en grand : 394 × 231, coin 24, nom en 600 24/29 */
    .card-photo--profile{
        height: 231px;
        min-height: 231px;
        border-radius: var(--sp-radius-2xl);
    }

    .card-photo--profile .card-photo-identity h1{
        font-size: var(--sp-font-size-h2-dense);
        line-height: 29px;
    }
}

/* --- Panier (Figma PAYMENT_PAGE > CART 1517:11219) ----------------------------------------- */
/* Le lieu et la date de l'évènement en 500 11/13 (EVENT & TIME) */
.cart-group-event-meta{
    font-size: 11px;
    line-height: 13px;
}

/* --- Tableau de bord photographe desktop (Figma DASHBOARD 2670:17929) ----------------------- */
/* Le club a le même écran (même composition, mêmes surfaces) : mêmes cotes. */
@media (min-width: 992px) {
    /* Carte profil : lieu en 14/17, chiffres en 15/18 */
    .photographer-layout.dashboard-view .card-photo-meta,
    .club-layout.dashboard-view .card-photo-meta{
        line-height: 17px;
    }

    .photographer-layout.dashboard-view .card-photo .stat-block-value,
    .club-layout.dashboard-view .card-photo .stat-block-value{
        line-height: 18px;
    }

    /* Cagnotte : montant en 700 24/29, légende de la jauge en 13/16 */
    .photographer-layout.dashboard-view .section-figure,
    .club-layout.dashboard-view .section-figure{
        line-height: 29px;
        letter-spacing: var(--sp-font-tracking-tighter);
    }

    .photographer-layout.dashboard-view .progress-gauge-legend,
    .club-layout.dashboard-view .progress-gauge-legend{
        line-height: 16px;
    }

    /* Mes transactions (VENTES 4297:5531) : 21px au-dessus du titre, 24 sur les autres côtés */
    .dashboard-transactions{
        padding-top: 21px;
    }
}

/* --- Photographes d'un évènement sans photos (Figma GALLERY EVENT 2211:10641 et desktop
       2436:24368) ------------------------------------------------------------------------------ */
/* Les deux maquettes dessinent la même carte : 63px, rayon 16 (pas une pilule), 6px de marge
   filet compris, avatar de 51 à 12px du nom, 12px entre les cartes. La règle « pilule » du
   desktop (58px, avatar de 40) ne venait d'aucune maquette. */
.event-section-card > .d-flex.flex-column:has(> .event-photographer-card){
    gap: 12px !important;
}

.event-photographer-card{
    padding: 5px;   /* filet intérieur : 1 + 5 = les 6px de la maquette */
    border-radius: 16px;
}

.event-photographer-card:not(.event-photographer-card--me){
    border-color: #DCDAD1;
    background-color: transparent;
}

/* La mienne : fond crème, 12px à droite pour le badge */
.event-photographer-card--me{
    padding-right: 11px;
}

.event-photographer-card .profile-card{
    gap: 12px !important;
}

.event-photographer-card .avatar{
    width: 51px;
    height: 51px;
    flex: 0 0 51px;
}

.event-photographer-card .list-item-title{
    margin-bottom: 4px !important;
}

/* « Moi » : étiquette de 27×16, coin 6, 500 10/12 — alignée sur le nom, à 12px du bord droit
   (et non la pilule de 22px centrée dans la carte) */
.event-photographer-me{
    top: 14px;
    right: 11px;   /* + le filet de 1px de la carte : 12px du bord */
    transform: none;
    padding: 2px 5px;
    border-radius: 6px;
    font-size: 10px;
    font-weight: var(--sp-font-weight-body);
    line-height: 12px;
    letter-spacing: -0.03em;
}

/* Desktop de cette page (CONTENT 2436:24368) : deux colonnes de 488 (col-lg-6 dans le gabarit)
   à 24px sous le hero et 24px l'une de l'autre ; titres en retrait de 12 ; cartes à 16px de
   marge, coin 24, fond #FAF9F5, ombre 0 2 2 à 10 %. */
@media (min-width: 992px) {
    main:has(.event-nophotos-col) .event-highlighted-header--page.mb-4{
        margin-bottom: 24px !important;
    }

    /* Titres en retrait de 12 ; les 16px jusqu'à la carte restent ceux du retour client */
    .event-nophotos-col > .sec-header{
        padding: 0 12px;
    }

    .event-nophotos-col > .event-section-card{
        padding: 16px;
        border-radius: 24px;
        background-color: #FAF9F5;
        box-shadow: 0 2px 2px rgba(0, 0, 0, .1);
    }
}

/* « Publier mes photos », « Quitter l'évènement » : 24px sur les deux maquettes (Number, marge
   4/8), et non les 26 de btn-xs */
.event-nophotos-col > .sec-header .btn{
    min-height: 24px;
    border-width: 0;
}

/* --- Champs de lieu (autocomplétion Google) ------------------------------------------------ */
/* Filtre Localisation : la loupe se centre sur le CHAMP (46px), pas sur son conteneur — les
   suggestions s'y rendent dans le flux (.filter-location-panel .places-suggestions) et
   l'allongent : centrée à 50 %, la loupe tombait sous le champ, sur la première suggestion. */
.filter-location-icon{
    top: 23px;
}

/* Panneau Localisation (Figma CASE_LOCATION, Bottom_card) : il ne suit pas la gouttière des
   autres panneaux (FILTER_PAGE, 18px) — 16px de côté, 18 au-dessus, 23 sous le titre. Le pied
   garde ses 18px et non les 24 de la maquette : le décompte « (49) » élargit le bouton principal,
   et à 24 « Effacer le filtre » passait sur deux lignes. */
@media (max-width: 991.98px) {
    .filter-panel:has(.filter-location-panel){
        gap: 23px;
        padding: 18px var(--sp-space-4) var(--sp-space-6);
    }

    .filter-panel:has(.filter-location-panel) .filter-panel-foot{
        margin-left: calc(-1 * var(--sp-space-4));
        margin-right: calc(-1 * var(--sp-space-4));
    }
}

/* « Chercher un lieu » dans sa rangée de 28px (3 au-dessus, 6 dessous) : le champ tombe à 33px
   du haut du libellé, puis 16px jusqu'au rayon */
.filter-location-label{
    padding: 3px 0 6px;
}

.filter-location-search{
    margin-bottom: var(--sp-space-4);
}

/* Loupe de 20 à 14px du bord, invite à 12px d'elle */
.filter-location-icon{
    left: 14px;
    width: 20px;
    height: 20px;
}

.filter-location-field .form-control{
    padding-left: 46px;
}

/* Curseur : 16px de la légende à la piste, 4 de la piste aux bornes (11px), poignée de 16 */
.filter-location-panel .slider{
    gap: 0;
}

.filter-location-panel .slider-head{
    margin-bottom: var(--sp-space-4);
}

.filter-location-panel .slider-bounds{
    margin-top: var(--sp-space-1);
    font-size: 11px;
}

.filter-location-panel .slider-input::-webkit-slider-thumb{
    width: 16px;
    height: 16px;
    box-shadow: 0 0 4px rgba(0, 0, 0, .39);
}

.filter-location-panel .slider-input::-moz-range-thumb{
    width: 16px;
    height: 16px;
    box-shadow: 0 0 4px rgba(0, 0, 0, .39);
}

/* Carte « Dates et lieu » de la création d'évènement (Figma DROP) : le libellé ne flotte plus
   par réduction (Bootstrap : 15px à 85 %, marges en rem au pas de 14px, donc 22,75 / 10,5px) —
   il se pose en 13px au-dessus de la valeur, en permanence, et la valeur s'écrit en 600 13px
   gris foncé. Dates : 61px au coin 12 ; lieu : 59px au coin 16 (maquette). Le libellé restant
   levé, l'invite du champ de lieu se lit au repos au lieu d'être masquée. */
.event-dates-place.card .form-floating > .form-control{
    height: 61px;
    min-height: 61px;
    padding: 31px 8px 12px 16px;
    border-color: var(--sp-color-grey-300);
    border-radius: var(--sp-radius-md);
    font-size: 13px;
    font-weight: var(--sp-font-weight-title);
    line-height: 16px;
    letter-spacing: -0.01em;
    color: var(--sp-color-grey-700);
}

.event-dates-place.card .form-floating > .form-control ~ label{
    top: 12px;
    left: 1px;
    height: auto;
    padding: 0 0 0 16px;
    transform: none;
    opacity: 1;
    font-size: 13px;
    font-weight: var(--sp-font-weight-body);
    line-height: 16px;
    letter-spacing: -0.01em;
    color: var(--sp-color-grey-600);
}

.event-dates-place.card .form-floating > .form-control::placeholder{
    font-weight: var(--sp-font-weight-body);
    color: var(--sp-color-text-muted);
}

.event-dates-place.card .places-anchor > .form-control{
    height: 59px;
    min-height: 59px;
    padding-top: 30px;
    padding-bottom: 11px;
    border-radius: var(--sp-radius-lg);
}

.event-dates-place.card .places-anchor > .form-control ~ label{
    top: 9px;
}

/* Agenda de 18px à droite des dates, à 12px du bord (8 de marge + 3 de case + le filet) :
   décoratif, le clic traverse jusqu'au champ qui ouvre le calendrier */
.event-dates-place .row > [class*="col-"]:has(> .is-datefield){
    position: relative;
}

/* En erreur, l'icône d'alerte Bootstrap tombait sous l'agenda (retour client du 14/10) : la bordure
   rouge et le message suffisent. */
.is-datefield > .form-control.is-invalid{
    background-image: none;
}

.event-date-icon{
    position: absolute;
    top: 21.5px;
    right: calc(var(--bs-gutter-x) * .5 + 12px);
    color: var(--sp-color-grey-600);
    pointer-events: none;
}

/* Carte du panneau Localisation (Figma CASE_LOCATION, Figmap) : 222px de haut, à 22px des bornes
   du rayon (14 + 8), légende 500 15/18 à 10px dessous, 18px jusqu'au filet du pied (16 + 2) */
.filter-location-map-block{
    margin-top: 22px;
}

.filter-location-map{
    height: 222px;
    background-color: var(--sp-color-bg-sunken);
}

.filter-location-map-hint{
    margin: 10px 0 0;
    font-size: 15px;
    font-weight: var(--sp-font-weight-body);
    line-height: 18px;
    letter-spacing: -0.02em;
    color: var(--sp-color-text-default);
}

.filter-location-panel:has(.filter-location-map-block){
    padding-bottom: 18px;
}

/* Deux dates de 230px à 24px l'une de l'autre, qui ne remplissent pas la ligne (maquette) */
@media (min-width: 992px) {
    .event-dates-place .row:has(> [class*="col-"] > .is-datefield){
        --bs-gutter-x: 24px !important;
    }

    .event-dates-place .row > [class*="col-"]:has(> .is-datefield){
        flex: 0 0 auto;
        /* plafonnées à la demi-ligne : sous ~1200px, deux fois 230 ne tiennent plus */
        width: min(calc(230px + var(--bs-gutter-x)), 50%);
    }
}

/* Invite du champ de lieu en 15px (maquette) là où l'on pointe à la souris ; les écrans tactiles
   gardent 16px — en dessous, Safari iOS zoome sur le champ dès qu'on le touche. */
@media (hover: hover) and (pointer: fine) {
    .filter-location-field .form-control{
        font-size: 15px;
        line-height: 18px;
    }
}

/* --- Mot de passe d'un album (Figma MOBILE_GALLERY, Bottom_card « Mot de passe ») ------------ */
/* Rangée de titre de 25px, croix comprise (elle déborde comme celle des autres panneaux) */
.album-unlock-head{
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-space-3);
    height: 25px;
}

/* 18px au-dessus du titre, 23 entre les blocs */
@media (max-width: 991.98px) {
    .album-unlock-sheet{
        padding-top: 18px;
    }
}

.album-unlock-sheet .album-unlock{
    gap: 23px;
}

/* Rappel de 100px : lignes à 4px, sport sur 18 */
.album-unlock-recap-body{
    gap: var(--sp-space-1);
}

.album-unlock-sport{
    min-height: 18px;
}

/* L'album en pilule de verre clair (Clear Glass) : 28px, 500 13/16, cadenas de 12 */
.album-unlock-album.badge-glass{
    height: 28px;
    padding: 0 9px;
    border-radius: var(--sp-radius-full);
    background-color: rgba(255, 255, 255, .23);
    box-shadow: 0 8px 40px rgba(0, 0, 0, .2);
    font-size: var(--sp-font-size-meta);
    font-weight: var(--sp-font-weight-body);
    line-height: 16px;
    letter-spacing: var(--sp-font-tracking-meta);
}

/* Cadenas à 14px du bord, invite à 12px de lui */
.album-unlock-field .form-control{
    padding-left: 40px;
}

/* « Annuler » est un lien : en bloc, son libellé collait au haut du bouton de 42px */
.album-unlock-foot .btn{
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

/* La carte « Mot de passe » est blanche (maquette, Bottom_card #FFFFFF) : crème sur la page
   crème, elle ne se détachait que par son ombre */
.album-unlock{
    background-color: var(--sp-color-bg-surface);
}

/* Évènement privé (maquette « Mot de passe », carte « Etape du Tour ») : le nom en pilule de verre
   600 16/19 avec son cadenas, puis le lieu et le nombre de photos en 500 13/16 */
.album-unlock-album--event.badge-glass{
    font-size: var(--sp-font-size-h4);
    font-weight: var(--sp-font-weight-title);
    line-height: 19px;
    letter-spacing: var(--sp-font-tracking-tight);
}

.album-unlock-place{
    display: flex;
    align-items: center;
    font-size: var(--sp-font-size-meta);
    font-weight: var(--sp-font-weight-body);
    line-height: 16px;
    letter-spacing: var(--sp-font-tracking-meta);
}

/* Sur desktop, que la maquette ne dessine pas : pas de voile, la feuille devient une carte posée
   au centre de la page, à la largeur de la feuille mobile */
@media (min-width: 992px) {
    .album-unlock-anchor--event{
        width: 100%;
    }

    .album-unlock-anchor--event .filter-veil{
        display: none;
    }

    .album-unlock-anchor--event .filter-panel{
        position: static;
        width: 420px;
        margin: 0 auto;
        padding: 18px 18px 24px;
        border-radius: var(--sp-radius-lg);
    }
}

.album-unlock-album--event.badge-glass{
    height: 31px;
}

/* 18px du champ au filet du pied (16 de marge + 2 d'écart, Bottom_card) : le formulaire n'en
   posait que 8 */
.album-unlock-sheet .album-unlock-foot{
    margin-top: 10px;
}

/* --- Panneau Albums (Figma ALBUMS) --------------------------------------------------------- */
/* 18px entre la dernière journée et le filet du pied (CONTENT : 2 de marge + 16 d'écart) : elle
   y touchait, son ombre coupée net */
.album-panel{
    padding-bottom: 18px;
}

/* Onglets AVEC compteurs (filtre actif) sur desktop : leurs pilules demandent ~420px, les quarts
   fixes de 375 les faisaient se chevaucher (celles du milieu, décalées de -18px, se couvraient).
   Chaque onglet prend la mesure de sa pilule : 18px de côté actif ou non, rien ne bouge au clic. */
@media (min-width: 992px) {
    .tab-bar-block .tab-bar-nav--counted{
        flex: 0 0 auto;
        justify-content: flex-start;
    }

    .tab-bar-block .tab-bar-nav--counted .nav-item{
        flex: 0 0 auto;
    }

    .tab-bar-block .tab-bar-nav--counted .nav-item:not(:first-child):not(:last-child) .nav-link{
        margin: 0;
    }
}

/* Onglets et pastilles ne tiennent pas toujours sur une ligne (filtre actif sous ~1150px : 420 +
   585px) : les pastilles passent dessous, calées à droite, au lieu de sortir de l'écran. */
@media (min-width: 992px) {
    .tab-bar-block{
        flex-wrap: wrap;
        row-gap: var(--sp-space-3);
    }
}

/* --- Mini galerie défilante (galerie qui vend des photos, retour client) ------------------- */
/* Le ruban défile sur ses 20 vignettes ; elles gardent la taille du ruban fixe (4 à l'écran sur
   mobile, 7 — ou 6 à côté du dossard — sur desktop). La réserve de 6px au-dessus et au-dessous
   garde l'ombre de la courante et l'anneau de focus, que le défilement rognerait sinon. */
.photo-filmstrip--scroll{
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x proximity;
    scrollbar-width: none;
    padding-block: 6px;
    margin-top: -6px;
}

.photo-filmstrip--scroll::-webkit-scrollbar{
    display: none;
}

.photo-filmstrip--scroll .photo-filmstrip-item,
.photo-filmstrip--scroll .photo-filmstrip-item.is-current{
    flex: 0 0 calc((100% - 3 * var(--sp-space-2)) / 4);
    scroll-snap-align: start;
    background-color: var(--sp-color-bg-sunken);
}

@media (min-width: 992px) {
    .photo-page-below > .photo-filmstrip--scroll .photo-filmstrip-item,
    .photo-page-below > .photo-filmstrip--scroll .photo-filmstrip-item.is-current{
        flex-basis: calc((100% - 6 * var(--sp-space-4)) / 7);
    }

    .photo-page-below:has(> .bib-others) > .photo-filmstrip--scroll .photo-filmstrip-item,
    .photo-page-below:has(> .bib-others) > .photo-filmstrip--scroll .photo-filmstrip-item.is-current{
        flex-basis: calc((100% - 5 * var(--sp-space-2)) / 6);
    }
}

/* « Rejoindre » d'un photographe connecté (maquette, EVENT sans photos) : son avatar de 16px à 3px
   devant le libellé, une pastille « + » de 8px — blanche au filet encre — posée sur son coin */
.event-join-btn{
    gap: 3px;
}

.event-join-avatar{
    position: relative;
    display: inline-flex;
    flex-shrink: 0;
    width: 16px;
    height: 16px;
}

.event-join-avatar img{
    width: 16px;
    height: 16px;
    border-radius: 50%;
    object-fit: cover;
}

.event-join-badge{
    position: absolute;
    right: -3px;
    bottom: -2px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 8px;
    height: 8px;
    border: .75px solid var(--sp-color-text-default);
    border-radius: 50%;
    background-color: var(--sp-color-bg-surface);
    color: var(--sp-color-text-default);
}

/* --- Onglets de la vue photo : un écart ÉGAL entre les libellés ---------------------------- */
/* En quarts fixes, chaque onglet se centrait dans sa part : les libellés n'ayant pas la même
   longueur, les écarts variaient (47 / 30 / 22px entre Infos, Aperçu, License et Offres), et un
   onglet changeait de place selon les autres (License à 116 ou 202px). Désormais :
   - chaque boîte mesure son libellé (la pilule de 18px déborde de part et d'autre), sauf la 1re,
     dont la pilule touche le bord de la liste, et la 4e, qui touche l'autre bord ;
   - un seul écart, quel que soit le nombre d'onglets : celui qui fait tenir les quatre dans la
     mesure — 33px à 375, 46 à 414 —, plafonné à 48 (le desktop, une tablette) au lieu d'étaler
     quatre onglets à 148px les uns des autres. 244px : les quatre libellés (208) et les 18px de
     pilule des deux bords ;
   - sous 360px, la pilule passe à 12px de côté : à 18, l'active mordait de 3px sur sa voisine.
   La boîte ne dépend pas de l'onglet actif : rien ne bouge au clic. */
.photo-tabs{
    justify-content: flex-start;
    column-gap: min(48px, (100% - 244px) / 3);
}

.photo-tabs .nav-item,
.photo-tabs .nav-item:first-child,
.photo-tabs .nav-item:nth-child(4){
    flex: 0 0 auto;
    justify-content: flex-start;
}

.photo-tabs .nav-item .nav-link,
.photo-tabs .nav-item:not(:first-child) .nav-link,
.photo-tabs .nav-item:nth-child(4) .nav-link{
    padding-left: 18px;
    padding-right: 18px;
    margin: 0 -18px;
}

.photo-tabs .nav-item:first-child .nav-link{
    margin: 0 -18px 0 0;
}

.photo-tabs > .nav-item:nth-child(4) .nav-link{
    margin: 0 0 0 -18px;
}

@media (max-width: 359.98px) {
    .photo-tabs{
        column-gap: min(48px, (100% - 232px) / 3);
    }

    .photo-tabs .nav-item .nav-link,
    .photo-tabs .nav-item:not(:first-child) .nav-link,
    .photo-tabs .nav-item:nth-child(4) .nav-link{
        padding-left: 12px;
        padding-right: 12px;
        margin: 0 -12px;
    }

    .photo-tabs .nav-item:first-child .nav-link{
        padding-left: 12px;
        padding-right: 12px;
        margin: 0 -12px 0 0;
    }

    .photo-tabs > .nav-item:nth-child(4) .nav-link{
        margin: 0 0 0 -12px;
    }
}

/* « Prévenez-moi » : ce que l'abonnement suit (retour client). « Tout l'évènement » a la carte
   d'une journée du panneau Albums ; éteint, les journées et leurs albums s'ouvrent dessous. */
.subscribe-scope{
    display: flex;
    flex-direction: column;
    gap: var(--sp-space-3);
}

.subscribe-scope-all .album-group-text{
    flex: 1;
    margin: 0;
    cursor: pointer;
}

.subscribe-scope-list{
    min-width: 0;
    margin: 0;
    padding: 0;
    border: 0;
    gap: var(--sp-space-3);
}

/* Une journée et ses albums forment UNE carte : les albums s'ouvrent dans la carte, sous un
   filet, et non dans un second cadre détaché (on lisait deux blocs pour un seul choix). */
.subscribe-scope-list .album-group{
    border: 1px solid transparent;
    border-radius: var(--sp-radius-lg);
    background-color: var(--sp-color-bg-cream);
    box-shadow: var(--sp-shadow-sm);
}

.subscribe-scope-list .album-group:has(.album-group-toggle[aria-expanded="true"]){
    border-color: var(--sp-color-border-brown);
    border-radius: var(--sp-radius-md);
    box-shadow: none;
}

.subscribe-scope-list .album-group-head,
.subscribe-scope-list .album-group-head:has(.album-group-toggle[aria-expanded="true"]){
    border: 0;
    background: none;
    box-shadow: none;
}

/* Les albums alignés sur le titre de leur journée (16 + chevron 14 + 8), leur case sur
   l'interrupteur */
.subscribe-scope-list .album-group-list .filter-list{
    margin: 0 var(--sp-space-3) 0 38px;
    padding: var(--sp-space-3) 0;
    border: 0;
    border-top: 0.5px solid var(--sp-color-border-default);
    border-radius: 0;
}

/* Une journée sans album n'a pas de chevron : son titre garde la même colonne que les autres */
.subscribe-scope-list .album-group--bare .album-group-toggle{
    padding-left: 22px;
}

/* Switch et case FIDÈLES À LA MAQUETTE (panneau ALBUMS), partout — y compris les panneaux de
   filtres, où ils avaient grossi en 46×26 et 22px :
   - switch : piste pleine 36×20 sans filet, pastille blanche de 16 (2px de marge) portant
     l'ombre `0 2px 4px rgba(39,39,39,.1)` ;
   - case : 18×18, rayon 6, coche blanche. */
.form-switch .form-check-input,
.form-switch .form-check-input:focus,
.form-switch .form-check-input:checked{
    width: 36px;
    height: 20px;
    border-width: 0;
    --bs-form-switch-bg: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-10 -10 20 20'%3e%3cdefs%3e%3cfilter id='s' x='-50%25' y='-50%25' width='200%25' height='200%25'%3e%3cfeDropShadow dx='0' dy='2' stdDeviation='2' flood-color='%23272727' flood-opacity='.1'/%3e%3c/filter%3e%3c/defs%3e%3ccircle r='8' fill='%23fff' filter='url(%23s)'/%3e%3c/svg%3e");
}

.album-panel .filter-row-check[type="checkbox"],
.filter-list-cards .filter-row-check[type="checkbox"]{
    width: 18px;
    height: 18px;
    border-radius: 6px;
}

/* Lignes d'albums FIDÈLES À LA MAQUETTE (ALBUMS > ITEM) : 39px (nom 19 + 4 + nombre 16), puis
   8px, un filet, 8px avant la suivante. Le filet collait à la ligne suivante dès le deuxième
   album d'une journée : la règle `:has()` du premier sélecteur, plus spécifique, y remettait
   le padding-top à 0 (17px au-dessus du filet, 9 en dessous). La case suit la ligne du nom. */
.album-panel .filter-row,
.album-panel .filter-list-single .filter-row + .filter-row:has(> [type="checkbox"]){
    align-items: flex-start;
    min-height: 39px;
    padding: 0;
}

.album-panel .filter-list-single .filter-row + .filter-row,
.album-panel .filter-list-single .filter-row + .filter-row:has(> [type="checkbox"]){
    min-height: 0;
    margin-top: var(--sp-space-2);
    padding-top: var(--sp-space-2);
    border-top: 0.5px solid var(--sp-color-border-default);
}

.album-panel .filter-row-check[type="checkbox"]{
    margin-top: 1px;
}

/* Liste : 12px en haut, 7 en bas, noms à 34px du bord (ITEM, pad 12 12 7 34) */
.album-panel .album-group-list .filter-list{
    padding: var(--sp-space-3) var(--sp-space-3) 7px 34px;
}

/* Panneau Albums du filtre — FIDÈLE À LA MAQUETTE ALBUMS (2833:5765 ; la version 4628:5593 en une
   seule carte n'existe plus dans le fichier) ; « Photos sans album » et « Pas encore de photo »
   restent (retours client). La modale « Prévenez-moi » garde ses propres règles.

   Journée repliée : carte crème de 63px, 12/12/12/18, coins de 16, ombre 0 1 1 à 5 % ; chevron
   de 6,95×11,9 à 8px sous le haut du contenu, titre à 8px de sa colonne de 11,9px. */
.filter-panel-body.album-panel .album-group-head{
    padding: 11px 11px 11px 17px;
    box-shadow: 0 1px 1px rgba(0, 0, 0, .05);
}

.filter-panel-body.album-panel .album-group-chevron{
    display: block;
    width: 11.9px;
    height: auto;
    padding-top: 6px;
    line-height: 0;
}

/* Le glyphe (6,58×12,04 dans sa boîte de 16) se cale sur le bord gauche de sa colonne */
.filter-panel-body.album-panel .album-group-chevron svg{
    width: 16px;
    height: 16px;
    margin-left: -4.71px;
}

/* Journée dépliée (ALBUMS > DAY_EXTENDED) : DEUX cadres à 9px l'un de l'autre. L'en-tête reste
   crème, cerné de #A29689 au coin de 12, en 12/13/14/16 pour 65px ; ses albums s'ouvrent dessous
   dans un second cadre au filet #D3CDC3 (ITEM). */
.filter-panel-body.album-panel .album-group-head:has(.album-group-toggle[aria-expanded="true"]){
    min-height: 65px;
    padding: 11px 12px 13px 15px;   /* + le filet de 1 */
}

/* Le chevron pointe vers le bas : 11,9×6,95, contre le bord gauche, centré sur la date */
.filter-panel-body.album-panel .album-group-toggle[aria-expanded="true"] .album-group-chevron{
    padding-top: 3.3px;
}

.filter-panel-body.album-panel .album-group-toggle[aria-expanded="true"] .album-group-chevron svg{
    margin-left: -1.98px;
}

/* Journée sans album : pas de chevron, la date à 31px du bord de sa carte de 60px (DAY,
   12/12/12/31) */
.filter-panel-body.album-panel .album-group--bare .album-group-head{
    min-height: 60px;
    padding-left: 30px;   /* + le filet de 1 */
}

.filter-panel-body.album-panel .album-group--bare .album-group-text{
    padding-top: 0;
}

/* Les albums (ITEM) : 12/12/7/34 filet compris, noms de 39px séparés de 8 / filet / 8 */
.filter-panel-body.album-panel .album-group-list .filter-list{
    padding: 11px 11px 6px 33px;
}

.filter-panel-body.album-panel .album-group-list .filter-list-single .filter-row + .filter-row,
.filter-panel-body.album-panel .album-group-list .filter-list-single .filter-row + .filter-row:has(> [type="checkbox"]){
    border-top-width: 1px;
}

/* « Prévenez-moi » : les albums n'y ont pas de nombre de photos, la ligne n'a que son nom.
   Même rythme de 8 / filet / 8, sans la hauteur réservée au nombre. */
.subscribe-scope-list .filter-row,
.subscribe-scope-list .filter-list-single .filter-row + .filter-row:has(> [type="checkbox"]){
    min-height: 0;
}

.subscribe-scope-list .album-group-list .filter-list{
    padding: var(--sp-space-3) 0;
}

/* Tableau de bord — carte de profil FIDÈLE À LA MAQUETTE (DASHBOARD > Event_card) : 235px et
   16px de marge ; l'identité rentrée de 10px (avatar 82, 8px, nom 29, ville 17 collée) ; les
   chiffres au pied, dans une bande de 46px (6px 9px) où ils se répartissent d'un bord à l'autre,
   les sports en glyphes de 15px espacés de 6. */
.dashboard-view .card-photo-scrim{
    padding: var(--sp-space-4);
}

.dashboard-view .card-photo-scrim > .min-w-0{
    padding: 0 10px;
}

.dashboard-view .card-photo .avatar{
    width: 82px;
    height: 82px;
}

.dashboard-view .card-photo-stats{
    display: flex;
    justify-content: space-between;
    align-items: center;
    min-height: 46px;
    padding: 6px 9px;
}

.dashboard-view .card-photo-stats > .col{
    flex: 0 0 auto;
}

.dashboard-view .card-photo .stat-block-glyphs{
    gap: 6px;
}

.dashboard-view .card-photo .stat-block-glyphs svg{
    width: 15px;
    height: 15px;
}

/* Tableau de bord — « Ma cagnotte » FIDÈLE À LA MAQUETTE (CAGNOTTE) : 21px au-dessus du titre,
   24 ailleurs ; 14px du titre à la jauge ; jauge de 9px au coin de 4, piste pêche #FFC29E et
   remplissage #FF6000 ; légende gris clair ; bouton de 40px au coin de 12, en 16 semibold,
   gris plein tant que le virement n'est pas possible. La légende garde sa graisse (retour
   client : medium, seul le montant en semibold). */
.dashboard-view .card-dark{
    padding-top: 21px;
}

.dashboard-view .card-dark .section-header-figure{
    margin-bottom: 14px !important;
}

.progress-gauge{
    height: 9px;
    border-radius: 4px;
    background-color: #FFC29E;
}

.progress-gauge-fill{
    border-radius: 4px;
    background-color: #FF6000;
}

.dashboard-view .card-dark .progress-gauge-legend{
    color: var(--sp-color-border-on-white);
    letter-spacing: -0.01em;
}

.dashboard-view .card-dark .btn{
    min-height: 40px;
    border-radius: 12px;
    font-size: 16px;
    font-weight: var(--sp-font-weight-title);
    line-height: 19px;
    letter-spacing: -0.02em;
}

.dashboard-view .card-dark .btn.disabled{
    opacity: 1;
    border-color: #D1D1D1;
    background-color: #D1D1D1;
    color: #757575;
}

/* Tableau de bord — « Photos payantes » : piste #DCDAD1 (BROWN_BORDER_MEDIUM), coins de 4
   (maquette). Au dépôt, la piste reste grise #757575, comme SA maquette. */
.quota-progress,
.quota-progress .progress-bar{
    border-radius: 4px;
}

.dashboard-view .quota-progress{
    background-color: #DCDAD1;
}

/* Tableau de bord — « Mes photos » et « Blog » FIDÈLES À LA MAQUETTE (MES PHOTOS) : 16px 24px de
   marge, coin de 20, 17px entre le titre, le contenu et le bouton ; les quatre chiffres sur deux
   colonnes de 113,5px à 16px l'une de l'autre, deux rangs à 56px. */
.dashboard-view .dashboard-tile{
    padding: var(--sp-space-4) var(--sp-space-6);
    border-radius: 20px;
}

.dashboard-view .dashboard-tile > h3,
.dashboard-view .dashboard-tile > .card-sunken-text{
    margin-bottom: 17px;
}

.dashboard-view .dashboard-tile-stats{
    display: grid;
    grid-template-columns: repeat(2, 113.5px);
    gap: 16px;
    margin-bottom: 17px;
}

/* « Mes photos » / « Blog » : le titre à 17px du contenu. Le sélecteur passe l'id, qui fixe la
   marge de tous les h3 de l'écran. */
#photographer-dashboard .dashboard-tile > h3,
#club-dashboard .dashboard-tile > h3{
    margin-bottom: 17px;
}

/* « 30 derniers jours » (CAGNOTTE_LARGE) : 21px au-dessus du titre, 12 du titre aux graphiques. */
.dashboard-view .card-section:has(> .dashboard-last30-header){
    padding-top: 21px;
}

.dashboard-view .dashboard-last30-header{
    margin-bottom: 12px !important;
}

/* Tableau de bord — « Mon agenda » FIDÈLE À LA MAQUETTE (AGENDA) : 16px au-dessus du titre, 24
   ailleurs ; 8px sous le titre puis 20 avant la première journée ; rail de 7px à 14px du
   contenu ; en-tête de journée de 29px (étiquette de 26, 5px 6px) ; l'évènement à 8px dessous,
   vignette de 72 au coin de 16 ; 29px entre deux journées ; pastilles des jours à venir en
   #D3CDC3. La couleur de l'étiquette reste celle du retour client (brun text.caption). */
.dashboard-view .dashboard-agenda{
    padding-top: var(--sp-space-4);
}

#photographer-dashboard .dashboard-agenda > h3,
#club-dashboard .dashboard-agenda > h3{
    margin-bottom: var(--sp-space-2);
}

.dashboard-view .timeline--agenda{
    --timeline-agenda-header: 29px;
    margin-top: 20px;
}

.dashboard-view .timeline--agenda .timeline-item{
    grid-template-columns: 7px 1fr;
    gap: 14px;
    padding-bottom: 29px;
}

.dashboard-view .timeline--agenda .timeline-item:last-child{
    padding-bottom: 0;
}

.dashboard-view .timeline--agenda .timeline-item:not(:last-child) .timeline-marker::before{
    height: calc(100% + 29px);
}

.dashboard-view .timeline--agenda .timeline-dot{
    background-color: #D3CDC3;
}

.dashboard-view .timeline--agenda .timeline-item--current .timeline-dot{
    background-color: var(--sp-color-accent-selected);
}

.dashboard-view .timeline--agenda .timeline-header{
    margin-bottom: var(--sp-space-2) !important;
}

.dashboard-view .timeline--agenda .timeline-label{
    display: inline-flex;
    align-items: center;
    height: 26px;
    padding: 5px 6px;
}

.dashboard-view .timeline--agenda .list-item{
    padding: 0;
}

.dashboard-view .timeline--agenda .list-item-thumb{
    border-radius: var(--sp-radius-lg);
}

/* Barre haute de l'espace pro FIDÈLE À LA MAQUETTE (TOP BAR) : 50px, 24px de marge latérale,
   filet #DCDAD1 ; le logotype en 90×17 ; à droite le prénom (16 bold), l'avatar de 30 et le
   chevron, à 8px les uns des autres. L'écart sous la barre reste celui du retour client (24). */
.photographer-layout #top-bar,
.club-layout #top-bar{
    min-height: 50px;
    padding: 0 var(--sp-space-6);
}

@media (min-width: 992px){
    .photographer-layout #top-bar,
    .club-layout #top-bar{
        border-bottom-color: #DCDAD1;
    }
}

.top-bar-account{
    display: inline-flex;
    align-items: center;
    gap: var(--sp-space-2);
    border: 0;
    color: var(--sp-color-text-default);
}

.top-bar-account-name{
    font-size: 16px;
    font-weight: var(--sp-font-weight-bold);
    line-height: 19px;
    letter-spacing: -0.04em;
}

.top-bar-account-chevron{
    transform: rotate(180deg);
}

/* « Mes évènements » FIDÈLE À LA MAQUETTE (DASHBOARD 3093:29454) : contenu de 1067px, titre en
   32/39, « Créer un évènement » de 41px en 16 semibold (glyphe de 15), tuiles de 339,67 × 235 au
   coin de 16 sur trois colonnes à 24px. */
.photographer-events{
    max-width: calc(1067px + 2 * var(--bs-gutter-x, 1.5rem) / 2 * 2);
}

@media (min-width: 1200px){
    .photographer-events{
        max-width: 1103px;
    }
}

.photographer-events .page-title{
    font-size: 32px;
    line-height: 39px;
    letter-spacing: -0.03em;
}

.photographer-events .sec-header > .btn-primary{
    min-height: 41px;
    padding: 0 var(--sp-space-6);
    border-radius: 12px;
    font-size: 16px;
    font-weight: var(--sp-font-weight-title);
    line-height: 19px;
}

/* La tuile de gestion (EVENT_CARD) : 235px, 16px de marge ; la visibilité au centre du haut ;
   sport, titre et méta à 6px ; la barre d'actions de 30px à 10px de la méta. Le voile est celui
   de la maquette : un quart de noir, plus un dégradé qui fonce le haut et le pied. */
.event-highlighted-manage{
    height: 235px;
    min-height: 0;
    aspect-ratio: auto;
    border-radius: var(--sp-radius-lg);
}

/* « Mes albums » d'un évènement suivi : la carte en tête a la hauteur de celles de « Mes
   évènements » (retour client d'octobre). */
.event-albums-cover .event-highlighted{
    height: 235px;
    min-height: 0;
    aspect-ratio: auto;
}

.event-highlighted-manage::after{
    background:
        linear-gradient(0deg, rgba(0, 0, 0, .25), rgba(0, 0, 0, .25)),
        linear-gradient(180deg, rgba(0, 0, 0, .6111) 0%, rgba(0, 0, 0, 0) 26.44%, rgba(0, 0, 0, 0) 49.52%, rgba(0, 0, 0, .97) 100%);
}

.event-highlighted-manage .event-highlighted-top{
    padding: var(--sp-space-4);
    justify-content: center;
}

.event-highlighted-manage .event-highlighted-top .badge-glass{
    margin-right: auto;
}

.event-highlighted-manage .event-highlighted-scrim{
    gap: 6px;
    padding-bottom: calc(var(--sp-space-4) + 30px + 10px);
}

.event-highlighted-action--bar .btn{
    min-height: 28px;
    padding: 3px 10px;
    gap: 5px;
    border-radius: 8px;
    font-size: var(--sp-font-size-meta);
    font-weight: var(--sp-font-weight-title);
    line-height: 16px;
    letter-spacing: -0.01em;
}

.event-highlighted-action--bar .btn-marketing{
    min-height: 30px;
    padding: 0 12px;
    gap: 4px;
    font-weight: var(--sp-font-weight-body);
}

/* Le « + » de dépôt : le padding de 12px écrasait le glyphe à 6px de large. 35 × 30 comme la
   maquette ; le trait du glyphe (13/16 de sa boîte) fait la taille de police des voisins. */
.event-highlighted-action--bar .btn-icon-only{
    width: 35px;
    padding: 0;
}

.event-highlighted-action--bar .btn-icon-only svg{
    flex-shrink: 0;
    width: 16px;
    height: 16px;
}

.event-highlighted-action--bar .btn-glass{
    border: 1px solid #FFFFFF;
    /* Maquette : « 923 photos publiées » à 30px, « Modifier » reste à 28. */
    min-height: 30px;
}

/* Bouton FILAIRE simple sur les tuiles de gestion (retour client d'octobre) : le liseré du
   verre doublait le filet blanc — deux contours l'un dans l'autre. Plus de lentille, de liseré
   ni d'ombre : un filet blanc, le texte blanc, le voile clair au survol. */
.event-highlighted-action--bar .btn-glass{
    box-shadow: none;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
}

.event-highlighted-action--bar .btn-glass::before,
.event-highlighted-action--bar .btn-glass::after{
    content: none;
}

/* « Prolonger » partage la barre comme les autres libellés : son formulaire prend la place */
.event-highlighted-action-form{
    display: flex;
    flex: 1 1 auto;
    min-width: 0;
}

/* « Voir tout » : les évènements expirés, rangés à part sous leur titre (retour client) */
.events-expired-title{
    margin: var(--sp-space-8) 0 var(--sp-space-4);
    font-size: 16px;
    font-weight: var(--sp-font-weight-title);
    line-height: 19px;
    letter-spacing: -0.02em;
}

/* Le défilement descend un peu sous les dernières tuiles (retour client : il s'arrêtait au ras
   des cartes « Intéressés ») */
.photographer-events{
    padding-bottom: var(--sp-space-12);
}

/* « Mes évènements » : 32px entre le titre et la barre (20 + 12) ; barre de 37px ; onglets de la
   maquette (TEMPORAL_SELECTOR) — l'actif en pilule 6px 12px, l'autre sans pilule, 30px entre
   eux, glyphe à 8px du mot ; filet à 12px sous la barre, 30px avant la section ; en-tête de
   section de 25px, 15px au-dessus de la grille, le compte en 16 semibold (le nombre en bold). */
.photographer-events > .sec-header{
    margin-bottom: 32px !important;
}

.photographer-events .photo-filter-bar{
    min-height: 37px;
    margin-bottom: 12px !important;
}

.photographer-events .tab-bar-nav{
    gap: 30px !important;
}

.photographer-events .tab-bar-nav .nav-link{
    gap: var(--sp-space-2);
    padding: 6px 0;
}

.photographer-events .tab-bar-nav .nav-link.active{
    padding: 6px 12px;
}

.photographer-events .filter-bar-rule{
    margin-bottom: 30px;
}

.photographer-events section > .sec-header{
    min-height: 25px;
    margin-bottom: 15px;
}

.photographer-events section > .sec-header .sec-header-title{
    font-size: 16px;
    font-weight: var(--sp-font-weight-title);
    line-height: 19px;
    letter-spacing: -0.04em;
}

.photographer-events .photo-filter-bar .filter-chips{
    padding-top: 0;
    padding-bottom: 0;
}

/* Chip de tri (maquette SORT) : « Trier par » en 14 medium gris, la valeur en 13 semibold ink et
   son chevron à 4px, 8px entre le nom et la valeur. */
.chip-filter:has(.chip-filter-prefix){
    gap: var(--sp-space-2);
}

.chip-filter-prefix{
    color: var(--sp-color-text-muted);
}

.chip-filter-value{
    display: inline-flex;
    align-items: center;
    font-size: var(--sp-font-size-meta);
    font-weight: var(--sp-font-weight-title);
    line-height: 16px;
    letter-spacing: -0.01em;
    color: var(--sp-color-text-default);
}

/* Gérer mes photos : la valeur du tri au même corps et à la même graisse que les autres chips, en ink (retour client) */
.photographer-events .chip-filter-value{
    font-size: inherit;
    font-weight: inherit;
    line-height: inherit;
    letter-spacing: inherit;
    color: var(--sp-color-text-default);
}

.chip-filter-value-chevron{
    margin-left: 4px;
    transform: rotate(180deg);
}

.photographer-events .sec-header > .btn-primary{
    display: inline-flex;
    align-items: center;
}

/* Les libellés de la barre d'actions tiennent sur une ligne : le bouton s'élargit à son texte
   (maquette : « Modifier », « 523 photos publiées », « + » côte à côte). */
.event-highlighted-action--bar .btn{
    white-space: nowrap;
}

/* Onglets de filtre FIDÈLES À LA MAQUETTE (Mes transactions, FILTER) : pilules de 34px au coin
   de 12, 0 12px, 15/18 ; au repos en #F4F4F2 et gris #757575, l'actif en ink ; 13px entre elles.
   Second axe (période) : filet #D1D1D1 au repos, filet noir et 15 semibold ink pour l'option
   retenue, 12px entre elles ; 16px de part et d'autre du filet qui sépare les deux axes. */
.tabs-filter{
    gap: 13px;
}

.tabs-filter--second{
    gap: var(--sp-space-3);
}

.tabs-filter-item{
    min-height: 34px;
    padding: 0 var(--sp-space-3);
    border-radius: 12px;
    font-size: 15px;
    font-weight: var(--sp-font-weight-body);
    line-height: 18px;
    letter-spacing: -0.02em;
    color: #757575;
}

.tabs-filter-item--active{
    color: var(--sp-color-action-primary-text);
}

.tabs-filter--second .tabs-filter-item{
    border-color: #D1D1D1;
    color: #757575;
}

.tabs-filter--second .tabs-filter-item--active{
    border-width: 1px;
    border-color: #000000;
    font-weight: var(--sp-font-weight-title);
    color: var(--sp-color-text-default);
}

.tabs-filter-separator{
    margin: var(--sp-space-4) 0;
}

/* Mes transactions (DASHBOARD 3031:5358) : 1067px ; cartes au coin de 24, 21px au-dessus du
   titre et 24 ailleurs ; titre 24/29 à 24px des onglets ; le compte en 16 semibold et le total
   en 24/29, rentrés de 16px. `.ledger-screen` porte les mêmes cotes aux écrans comptables de
   même composition que la maquette ne dessine pas (ventes du club). */
@media (min-width: 1200px){
    .photographer-transactions,
    .ledger-screen{
        max-width: 1103px;
    }
}

.photographer-transactions > .card,
.ledger-screen > .card{
    padding: 21px var(--sp-space-6) var(--sp-space-6);
    border-radius: 24px;
}

#photographer-transactions h1,
.ledger-screen > .card > h1{
    font-size: 24px;
    line-height: 29px;
    letter-spacing: -0.03em;
    margin-bottom: var(--sp-space-6) !important;
}

.photographer-transactions > .section-header-figure,
.ledger-screen > .section-header-figure{
    padding: 0 var(--sp-space-4);
}

.photographer-transactions > .section-header-figure > p:first-child,
.ledger-screen > .section-header-figure > p:first-child{
    font-size: 16px;
    font-weight: var(--sp-font-weight-title);
    line-height: 19px;
    letter-spacing: -0.02em;
}

/* Le nombre garde le semibold de sa ligne (maquette) : en `<strong>`, la police variable le
   poussait au plus gras (retour client : « réduire le graissage du nombre »). Espace
   photographe seulement : les écrans du club (`.ledger-screen`) gardent leur rendu. */
.photographer-transactions > .section-header-figure > p:first-child strong{
    font-weight: inherit;
}

.photographer-transactions .section-figure,
.ledger-screen .section-figure{
    font-size: 24px;
    font-weight: var(--sp-font-weight-title);
    line-height: 29px;
    letter-spacing: -0.03em;
}

.photographer-transactions > .section-header-figure,
.ledger-screen > .section-header-figure{
    margin-bottom: var(--sp-space-6) !important;
}

/* Spicto Pro FIDÈLE À LA MAQUETTE (3138:12769, Frame 73) : 1205px, l'argumentaire sur 659, 41px,
   la décision sur 505 ; héros au coin de 32 et 42px de marge, 24px entre verrou, promesse,
   sous-titre et avantages ; avantages en 24px 32px 32px au coin de 24 ; 24px entre les cartes. */
@media (min-width: 1240px){
    #pro-offer{
        max-width: none;
        width: 1205px;
        padding: 0;
    }

    #pro-offer > .row{
        flex-wrap: nowrap;
        gap: 41px;
        margin: 0;
    }

    #pro-offer > .row > *{
        padding: 0;
        margin-top: 0;
    }

    #pro-offer > .row > .col-lg-7{
        flex: 0 0 659px;
        width: 659px;
    }

    #pro-offer > .row > .col-lg-5{
        flex: 0 0 505px;
        width: 505px;
    }
}

.pro-hero{
    padding: 42px;
    border-radius: 32px;
}

.pro-hero-lockup{
    margin-bottom: var(--sp-space-6);
}

#pro-offer .pro-hero-title{
    margin-bottom: var(--sp-space-6);
}

.pro-hero-text{
    margin-bottom: var(--sp-space-6);
}

.pro-benefits{
    --bs-card-spacer-x: 32px;
    --bs-card-spacer-y: 24px;
    padding: 24px 32px 32px;
    border-radius: 24px;
}

.pro-feature{
    margin-top: var(--sp-space-6);
}

/* Spicto Pro, colonne de droite FIDÈLE À LA MAQUETTE : titres 20/20, 15px au-dessus du cycle et
   14 au-dessus du paiement, 23px entre les blocs ; cycle au coin de 24 (16px 24px), sans filet,
   le prix 16px sous les options ; paiement en cadre blanc de 44px au coin de 20, sans liseré ;
   conditions au coin de 20 (24px 24px 28px), titre 15/18 gris foncé, texte 13/20 gris ; bouton
   de 56px au coin de 16, 16/19 semibold. */
.pro-aside-title{
    line-height: 20px;
    letter-spacing: -0.03em;
    margin-bottom: 15px;
}

.pro-aside-title + .pro-aside-title,
.pro-cycle + .pro-aside-title,
.pro-payment-note + .pro-aside-title{
    margin-top: 23px;
}

.pro-cycle{
    padding: var(--sp-space-4) var(--sp-space-6);
    border-radius: 24px;
}

.pro-cycle-choice{
    padding-bottom: 0;
    margin-bottom: var(--sp-space-4);
    border-bottom: 0;
}

.pro-payment{
    min-height: 44px;
    border: 0;
    border-radius: 20px;
}

.pro-terms{
    margin-top: 23px;
    padding: 24px 24px 28px;
    border-radius: 20px;
}

.pro-terms-title{
    font-size: 15px;
    line-height: 18px;
    letter-spacing: -0.02em;
    color: #464646;
    margin-bottom: var(--sp-space-4);
}

.pro-terms p{
    line-height: 20px;
    letter-spacing: -0.03em;
    color: #757575;
}

.pro-cta{
    min-height: 56px;
    border-radius: 16px;
    font-size: 16px;
    line-height: 19px;
    letter-spacing: -0.02em;
}

.pro-cycle-choice{
    min-height: 25px;
    align-items: center;
}

.pro-cycle-price{
    padding-top: 12px;
}

.pro-aside-title:has(+ .pro-payment){
    margin-bottom: 14px;
}

.pro-payment{
    padding-top: var(--sp-space-1);
    padding-bottom: var(--sp-space-1);
}

.pro-cta{
    margin-top: 23px;
}

/* Paramètres du compte FIDÈLES À LA MAQUETTE (3161:19729) : 1200px — la navigation sur 380, 42px,
   la section sur 778 ; le titre de gauche rentré de 16px ; la carte de navigation au coin de 36,
   24px de marge, 14px entre des entrées de 60px (12px de marge, 15/18) ; 26px sous le titre de
   la section. */
@media (min-width: 1240px){
    .settings-shell{
        max-width: none;
        width: 1200px;
        padding: 0;
    }

    .settings-shell > .row{
        flex-wrap: nowrap;
        gap: 42px;
        margin: 0;
    }

    .settings-shell > .row > *{
        padding: 0;
        margin-top: 0;
    }

    .settings-shell > .row > .col-lg-4{
        flex: 0 0 380px;
        width: 380px;
    }

    .settings-shell > .row > .col-lg-8{
        flex: 0 0 778px;
        width: 778px;
    }
}

.settings-shell .col-lg-4 > .page-title{
    padding: 0 var(--sp-space-4);
    margin-bottom: var(--sp-space-4) !important;
}

.settings-shell .col-lg-8 > .page-title{
    margin-bottom: 26px !important;
}

.settings-shell .col-lg-4 > .card{
    padding: var(--sp-space-6);
    border-radius: 36px;
}

.settings-nav{
    gap: 14px;
}

.settings-nav-item{
    min-height: 60px;
    padding: var(--sp-space-3);
    gap: 14px;
    font-size: 15px;
    line-height: 18px;
    letter-spacing: -0.02em;
}

/* Paramètres — la bannière de profil FIDÈLE À LA MAQUETTE (Event_card) : 232px au coin de 24,
   24px de marge ; l'identité rentrée de 7px 16px, portrait de 121 à 25px du nom (48/58), la
   ville en 15/18, les sports à 13px dessous, espacés de 12 ; au pied des boutons de 34px (7px
   10px), 13/16 semibold. */
@media (min-width: 992px){
    .settings-shell .card-photo--banner{
        min-height: 232px;
        border-radius: 24px;
    }

    .settings-shell .card-photo--banner .card-photo-scrim{
        padding: var(--sp-space-6);
    }

    .settings-shell .card-photo--banner .card-photo-identity{
        gap: 25px;
        padding: 7px var(--sp-space-4) 0;
    }

    .settings-shell .card-photo--banner .avatar{
        width: 121px;
        height: 121px;
    }

    .settings-shell .card-photo--banner .card-photo-identity-text h1.card-photo-name{
        line-height: 58px;
        margin-bottom: 0 !important;
    }

    .settings-shell .card-photo--banner .card-photo-meta{
        font-size: 15px;
        line-height: 18px;
    }

    .settings-shell .card-photo--banner .card-photo-stats{
        margin-top: 13px;
        gap: 12px;
    }

    .settings-shell .card-photo--banner .card-photo-footer .btn{
        min-height: 34px;
        padding: 7px 10px;
        border-radius: 8px;
        font-size: var(--sp-font-size-meta);
        font-weight: var(--sp-font-weight-title);
        line-height: 16px;
    }
}

@media (min-width: 992px){
    .settings-shell .card-photo--banner .card-photo-identity{
        align-items: flex-start;
    }
}

/* Le titre de bloc perdait ses 4px face à `.photographer-layout h3` (0,1,1), qui remet 16 à tout
   h3 de l'espace : 16px entre titre et sous-titre au lieu de 4. La portée par le bloc le
   dépasse. Les sports favoris sont à 25px de leur sous-titre (maquette SPORT, gap 25). */
.settings-block .settings-block-title{
    margin: 0 0 4px;
}

.settings-block:has(.choice-pill) .settings-block-sub{
    margin-bottom: 25px;
}

.settings-block:has(.choice-pill) .settings-block-sub + *{
    gap: var(--sp-space-3);
}

/* Dépôt, choix de l'évènement FIDÈLE À LA MAQUETTE (EVENT_SELECT 2525:5137) : 954px, 23px entre
   titre, cartes et « ou » ; cartes au coin de 24 (21px 24px 24px) ; titre de carte 20/24 à 6px de
   son sous-titre 15/18, le contenu 22px dessous ; tuiles enregistrées de 299 × 200 au coin de 16. */
@media (min-width: 1200px){
    .deposit-select{
        max-width: 954px;
    }
}

.deposit-select > .page-title{
    margin-bottom: 23px;
}

.deposit-select > .card{
    margin-bottom: 23px !important;
    padding: 21px var(--sp-space-6) var(--sp-space-6);
    border-radius: 24px;
}

.deposit-select > .card :is(h2.h3){
    margin-bottom: 6px !important;
}

.deposit-select > .card :is(h2.h3) + p{
    line-height: 18px;
    letter-spacing: -0.02em;
}

.deposit-select > .card > .sec-header,
.deposit-select .deposit-search-sub{
    margin-bottom: 22px !important;
}

.deposit-select .event-rail > .event-highlighted,
.deposit-select .event-rail > .event-highlighted-wrap{
    flex: 0 0 299px;
}

.deposit-select .event-rail .event-highlighted{
    height: 200px;
    min-height: 0;
    aspect-ratio: auto;
    border-radius: var(--sp-radius-lg);
}

.deposit-select > .path-separator{
    margin-bottom: 23px !important;
}

.deposit-select .event-rail{
    gap: var(--sp-space-6);
}

.deposit-select > .path-separator{
    line-height: 18px;
}

/* « Astuces du jour » FIDÈLE À LA MAQUETTE (TIPS, DEPOT_NEW) : 16px 24px 14px ; titre sur 24px,
   compteur « 1/3 » en 12/15 medium ink ; 5px puis la vignette de 70 au coin de 16 (6px dessus,
   12 dessous) ; 5px puis le titre 16/19, 5px le texte 15/18 ; pastilles de 6 à 5px, 12px sous le
   texte. */
.tips-card{
    padding: var(--sp-space-4) var(--sp-space-6) 14px;
}

.tips-card > .sec-header{
    min-height: 24px;
    margin-bottom: 5px;
}

.tips-nav-count{
    font-size: 12px;
    font-weight: var(--sp-font-weight-body);
    line-height: 15px;
    letter-spacing: -0.02em;
    color: var(--sp-color-text-default);
}

/* La hauteur suit le ratio de l'image téléversée (retour client du 27/10) ; sans image, la bande garde 70px. */
.tip-media{
    height: auto;
    margin: 6px 0 17px;
    border-radius: var(--sp-radius-lg);
}
.tip-media:not(:has(img)){ height: 70px; }
.tip-media img{ height: auto; object-fit: initial; }

.tip-title{
    font-size: 16px;
    line-height: 19px;
    letter-spacing: -0.02em;
    margin-bottom: 5px;
}

.tip-text{
    line-height: 18px;
    letter-spacing: -0.02em;
}

.tips-dots{
    gap: 5px;
    margin-top: var(--sp-space-3);
}

.tips-dot{
    width: 6px;
    height: 6px;
}

.tips-card .tips-nav-btn{
    width: 24px;
    height: 24px;
    min-width: 0;
    min-height: 0;
}

/* Parcours de dépôt FIDÈLE À LA MAQUETTE (DEPOT_NEW 2551:11006) : le titre de page rentré de
   16px ; colonne gauche à 19px d'écart — carte d'évènement de 219, quota, puis « Téléchargement »
   24px plus bas, son cadre 19px sous le titre. */
.tunnel-shell > .page-title--drop,
.tunnel-shell .page-title--drop{
    padding-left: var(--sp-space-4);
}

@media (min-width: 992px){
    .tunnel-grid > .col-lg-5 > .event-highlighted-header{
        min-height: 219px;
    }

    .tunnel-grid > .col-lg-5 > *:not(:last-child){
        margin-bottom: 19px !important;
    }

    .tunnel-grid > .col-lg-5 > .quota-card + *{
        padding-top: var(--sp-space-6);
    }

    .tunnel-grid > .col-lg-5 > .quota-card + * > .sec-header{
        margin-bottom: 19px;
    }
}

/* Étape Album : la phrase sous « Album » reste en 15/18 (maquette) — `.upload-flow
   .card-nested-fields > .sec-note`, déclarée plus bas à spécificité égale, la ramenait à 13. */
.upload-flow.album-step .card-nested > .sec-note{
    margin-bottom: 26px !important;
    font-size: 15px;
    font-weight: 500;
    line-height: 18px;
    letter-spacing: -0.02em;
    color: #10110F;
}

/* La frise d'étapes (maquette DROP) : noms en 13/16 semibold répartis sur toute la largeur qui
   suit le compteur. La couleur des étapes à venir reste celle du retour client (brun). */
.stepper-list{
    flex: 1 1 auto;
    justify-content: space-between;
    font-size: var(--sp-font-size-meta);
    font-weight: var(--sp-font-weight-title);
    line-height: 16px;
    letter-spacing: -0.01em;
}

.stepper-list{
    flex-wrap: nowrap;
    gap: var(--sp-space-1);
}

@media (max-width: 575.98px){
    .stepper-list{
        flex-wrap: wrap;
    }
}

/* Pastilles de prix du dépôt (maquette DEPOT_MONETISATION, Tags) : 40px, 8px 16px, coin de 16,
   12px d'écart ; la graisse et le filet au repos restent ceux du retour client. */
.upload-flow .btn-toggle{
    min-height: 40px;
    padding: var(--sp-space-2) var(--sp-space-4);
    border-radius: var(--sp-radius-lg);
    line-height: 18px;
}

.upload-flow .d-flex:has(> .btn-toggle){
    gap: var(--sp-space-3) !important;
}

/* Le bouton qui fait avancer le parcours : 120px de large (maquette DROP › BUTTON). */
.upload-flow .btn-primary[type="submit"]{
    min-width: 120px;
}

.upload-flow .btn-toggle{
    height: 40px;
    min-height: 0;
    display: inline-flex;
    align-items: center;
}

/* Parcours de dépôt — étape repliée FIDÈLE À LA MAQUETTE (ALBUM_CLOSED) : coin de 24 ; nom 16/19,
   ce qui a été choisi en 14/18 ; « Modifier » de 32px (8px 16px) en 13 semibold — blanc au filet
   gris, comme le veut le retour client. Retour d'octobre : le fond s'éclaircit en BG_CREAM_FADE
   (#FAF9F5, il était #EFE9DD) et la marge devient la même sur les quatre côtés — la gauche, à
   16px, était plus serrée que le haut et le bas. */
.tunnel-grid .upload-flow .step-recap{
    padding: 20px;
    border-radius: 24px;
    background-color: var(--sp-color-cream-100);
}

.tunnel-grid .upload-flow .step-recap-title{
    line-height: 19px;
    letter-spacing: -0.02em;
}

.tunnel-grid .upload-flow .step-recap-meta{
    font-size: 14px;
    line-height: 18px;
    letter-spacing: -0.03em;
}

.tunnel-grid .upload-flow .step-recap .btn{
    min-height: 32px;
    padding: var(--sp-space-2) var(--sp-space-4);
    font-size: var(--sp-font-size-meta);
    font-weight: var(--sp-font-weight-title);
    line-height: 16px;
}

/* Dépôt, étape Photos FIDÈLE À LA MAQUETTE (PHOTO_OPEN) : carte au coin de 24 ; zone de 251px
   (16px 20px 20px) — vignette de 85 × 64, 16px, « Charge tes photos au format » 20/24 et sa
   pastille JPEG de 30 (1px 8px 0, coin de 5, 12/16 bold), la limite 13/16 collée dessous, 22px,
   l'invite 13/16 bold grise ; puis 20px, un filet, et au pas de 10 : les règles 16/19, la liste
   13/16 (rangs de 16 à 8px), un filet, la mention 13/16 grise. */
.upload-flow .card-nested-framed:has(> .custom-dropzone-wrapper){
    border-radius: 24px;
}

.upload-flow .custom-dropzone-wrapper{
    min-height: 251px;
    padding: var(--sp-space-4) 20px 20px;
}

.upload-flow .dropzone-content > p:first-child{
    margin-bottom: var(--sp-space-4) !important;
}

.upload-flow .dropzone-content > p:first-child img{
    width: 85px;
    height: 64px;
    object-fit: contain;
}

.upload-flow .dropzone-content > .h4{
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 9px;
    min-height: 30px;
    margin-bottom: 0 !important;
    font-size: 20px;
    line-height: 24px;
    letter-spacing: -0.03em;
}

.upload-flow .dropzone-content > .h4 .badge{
    height: 30px;
    padding: 1px 8px 0;
    border-radius: 5px;
    font-size: 12px;
    font-weight: var(--sp-font-weight-bold);
    line-height: 16px;
    display: inline-flex;
    align-items: center;
}

.upload-flow .dropzone-limit{
    margin-bottom: 22px !important;
    line-height: 16px;
    letter-spacing: -0.01em;
}

.upload-flow .dropzone-prompt{
    font-weight: var(--sp-font-weight-bold);
    line-height: 16px;
    letter-spacing: -0.01em;
    color: #757575 !important;
}

.upload-flow .custom-dropzone-wrapper + .sec-header{
    margin-top: 20px !important;
    padding-top: 10px;
    margin-bottom: 10px;
    border-top: 1px solid var(--sp-color-border-default);
}

.upload-flow .custom-dropzone-wrapper + .sec-header .sec-header-title{
    line-height: 19px;
    letter-spacing: -0.02em;
}

.upload-flow .dropzone-rules{
    column-gap: 6px;
    row-gap: var(--sp-space-2);
    line-height: 16px;
    letter-spacing: -0.01em;
    color: #464646;
}

.upload-flow .dropzone-rules + .card-rule{
    margin: 10px 0;
}

.upload-flow .dropzone-legal{
    line-height: 16px;
    letter-spacing: -0.01em;
    color: #757575 !important;
}

/* Création d'évènement, « Format de l'évènement » (maquette CREATE EVENT OK) : le nom de l'option
   en 15/18 semibold, sa phrase 8px dessous, 19px de part et d'autre du filet. */
.create-grid .option-row-name{
    font-weight: var(--sp-font-weight-title);
}

.create-grid .option-row-label{
    gap: var(--sp-space-2);
}

.create-grid .option-row{
    padding: 19px 0;
}

.create-grid .option-row:first-of-type{ padding-top: 0; }
.create-grid .option-row:last-of-type{ padding-bottom: 0; }

/* Chiffres de la carte de profil : répartis d'un bord à l'autre, mais jamais collés — quand la
   colonne se resserre (carte de 292px entre 992 et 1400), ils gardent 12px entre eux et leur
   légende passe à la ligne plutôt que de toucher la voisine. */
.dashboard-view .card-photo-stats{
    gap: var(--sp-space-3);
}

.dashboard-view .card-photo-stats > .col{
    flex: 0 1 auto;
    min-width: 0;
}

/* Une légende ne se coupe qu'entre deux mots (« Photos / publiées »), jamais au milieu d'un
   (« Évènemen / ts ») : chaque chiffre garde au moins la largeur de son plus long mot. */
.dashboard-view .card-photo-stats > .col{
    min-width: min-content;
}

.dashboard-view .card-photo-stats .stat-block-label{
    overflow-wrap: normal;
    word-break: normal;
}

/* Création d'évènement — étape repliée FIDÈLE À SA MAQUETTE (MONETISATION_CLOSED du tunnel de
   création) : crème très clair #FAF9F5, 16px 16px 12px 22px, coin de 24. Celle du dépôt est plus
   soutenue (#EFE9DD) : les deux maquettes diffèrent, chacune garde la sienne. */
.create-grid .step-recap{
    padding: var(--sp-space-4) var(--sp-space-4) var(--sp-space-3) 22px;
    border-radius: 24px;
    background-color: #FAF9F5;
}

/* Récapitulatif d'étape de la création (maquette MONETISATION_CLOSED) : la tête (titre +
   « Modifier », 32px) puis un bloc — méta en 15 semibold sur une ligne de 22, filet entouré de
   8px, qualificatifs en 13 medium sur des lignes de 20 séparées de 5. La couverture de
   « Personnalisation » s'y pose en vignette 60×60 au coin de 8, à 24px du texte ; 16px sous
   le bloc. */
.create-grid .step-recap{
    padding-bottom: var(--sp-space-4);
}

.create-grid .step-recap-head{
    align-items: center;
    min-height: 32px;
}

.step-recap-body{
    display: flex;
    align-items: flex-start;
    gap: var(--sp-space-6);
}

.step-recap-thumb{
    flex-shrink: 0;
    width: 60px;
    height: 60px;
    border-radius: 8px;
    object-fit: cover;
}

.step-recap-body-lines{
    display: flex;
    flex: 1;
    flex-direction: column;
    gap: 5px;
    padding-bottom: var(--sp-space-1);
}

.create-grid .step-recap-meta{
    font-size: 15px;
    font-weight: var(--sp-font-weight-title);
    line-height: 22px;
    letter-spacing: -0.02em;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.create-grid .step-recap-rule{
    margin: 3px 0;
}

.create-grid .step-recap-detail{
    font-weight: 500;
    line-height: 20px;
    letter-spacing: -0.01em;
}

/* Création, étape Albums : la carte des journées (PRIVE_NOT_PRO) — 24px tout autour, coin de 24. */
.create-grid .card-nested:is(:has(.album-days), :has(.visibility-row)){
    padding: 23px;   /* 24 dans la maquette, filet intérieur compris */
    border-radius: 24px;
}

/* Ses cotes internes (PRIVE_NOT_PRO) diffèrent de l'étape Album du dépôt : titre et phrase à 4px
   (phrase 13/16 medium #464646), 24px entre la phrase et chaque journée ; une journée tient sur
   55px, repliée (#FAF9F5, ombre courte) comme dépliée (#F5F3EB, filet #A29689), sans sous-titre ;
   12px plus bas, sa liste dans un cadre au filet #D1D1D1, coin de 24, 16px autour. */
.create-grid .card-nested:is(:has(.album-days), :has(.visibility-row)) > .sec-header{
    margin-bottom: 4px !important;
}

.create-grid .card-nested:is(:has(.album-days), :has(.visibility-row)) > .sec-header .sec-header-title{
    font-size: 20px;
    font-weight: 600;
    line-height: 24px;
    letter-spacing: -0.03em;
}

.create-grid .card-nested:is(:has(.album-days), :has(.visibility-row)) > .sec-note{
    margin-bottom: 24px !important;
    font-size: 13px;
    font-weight: 500;
    line-height: 16px;
    letter-spacing: -0.01em;
    color: #464646;
}

.create-grid .album-days{
    gap: 24px;
}

.create-grid .album-day{
    gap: 12px;
}

.create-grid .album-day-card,
.create-grid .album-day:not(.is-open) .album-day-card{
    display: flex;
    align-items: center;
    height: 55px;
    padding: 0 20px 0 16px;
}

.create-grid .album-day-card .album-day-head{
    flex: 1;
    min-height: 0;
}

.create-grid .album-day.is-open .album-day-card{
    background-color: #F5F3EB;
}

.create-grid .album-day.is-open .album-day-card .album-day-hint{
    display: none;
}

.create-grid .album-day-panel{
    padding: 15px;
    border-color: #D1D1D1;
    border-radius: 24px;
}

/* La liste : 16px de part et d'autre de chaque filet, 17px entre le dernier et « Créer ». */
.create-grid .album-day-panel .option-row:not(:first-of-type){ padding-top: 16px; }
.create-grid .album-day-panel .option-row:not(:last-of-type){ padding-bottom: 16px; }

.create-grid .album-day-panel .album-rule{
    margin: 16px 0 17px;
}

/* La colonne de l'étape (DROP) espace tout de 24px : récapitulatifs, carte, « Suivant », filet
   et frise. */
.create-grid .step-recap{
    margin-bottom: var(--sp-space-6);
}

.create-grid .card-nested:is(:has(.album-days), :has(.visibility-row)){
    margin-bottom: var(--sp-space-6) !important;
}

.create-grid .card-nested:has(.album-days) ~ .d-flex,
.create-grid [data-controller="choice-reveal"] + .d-flex,
.create-grid [data-controller="visibility-fields"] + .d-flex{
    margin-top: 0 !important;
}

.create-grid .card-foot-rule{
    margin-bottom: var(--sp-space-6);
}

/* Étape Visibilité (maquette EVENT_TYPE) : chaque option est une carte — filet #D1D1D1, coin de
   16, 16px autour —, 24px entre elles ; une option réservée qu'on ne peut plus choisir passe
   sur un aplat #F5F5F5 sans filet. Le nom en 15/18 semibold, la mention « Réservé aux abonnés »
   poussée à droite ; 8px plus bas, une ligne par phrase en 13/16 medium #464646, 4px entre
   elles, la première en semibold. */
.create-grid .option-list .visibility-row{
    gap: 6px;
    padding: 15px;   /* 16 dans la maquette, filet intérieur compris */
    border: 1px solid #D1D1D1;
    border-radius: 16px;
}

.create-grid .option-list .visibility-row + .visibility-row{
    margin-top: var(--sp-space-6);
}

.create-grid .option-list .visibility-row--locked{
    border-color: transparent;
    background-color: #F5F5F5;
}

.create-grid .visibility-row--locked .option-row-label{
    opacity: 1;
}

.create-grid .visibility-row .option-row-label{
    flex: 1;
    gap: var(--sp-space-2);
}

.create-grid .visibility-row .option-row-name{
    display: flex;
    align-items: center;
    font-size: 15px;
    line-height: 18px;
    letter-spacing: -0.02em;
    color: #1E1C1A;
}

.create-grid .visibility-row .visibility-pro{
    margin-left: auto;
}

/* Visuel 29 du 27/10 : une mention rectangulaire à fin filet, plus discrète que la pastille. */
.visibility-row .visibility-pro{
    padding: 1px 6px;
    border-color: #464646;
    border-radius: 4px;
    font-size: 11px;
    font-weight: 600;
    color: #1E1C1A;
}

.visibility-row .visibility-pro .pro-lockup-logotype{
    height: 10px;
}

.visibility-row .visibility-pro .pro-lockup-seal svg{
    width: 11px;
    height: 11px;
}

.visibility-row .visibility-pro .pro-lockup-tier{
    font-size: 9px;
    line-height: 12px;
}

/* La ligne porte l'option et, pour la privée, l'interrupteur du mot de passe sous un filet. */
.visibility-row{
    flex-direction: column;
    align-items: stretch;
    cursor: default;
}

.visibility-row-main{
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--sp-space-4);
    cursor: pointer;
}

.visibility-row--locked .visibility-row-main{
    cursor: not-allowed;
}

.visibility-protect{
    margin-top: 10px;
    padding-top: 12px;
    border-top: 1px solid #E3E3E3;
}

.visibility-protect-switch{
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-space-4);
}

.visibility-protect-label{
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 13px;
    font-weight: 600;
    line-height: 16px;
    color: #1E1C1A;
    cursor: pointer;
}

.visibility-password{
    margin-top: 12px;
}

.visibility-lines{
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.create-grid .visibility-lines{
    font-size: 13px;
    font-weight: 500;
    line-height: 16px;
    letter-spacing: -0.01em;
    color: #464646;
}

.visibility-line--lead{
    font-weight: var(--sp-font-weight-title);
}

.create-grid .card-nested:has(.visibility-row) > .sec-note{
    margin-bottom: 25px !important;
}

/* Noms d'albums du récapitulatif : séparés d'un point aéré, un cadenas devant les protégés. */
.step-recap-detail-sep{
    margin: 0 6px;
}

.step-recap-detail-item{
    display: inline-flex;
    align-items: center;
    gap: 4px;
}

/* « Suivant » de la création (maquette BUTTON) : 93×34, coin de 8, 15/18 semibold. Celui du
   dépôt garde ses 120px. */
.create-grid .upload-flow .btn-primary:not(.btn-sm):not(.btn-xs):not(.btn-tall){
    min-width: 93px;
    height: 34px;
    min-height: 0;
    padding: 0 var(--sp-space-4);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 8px;
    font-size: 15px;
    font-weight: 600;
    line-height: 18px;
    letter-spacing: -0.02em;
}

/* « Supprimer » d'une ligne d'album (maquette) : 13/16 semibold gris #757575, sans soulignement. */
.create-grid .album-row .album-delete{
    font-size: 13px;
    font-weight: 600;
    line-height: 16px;
    letter-spacing: -0.01em;
    color: #757575;
    text-decoration: none;
}

/* Récap Visibilité (maquette ALBUM_CLOSED de la Validation) : le mode en 15/18 semibold #464646,
   à 8px d'une étiquette cernée #757575 (coin de 4, 2/8/3/7, cadenas à 3px, 13/16 medium) ; 8px
   plus bas, ce que le mode implique en 13/16 medium #757575, sans filet. */
.step-recap-meta--badged{
    display: flex;
    align-items: center;
    gap: var(--sp-space-2);
}

.create-grid .step-recap-meta--badged{
    color: #464646;
    overflow: visible;
}

.step-recap-badge{
    display: inline-flex;
    align-items: center;
    gap: 3px;
    padding: 1px 7px 2px 6px;   /* 2/8/3/7 dans la maquette, filet intérieur compris */
    border: 1px solid #757575;
    border-radius: 4px;
    font-size: 13px;
    font-weight: 500;
    line-height: 16px;
    letter-spacing: -0.01em;
    color: #757575;
}

.step-recap-note{
    margin-top: 3px;   /* 5 de gouttière + 3 = les 8 de la maquette */
    font-size: 13px;
    font-weight: 500;
    line-height: 16px;
    letter-spacing: -0.01em;
    color: #757575;
}

/* Carte « Validation » (maquette SIDE PANEL › TIPS) : blanche, 24px autour, coin de 24, 17px
   entre titre, engagements et bouton ; titre 16/19 semibold ; engagements en 13/16 medium ink,
   leur lien semibold souligné, case de 16 au coin de 4, 7px entre eux. Le bouton garde ses 45px
   (retour client, `.btn-tall`) plutôt que les 40 de la maquette. */
.create-grid .validation-card{
    display: flex;
    flex-direction: column;
    gap: 17px;
    padding: var(--sp-space-6);
    border-radius: 24px;
}

.create-grid .validation-card > .sec-header{
    margin: 0;
}

.create-grid .validation-card .sec-header-title{
    font-size: 16px;
    font-weight: 600;
    line-height: 19px;
    letter-spacing: -0.02em;
    color: #000;
}

.validation-consents{
    display: flex;
    flex-direction: column;
    gap: 7px;
}

.validation-consents .form-check-consent{
    margin: 0 !important;
}

.validation-consents .form-check{
    display: flex;
    align-items: center;
    gap: var(--sp-space-2);
    min-height: 16px;
    margin: 0;
    padding: 0;
}

.validation-consents .form-check-input{
    flex-shrink: 0;
    width: 16px;
    height: 16px;
    margin: 0;
    border-radius: 4px;
}

.validation-consents .form-check-label{
    font-size: 13px;
    font-weight: 500;
    line-height: 16px;
    letter-spacing: -0.01em;
    color: #1E1C1A;
}

.validation-consents .form-check-label a{
    font-weight: 600;
    color: inherit;
    text-decoration: underline;
}

/* Les étapes repliées de la Validation (maquette DROP) : le coin de 36 des autres étapes. */
.create-grid .steps-recap-card{
    border-radius: 36px;
}

.step-recap-body-lines:has(.step-recap-note){
    padding-bottom: 0;
}

/* Tom Select remplit son contrôle en rem (0.375 / 0.75rem) : 5,25 et 10,5px sur la racine de 14.
   Recalé sur les champs voisins : texte à 12px du bord, 8px après un préfixe (« Running › »). */
.ts-wrapper.form-select .ts-control{
    padding: var(--sp-space-1) 0 var(--sp-space-1) var(--sp-space-3);
}

.select-lead .ts-wrapper.form-select .ts-control{
    padding-left: var(--sp-space-2);
}

/* Saisie libre de la période et recherche des écrans comptables : un seul gabarit, 40px de haut,
   coin de 12, texte 14px. En `-sm`, champs et boutons tombaient à 12,25px (0.875rem sur la racine
   de 14) et les hauteurs allaient de 32 à 54 d'un contrôle à l'autre. */
.period-custom .form-control,
.period-custom .btn,
.ledger-search .form-control,
.ledger-search .form-select,
.ledger-search .btn{
    height: 40px;
    min-height: 0;
    border-radius: 12px;
    font-size: 14px;
    line-height: 18px;
}

.period-custom .form-control,
.ledger-search .form-control,
.ledger-search .form-select{
    padding-top: 0;
    padding-bottom: 0;
}

.period-custom .btn,
.ledger-search .btn{
    display: inline-flex;
    align-items: center;
    padding: 0 var(--sp-space-4);
    font-weight: var(--sp-font-weight-title);
}

.ledger-search .input-search .form-control{
    padding-left: 40px;
}

/* Le chevron du sélecteur d'évènement à 12px du bord (il tombait à 10,5, en rem) et le texte
   arrêté 8px avant lui : sinon « Tous les évènements » passait dessous. */
.ledger-search .form-select{
    padding-right: 36px;
    background-position: right 12px center;
}

/* Notes des écrans comptables en 13/16, comme les mentions de la maquette (1.4 donnait 18,2). */
.ledger-screen .sec-note,
.ledger-screen small{
    line-height: 16px;
}

/* Écrans comptables : le titre de page en 24/29 à 24px de la première carte ; la cagnotte aux
   cotes de celle du tableau de bord (maquette CAGNOTTE) — 21px au-dessus du titre 20/24, 14 du
   titre à la jauge, légende 13/16 gris clair, bouton de 40 au coin de 12 en 16 semibold, gris
   plein tant que le virement n'est pas possible. */
.ledger-screen > .ledger-title{
    margin-bottom: var(--sp-space-6);
}

.ledger-screen > .card-dark{
    padding-top: 21px;
}

.ledger-screen .card-dark .section-header-figure{
    margin-bottom: 14px !important;
}

.ledger-screen .card-dark h2{
    font-size: 20px;
    line-height: 24px;
    letter-spacing: -0.03em;
}

.ledger-screen .card-dark .progress-gauge-legend{
    line-height: 16px;
    letter-spacing: -0.01em;
    color: var(--sp-color-border-on-white);
}

.ledger-screen .card-dark .btn{
    min-height: 40px;
    border-radius: 12px;
    font-size: 16px;
    font-weight: var(--sp-font-weight-title);
    line-height: 19px;
    letter-spacing: -0.02em;
}

.ledger-screen .card-dark .btn:disabled{
    opacity: 1;
    border-color: #D1D1D1;
    background-color: #D1D1D1;
    color: #757575;
}

/* Paramètres pro (club, photographe) — champs fichier des documents légaux : leur titre est une
   <legend> de Bootstrap, en rem (6,25px au-dessus, ligne de 22,5) ; il prend les cotes des autres
   libellés de l'écran (15/18 medium, 7px du champ). L'aide passe en 13/16 au gris de la palette,
   4px sous le champ (13,125px et le gris froid de Bootstrap). Scopé à l'écran : la même règle à la
   racine changerait le front. */
.settings-shell legend.col-form-label{
    padding: 0;
    margin-bottom: 7px;
    font-size: 15px;
    font-weight: var(--sp-font-weight-body);
    line-height: 18px;
    letter-spacing: -0.02em;
}

.settings-shell .form-text{
    margin-top: var(--sp-space-1);
    font-size: 13px;
    line-height: 16px;
    color: var(--sp-color-text-muted);
}

/* =============================================================================================
   Dernières retouches client (Google Doc « DERNIERES RETOUCHES », 30/09/2026) — pages client
   seulement (.front-layout, posée par layout/default.html.twig). Les cotes demandées sont des
   écarts au rendu mobile d'alors (« +2px », « +1px ») : le client compare iOS à Figma, dont le
   rendu tombe ~7 % plus grand. Chaque règle est scopée à son écran ; ne pas remonter à la
   racine, les classes (chip-filter, btn-circle, badge-count…) servent aussi aux espaces pro.
   ============================================================================================= */

/* Navigation — logotype +4px de large (94, hauteur au prorata), toutes les pages mobiles */
@media (max-width: 991.98px) {
    .front-layout .topbar-front .brand{
        width: 94px;
        height: auto;
    }

    /* Avatar de la barre haute : 32 de diamètre (30 auparavant) */
    .front-layout .topbar-avatar .avatar{
        width: 32px;
        height: 32px;
    }

    /* Panier : 34 de diamètre (36 auparavant), glyphe inchangé */
    .front-layout .topbar-actions [data-cart-badge] .btn-circle{
        width: 34px;
        height: 34px;
        min-width: 34px;
        min-height: 34px;
    }
}

/* Burger : trois traits de 20×2 (+2px de large), en gris foncé #464646 */
.front-layout .topbar-front .icon-burger{
    width: 20px;
    height: 12px;
    color: var(--sp-color-grey-700);
}

/* Pastille du panier aux cotes Figma (HEADER_BAR > CART > Notif) : 16px, chiffre 11/13 semibold,
   débordant de 6px à droite du disque. Elle passait au-dessus de la page (coupée en haut, retour
   client) : elle descend juste assez pour rester dans la barre. Mobile seulement : la barre desktop,
   plus haute, ne la coupait pas. */
@media (max-width: 991.98px) {
    .front-layout [data-cart-badge] .badge-count{
        min-width: 16px;
        height: 16px;
        --bs-badge-padding-x: 4px;
        top: -3px !important;
        transform: translateX(-9px) !important;   /* translate-middle de Bootstrap est !important */
        font-size: 11px;
        font-weight: var(--sp-font-weight-600);
        line-height: 13px;
    }
}

/* Barre de recherche (accueil) — +4px (48), loupe +3px (19). Invite et loupe « plus foncées »
   (retour client) : Figma les pose en #D3CDC3 mais en mode de fusion plus-darker sur le fond de la
   barre (SEARCH_GLASS, HOMEPAGE_LIVE_CELL_VIEW 2356:11733) — c'est ce qui les assombrit sur la
   maquette. Safari (iOS) connaît ce mode : on le reprend tel quel ; ailleurs, la teinte obtenue. */
@media (max-width: 991.98px) {
    .front-layout .search-bar-mobile-wrapper{
        min-height: 48px;
    }

    .front-layout .search-bar{
        height: 48px;
        min-height: 48px;
    }

    .front-layout .search-bar .ts-control{
        padding-top: 12px !important;
        padding-bottom: 12px !important;
    }

    .front-layout .search-bar .input-group-text,
    .front-layout .search-bar .ts-control input::placeholder{
        color: #C1B9A9;   /* #D3CDC3 en plus-darker sur le fond de la barre, pour les moteurs sans ce mode */
    }

    @supports (mix-blend-mode: plus-darker) {
        .front-layout .search-bar .input-group-text,
        .front-layout .search-bar .ts-control input::placeholder{
            color: var(--sp-color-border-cream);
        }

        .front-layout .search-bar .input-group-text svg,
        .front-layout .search-bar .ts-control input{
            mix-blend-mode: plus-darker;
        }
    }

    .front-layout .search-bar .input-group-text svg{
        width: 19px;
        height: 19px;
    }

    /* « Recherchez un évènement, un sport… » tient jusqu'à 360px : 12px à droite au lieu de 16
       tant que la croix d'effacement n'est pas là (elle garde ses 44) */
    .front-layout .search-bar:not(:has(.search-clear:not([hidden]))) .ts-wrapper .ts-control{
        padding-right: 12px !important;
    }

    /* En deçà (320px), l'invite se termine sur des points de suspension, pas sur une lettre coupée */
    .front-layout .search-bar .ts-control input{
        text-overflow: ellipsis;
    }

    /* Recherche plein écran : la même barre de 48, sa croix à la même hauteur, et la barre
       active en blanc plein, loupe en ink (retour client) */
    .front-layout .search-fullscreen-close{
        width: 48px;
        height: 48px;
    }

    .front-layout .search-fullscreen-close svg{
        width: 16px;
        height: 16px;
    }

    .front-layout .search-fullscreen-open > .search-bar .input-group-text{
        color: var(--sp-color-text-default);
    }

    .front-layout .search-fullscreen-open .search-bar .ts-dropdown{
        top: calc(var(--sp-space-3) + 48px + var(--sp-space-3) + 36px + var(--sp-space-3)) !important;
    }
}

/* Onglets, chips et titres de l'accueil : les écarts demandés ont été relevés sur mobile (le
   desktop a sa propre maquette, HOMEPAGE DESKTOP) — ils ne valent que sous 992px. */
@media (max-width: 991.98px) {
    /* Tags de temporalité (Live, Récent, Passé, À venir) — +2px de haut (33), glyphe du Live +3px
       (17). Le libellé reste à la cote Figma, 16/19 semibold (TEMPORAL_FILTER). Le mode
       « compteurs » (sous un filtre) est validé tel quel par le client : il n'est pas touché. */
    .front-layout .tab-bar-block .tab-bar-nav:not(.tab-bar-nav--counted) .nav-link{
        min-height: 33px;
        padding-top: 7px;
        padding-bottom: 7px;
    }

    /* Avec le glyphe de 17, les quatre libellés font 199px : 18px de côté tant qu'ils tiennent, un
       côté resserré au pixel entier en deçà, pour que « À venir » ne sorte pas de l'écran */
    .front-layout .tab-bar-block .tab-bar-nav:not(.tab-bar-nav--counted) .nav-item .nav-link{
        padding-left: clamp(8px, round(down, (100vw - 32px - 199px) / 8, 1px), 18px);
        padding-right: clamp(8px, round(down, (100vw - 32px - 199px) / 8, 1px), 18px);
    }

    .front-layout .tab-bar-block .tab-bar-nav:not(.tab-bar-nav--counted) .nav-link svg{
        width: 17px;
        height: 17px;
    }

    /* Sélecteurs de filtres (chips) — +2px de haut (36), glyphe +3px (17), libellé +1px (15/18) en
       medium, la graisse de Figma (EVENT_FILTER) ; le retrait gauche compense le blanc interne du
       glyphe pour qu'il y ait autant de bord à gauche que de bord à droite ; chevron plus grand et
       plus épais. Graisse +1 cran ensuite (500 → 600, retour client « FINAL TOUCHES ») : iOS
       rend le medium plus maigre que Figma. Ce 600 ne se voyait pas : .btn-light fige l'axe de
       la police variable (`'wght' 400`), qui l'emporte sur font-weight — la chip rendait du 400
       (retour client d'octobre, « encore trop fine »). L'axe est rendu à la graisse ici
       seulement : le desktop, jugé juste, garde son rendu. Rendue en 600, elle sautait deux
       crans d'un coup ; le client n'avait jamais vu que du 400 : elle passe au cran au-dessus,
       le medium de la maquette (décision de Quentin, 07/10). Les 36px sont une demande client
       (30/09) : ils priment sur les 34 de la maquette, ne pas les y ramener.
       27/10 : le client la juge encore trop fine sur iPhone face au desktop : semi-bold. */
    .front-layout .chip-filter{
        height: 36px;
        font-size: 15px;
        line-height: 18px;
        font-weight: var(--sp-font-weight-600);
        font-variation-settings: normal;
    }

    .front-layout .chip-filter > svg{
        width: 17px;
        height: 17px;
    }

    .front-layout .chip-filter:has(> svg:first-child){
        padding-left: 11px;
    }

    .front-layout .chip-filter-chevron svg{
        width: 12px;
        height: 12px;
    }

    /* Le glyphe est un tracé plein : un contour du même ton l'épaissit (1,4 → 2,2 de sa grille) */
    .front-layout .chip-filter-chevron svg path{
        stroke: currentColor;
        stroke-width: 0.8px;
        stroke-linejoin: round;
    }

    /* 600 sur mobile (retour client : le 400 se lisait trop maigre à côté des chips) */
    .front-layout .filter-clear{
        font-size: 15px;
        line-height: 18px;
        font-weight: var(--sp-font-weight-600);
        font-variation-settings: normal;
    }

    /* Titres de section de l'accueil (tous ses onglets, et ses résultats filtrés) — +1px (21/25),
       glyphes du titre +3/4px (Live 22, flèche 18). Pas ailleurs : sur la page évènement, le client
       ne veut pas toucher au titre « Photographes ». */
    .front-layout .container-home .sec-header-title{
        font-size: 21px;
        line-height: 25px;
    }

    .front-layout .container-home .sec-header-title > svg{
        width: 18px;
        height: 18px;
    }

    .front-layout .container-home .sec-header-title > .sec-header-glyph-live{
        width: 22px;
        height: 22px;
    }
}

/* Carte évènement — un match porte sa ligue sous son nom : 12px medium en gris clair, collée au
   titre ; le groupe prend 4px de plus au-dessus de lui, la carte ne grandit pas */
.event-highlighted-heading{
    display: flex;
    flex-direction: column;
    gap: 1px;
    min-width: 0;
    margin-top: 4px;
}

.event-highlighted-subtitle{
    color: var(--sp-color-grey-300);
    font-size: 12px;
    font-weight: var(--sp-font-weight-500);
    line-height: 15px;
    letter-spacing: -0.01em;
}

/* Pastille VS des cartes : 20×14, 10px extra bold — sur les titres de 20px (cartes, et le hero
   mobile) ; le hero desktop, en 40px, garde la sienne à l'échelle de son titre */
.event-highlighted:not(.event-highlighted-header) .event-highlighted-title .vs-badge{
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 20px;
    height: 14px;
    padding: 0 3px;
    border-radius: 4px;
    font-size: 10px;
    font-weight: 800;
    letter-spacing: 0;
    vertical-align: 2px;
}

@media (max-width: 991.98px) {
    .event-highlighted-header .event-highlighted-title .vs-badge{
        display: inline-flex;
        align-items: center;
        justify-content: center;
        min-width: 20px;
        height: 14px;
        padding: 0 3px;
        border-radius: 4px;
        font-size: 10px;
        font-weight: 800;
        letter-spacing: 0;
        vertical-align: 2px;
    }
}

/* Tag « Expire » des cartes : la croix a la hauteur du E (capitale de 12px ≈ 9px d'encre, la
   croix n'occupe que 81 % de sa grille : 11px), au lieu des 14 du compteur ; l'échéance proche
   prend le rouge saturé demandé, #CC2D29, en aplat */
.event-highlighted .badge .badge-cross{
    width: 11px;
    height: 11px;
}

.event-highlighted .badge-danger{
    background-color: #CC2D29;
}

/* Le tag rouge est en 13px : sa capitale fait ~9,5px d'encre, la croix passe à 12 */
.event-highlighted .badge-danger .badge-cross{
    width: 12px;
    height: 12px;
}

/* Carte compacte (Live > Voir tout) : elle peut grandir (retour client) ; la ligue s'y détache de
   la méta comme dans le rail, 6px sous elle */
.event-highlighted-short .event-highlighted-heading{
    margin-bottom: 4px;
}

/* Panneau Lieux : le halo de focus débordait du panneau (retour client) — au focus, pas de halo
   ni de liseré orange, c'est le texte (loupe et invite) qui passe à l'ink */
.front-layout .filter-location-field .form-control:focus{
    box-shadow: none;
    border-color: var(--sp-color-border-cream);
    color: var(--sp-color-text-default);
}

.front-layout .filter-location-field:focus-within .form-control::placeholder,
.front-layout .filter-location-field:focus-within .filter-location-icon{
    color: var(--sp-color-text-default);
}

/* Recherche plein écran — barre active en blanc plein (le verre la laissait grisée) ; les chips
   de familles vont bord à bord et reprennent la gouttière en retrait (elles étaient rognées à
   16px du bord) ; pas de filet entre le dernier évènement et « Voir tous les évènements », que
   le lien rejoint ; 20px entre deux familles de résultats (+4) */
@media (max-width: 991.98px) {
    .front-layout .search-fullscreen-open > .search-bar{
        background: var(--sp-color-bg-surface);
    }

    .front-layout .search-fullscreen-tabs{
        margin: 0 calc(var(--sp-space-4) * -1);
        padding-left: var(--sp-space-4);
        padding-right: var(--sp-space-4);
        scroll-padding-left: var(--sp-space-4);
        scroll-padding-right: var(--sp-space-4);
    }

    .front-layout .search-fullscreen-open .search-suggestions{
        border-top: 0;
        padding-top: var(--sp-space-1);
    }

    .front-layout .search-fullscreen-open[data-search-category="all"] .ts-dropdown-content.search-options--collapsed .option:nth-child(2) .list-item{
        border-bottom: 0;
    }

    /* Qualifié par la famille : ailleurs qu'en « Meilleurs résultats », le lien reste masqué */
    .front-layout .search-fullscreen-open[data-search-category="all"] .search-more-events{
        display: inline-flex;
        align-items: center;
        gap: var(--sp-space-1);
        padding: 0 0 20px;
    }

    .front-layout .search-fullscreen-open .search-suggestions-section:not(:last-child){
        margin-bottom: 20px;
    }
}

/* Boutons liquid glass posés sur une photo (page évènement, vue photo, profil) — le retour prend
   le verre clair de la vue photo (« très bien » pour le client) agrandi de 4px, soit 44, avec le
   chevron fourni (CHEVRON BACK, 11×18) ; la pilule voisine prend la même hauteur. Sur l'évènement
   elle reste sombre, avec un liseré éteint (il brillait plus que celui du profil) ; sur la vue
   photo et le profil, le verre clair du profil. */
@media (max-width: 991.98px) {
    .front-layout .event-highlighted-header--page .event-hero-back.btn-glass,
    .front-layout .photo-stage-bar .btn-glass{
        width: 44px;
        height: 44px;
        min-width: 44px;
        min-height: 44px;
        border: 1px solid transparent;
        background:
            linear-gradient(var(--sp-glass-button-bg-light), var(--sp-glass-button-bg-light)) padding-box,
            var(--sp-glass-menu-rim) border-box;
        backdrop-filter: blur(4px);
        -webkit-backdrop-filter: blur(4px);
        box-shadow: none;
        color: var(--sp-color-text-inverse);
    }

    .front-layout .event-highlighted-header--page .event-hero-back svg,
    .front-layout .photo-stage-bar .btn-glass svg{
        width: 11px;
        height: 18px;
        margin-right: 2px;   /* le chevron pointe à gauche : son centre optique est à droite de sa boîte */
    }

    /* La pilule sombre de l'évènement : le CSS de celle du profil (flou de 20, ombre de décollement,
       lentille, liseré), en version sombre — sans le filet dégradé qu'elle doublait, et le
       liseré éteint à 35 % (« stroke plus sombre », retour client) */
    .front-layout .event-highlighted-header--page .glass-group{
        height: 44px;
        padding: 0 3px;
        border: 0;
        background: var(--sp-glass-button-bg);
        backdrop-filter: blur(var(--sp-glass-blur));
        -webkit-backdrop-filter: blur(var(--sp-glass-blur));
        box-shadow: var(--sp-glass-overlay-lift);
    }

    .front-layout .event-highlighted-header--page .glass-group .glass-group-item{
        width: 40px;
        min-width: 40px;
        height: 42px;
        min-height: 42px;
    }

    .front-layout .event-highlighted-header--page .glass-group::after{
        opacity: .35;
    }

    /* La pilule claire de la vue photo : celle du profil, à l'identique (retour client : « style
       parfait page profil ») — verre clair, flou de 20, ombre de décollement, lentille et liseré */
    .front-layout .photo-stage-bar .photo-stage-actions{
        position: relative;
        isolation: isolate;
        height: 44px;
        padding: 0 3px;
        border: 0;
        border-radius: var(--sp-radius-full);
        background: var(--sp-glass-button-bg-light);
        backdrop-filter: blur(var(--sp-glass-blur));
        -webkit-backdrop-filter: blur(var(--sp-glass-blur));
        box-shadow: var(--sp-glass-overlay-lift);
    }

    .front-layout .photo-stage-bar .photo-stage-actions::before{
        content: '';
        position: absolute;
        inset: 0;
        z-index: -1;
        border-radius: inherit;
        backdrop-filter: url(#spicto-liquid-glass);
        -webkit-backdrop-filter: url(#spicto-liquid-glass);
        pointer-events: none;
    }

    .front-layout .photo-stage-bar .photo-stage-actions::after{
        content: '';
        position: absolute;
        inset: 0;
        padding: 1px;
        border-radius: inherit;
        background: var(--sp-glass-overlay-rim);
        -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
        -webkit-mask-composite: xor;
        mask: linear-gradient(#000 0 0) content-box exclude, linear-gradient(#000 0 0);
        pointer-events: none;
    }

    .front-layout .photo-stage-bar .photo-stage-action{
        width: 40px;
        height: 44px;
    }

    .front-layout .card-photo--profile .card-photo-actions .glass-group,
    .front-layout .card-photo--profile .card-photo-actions .btn-glass{
        height: 44px;
    }

    .front-layout .card-photo--profile .card-photo-actions .glass-group-item{
        width: 40px;
        height: 44px;
    }

    .front-layout .card-photo--profile .card-photo-actions .btn-glass{
        width: 44px;
        min-width: 44px;
        min-height: 44px;
    }

    /* Page évènement : la carte gagne 8px (188) */
    .front-layout .event-highlighted-header--page{
        height: 188px;
        min-height: 188px;
    }
}

/* Le glyphe de partage pèse vers le bas (la boîte sous la flèche) : remonté d'1px pour se centrer
   à l'œil dans son disque (retour client, profil et vue photo) */
.front-layout .card-photo-actions [data-controller="share"] svg,
.front-layout .photo-actions .btn-share svg{
    transform: translateY(-1px);
}

/* Photo d'un album protégé, déverrouillé (galerie) : nette, son cadenas en coin (retour client) */
.photo-tile--private{
    position: relative;
}

/* Le cadenas d'une vignette carrée : `.ratio > *` de Bootstrap le collait au bord gauche (left: 0)
   à 8px du haut — même marge à gauche qu'en haut (retour client, « FINAL TOUCHES ») */
.ratio > .photo-tile-lock{
    top: var(--sp-space-2);
    left: var(--sp-space-2);
    right: auto;
    width: 24px;
    height: 24px;
}

/* Panneau Albums : le cadenas et le dossard qui suivent un nom d'album se centrent sur ses
   capitales (-2px les faisait descendre sous la ligne) */
.front-layout .album-panel .album-row-lock{
    vertical-align: 0;
}

/* Panneau Photographes : « 84 photos · Plus à venir » tient sur une ligne */
.front-layout .filter-row--card .filter-row-meta{
    white-space: nowrap;
}

.front-layout .filter-row--card .filter-row-meta .badge{
    white-space: nowrap;
}

/* Galerie de l'évènement : « Effacer les filtres » se pose juste après le dernier filtre réglé, comme sur
   l'accueil — les filtres réglés (ceux qui portent un chevron) passent devant, les autres
   suivent la sortie, le tri ferme la rangée */
.front-layout .event-page .photo-filter-bar .filter-chips > *{
    order: 2;
}

.front-layout .event-page .photo-filter-bar .filter-chips > .filter-anchor:has(.chip-filter-chevron){
    order: 0;
}

.front-layout .event-page .photo-filter-bar .filter-chips > .filter-clear{
    order: 1;
}

.front-layout .event-page .photo-filter-bar .filter-chips > .ms-lg-auto{
    order: 3;
}

/* Frise : l'en-tête compact au défilement prend le liquid glass de la page de téléchargement (la
   pastille du photographe : lentille, liseré), aux cotes de sa version verre dans Figma (« Glass
   Effect » 4567:31123) : blanc à 38 %, ombre 0 8 40 à 20 % ; la flèche dans le « Done Botton » de la
   même frame (4567:31146) — disque de 32 gris à 74 %, liseré dégradé, ombre 0 4 24 à 10 %, flou 4 */
.front-layout .timeline-sticky{
    isolation: isolate;
    overflow: hidden;
    border: 0;
    background-color: rgba(255, 255, 255, .38);
    backdrop-filter: blur(var(--sp-glass-overlay-blur));
    -webkit-backdrop-filter: blur(var(--sp-glass-overlay-blur));
    box-shadow: 0 8px 40px rgba(0, 0, 0, .2);
}

.front-layout .timeline-sticky::before{
    content: '';
    position: absolute;
    inset: 0;
    z-index: -1;
    border-radius: inherit;
    backdrop-filter: url(#spicto-liquid-glass);
    -webkit-backdrop-filter: url(#spicto-liquid-glass);
    pointer-events: none;
}

.front-layout .timeline-sticky::after{
    content: '';
    position: absolute;
    inset: 0;
    padding: 1px;
    border-radius: inherit;
    background: var(--sp-glass-overlay-rim);
    -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    -webkit-mask-composite: xor;
    mask: linear-gradient(#000 0 0) content-box exclude, linear-gradient(#000 0 0);
    pointer-events: none;
}

.front-layout .timeline-sticky-top{
    border: 1px solid transparent;
    background:
        linear-gradient(var(--sp-glass-button-bg-back), var(--sp-glass-button-bg-back)) padding-box,
        linear-gradient(160deg, #FFFFFF 0%, rgba(255, 255, 255, .02) 50%, #FFFFFF 100%) border-box;
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
    box-shadow: 0 4px 24px rgba(0, 0, 0, .1);
}

/* Page évènement sans photos — « Photographes (1) » : Figma l'écrit en un seul texte, le « (1) » en
   15px medium sur la ligne de base du titre (2211:11006). Aligné ainsi, il descend de ~2px — ce que
   demandait le client (« un peu trop haut ») —, sans toucher à la taille du titre */
.front-layout .event-photographers-col .sec-header-title{
    align-items: baseline;
}

.front-layout .event-photographers-col .sec-header-title-count{
    align-self: baseline;   /* une règle antérieure le centrait (align-self: center) */
    line-height: 18px;      /* 15px à 100 % (Figma) : la ligne du titre reste à 24 */
}

/* Vue photo — la photo se décolle de la barre haute de 6px, comme le hero de la page évènement */
@media (max-width: 991.98px) {
    .front-layout .photo-page .photo-frame,
    .front-layout .photo-frame{
        margin-top: 6px;
    }
}

/* Compteur de la photo : coin entièrement arrondi, position et total posés sur la même ligne de
   base (le total, plus petit, flottait au milieu) */
.front-layout .photo-stage-counter{
    align-items: baseline;
    padding-top: 6px;
    padding-bottom: 6px;
    border-radius: var(--sp-radius-full);
}

/* Parcours filtré : l'entonnoir du client (FILTER.svg) devant la position, posé sur la même ligne
   de base et haut comme ses chiffres (retour client, « FINAL TOUCHES ») */
.front-layout .photo-stage-counter-filter{
    flex-shrink: 0;
    width: 9px;
    height: 10px;
    margin-right: 4px;
}

/* « Acheter en HD » : orange uni, sans le reflet intérieur ; la portée (contour) est conservée */
.front-layout .photo-actions .btn.btn-acquire.btn-marketing{
    background-image: none;
}

/* Le loader Spicto de la vue photo (animation fournie par le client) : 56px, glyphes au brun des
   légendes, rotation verticale ; il remplace l'anneau tant que la photo charge */
.spicto-loader{
    position: absolute;
    top: 50%;
    left: 50%;
    z-index: 1;
    display: none;
    width: 56px;
    height: 56px;
    margin: -28px 0 0 -28px;
    perspective: 520px;
    color: var(--sp-color-text-caption);
    pointer-events: none;
}

.photo-stage.is-loading .spicto-loader{
    display: block;
}

.front-layout .photo-stage.is-loading::after{
    content: none;
}

.spicto-loader-rotor{
    position: relative;
    width: 100%;
    height: 100%;
    transform-style: preserve-3d;
    will-change: transform;
}

.spicto-loader-face{
    position: absolute;
    inset: 0;
    display: grid;
    place-items: center;
    backface-visibility: hidden;
    -webkit-backface-visibility: hidden;
}

.spicto-loader-face--back{
    transform: rotateY(180deg);
}

.spicto-loader-icon{
    display: grid;
    place-items: center;
    width: 58%;
    height: 58%;
}

.spicto-loader-icon svg{
    display: block;
    width: 100%;
    height: 100%;
    overflow: visible;
}

@media (prefers-reduced-motion: reduce) {
    .spicto-loader-face--back{
        display: none;
    }
}

/* Téléchargement offert : libellé en bold (le 600 paraissait maigre au client), à la taille du
   montant du bouton d'achat (15px, Figma) ; le glyphe DOWNLOAD.svg à sa taille réelle, 10×13 —
   un tracé de 12px de haut, celui de Figma (9,33×11,67), au lieu des 10 où le cadre de 11 le
   réduisait (retour client : « icône agrandir en conséquence ») */
.front-layout .btn-free.btn-acquire{
    font-weight: var(--sp-font-weight-700);
}

.front-layout .btn-free .btn-free-glyph{
    width: 10px;
    height: 13px;
}

/* Le retour en pilule des pages de téléchargement (offert et payant), aux cotes de son liquid glass
   dans Figma (« Done » 2391:7108, PHOTO_PAGE_FREE) : 40px, fond #F7F7F7 plein, ombre 0 8 40 à 9 %,
   sans bordure, 12px de côté, flèche de 19 à 7px du libellé en 15/18 semibold */
.front-layout .btn-back-pill{
    --bs-btn-bg: #F7F7F7;
    --bs-btn-hover-bg: #F7F7F7;
    --bs-btn-border-color: transparent;
    --bs-btn-hover-border-color: transparent;
    gap: 7px;
    height: 40px;
    padding: 0 12px;
    border: 0;
    box-shadow: 0 8px 40px rgba(0, 0, 0, .09);
    line-height: 18px;
    letter-spacing: -0.02em;
}

.front-layout .btn-back-pill svg{
    width: 19px;
    height: 19px;
}

/* Onglet Aperçu : un peu d'air entre la ligne des mégapixels et celle de l'impression */
.front-layout #photo-panel-apercu .info-row-meta + .info-row-meta{
    margin-top: 4px;
}

/* Vignette floutée d'un album protégé (profil) : le clic droit est bloqué (nocontext) et l'image
   ne se laisse ni viser ni garder par un appui long — le clic va au lien, pas à l'image
   (retour client : « Enregistrer l'image » emportait la photo nette sous le flou) */
.photo-tile--locked img{
    pointer-events: none;
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    user-select: none;
}

.photo-tile--locked{
    -webkit-touch-callout: none;
}

/* Panier mobile — le logotype à la cote de la barre haute (94px, 13px du haut) : il remonte, et
   l'air grandit au-dessus du filet (22px au lieu de 15) ; la croix reste centrée sur lui */
@media (max-width: 991.98px) {
    .front-layout #offcanvasCart .cart-header{
        align-items: flex-start;
        min-height: 53px;
        padding-top: 0;
    }

    .front-layout #offcanvasCart .cart-header-brand{
        margin-top: 13px;
    }

    .front-layout #offcanvasCart .cart-header-brand .brand{
        width: 94px;
        height: auto;
    }

    /* Plus de bandes noires autour du panneau plein écran (retour client) : le voile noir de
       Bootstrap, derrière lui, teintait la barre d'état et le bas d'écran d'iOS. Le panneau
       couvre tout : le voile prend son crème. */
    .front-layout:has(#offcanvasCart.show, #offcanvasCart.showing) .offcanvas-backdrop{
        background-color: var(--sp-color-bg-default);
    }

    .front-layout:has(#offcanvasCart.show, #offcanvasCart.showing) .offcanvas-backdrop.show{
        opacity: 1;
    }
}

/* Libellé flottant d'un champ requis (tunnel d'achat, « Pays ») : l'astérisque passe par le
   ::after que Bootstrap réserve au fond du libellé remonté — il héritait de sa position absolue
   et se posait derrière le P. Il revient dans la ligne, après le mot. */
/* Même défaut dans les paramètres pro (« Pays » de l'adresse de paiement, retour client). */
.front-layout .form-floating > label.required:not(.form-check-label)::after,
.photographer-layout .form-floating > label.required:not(.form-check-label)::after,
.club-layout .form-floating > label.required:not(.form-check-label)::after{
    position: static;
    inset: auto;
    z-index: auto;
    height: auto;
    padding: 0;
    border-radius: 0;
    background: none;
}

/* Tunnel — « Payer maintenant » : 46px (+6, retour client), en ink et 16px medium comme dans Figma
   (« Payer maintenant », 1814:3615). Dessous, l'adresse d'envoi des photos, reprise de l'ancien
   récapitulatif, en 16/19 au gris du texte secondaire, l'adresse en ink. */
.front-layout .btn-tunnel.btn-pay-now{
    min-height: 46px;
}

.front-layout .checkout-send-to{
    font-size: var(--sp-font-size-16);
    line-height: 19px;
    letter-spacing: var(--sp-font-tracking-tight);
    color: var(--sp-color-text-muted);
}

.front-layout .checkout-send-to strong{
    color: var(--sp-color-text-default);
    font-weight: var(--sp-font-weight-600);
    /* Sur sa ligne, l'adresse ne se coupe plus que si elle dépasse la largeur (retour client) */
    overflow-wrap: anywhere;
}

/* L'en-tête du tunnel porte le logotype de la barre haute : 94px sur mobile (retour client) */
@media (max-width: 991.98px) {
    .front-layout .checkout-header .brand{
        width: 94px;
        height: auto;
    }
}

/* Hero desktop de la page évènement : la ligue d'un match à l'échelle de la méta du hero (20/24
   medium), sous un titre de 40px — 12px s'y perdait */
@media (min-width: 992px) {
    .event-highlighted-header--page .event-highlighted-subtitle{
        font-size: 20px;
        line-height: 24px;
        letter-spacing: -0.01em;
    }
}

/* --- Liste des disciplines (création d'évènement) : la famille des suggestions du site --------
   Tom Select servait son habillage Bootstrap — filet gris froid, coin de 5,25px et marge de
   3,5px (rem sur la racine de 14), texte à 14px, surlignage jaune, plafond de 200px qui ne
   montrait que cinq lignes. Elle reprend celui des suggestions de lieu et d'organisateur du même
   formulaire : carte blanche au coin de 16, ombre « pop », lignes de 40px, crème au survol.
   Sélecteurs à quatre classes : la feuille de Tom Select est chargée après la nôtre (0,2,0). */
.select-lead .ts-wrapper .ts-dropdown{
    margin-top: var(--sp-space-2);
    border: 0;
    border-radius: var(--sp-radius-lg);
    background: var(--sp-color-bg-surface);
    box-shadow: var(--sp-shadow-pop);
    color: var(--sp-color-text-default);
    font-size: var(--sp-font-size-body);
    overflow: hidden;
}

.select-lead .ts-wrapper .ts-dropdown .ts-dropdown-content{
    max-height: min(360px, 50vh);
    padding: 0 0 var(--sp-space-2);
    overscroll-behavior: contain;
}

/* Le filet entre deux sports sépare les groupes ; l'en-tête, lui, reste collé en haut pendant
   qu'on parcourt son groupe : on sait toujours de quel sport on lit les disciplines. */
.select-lead .ts-wrapper .ts-dropdown .optgroup::before{
    display: none;
}

.select-lead .ts-wrapper .ts-dropdown .optgroup + .optgroup{
    border-top: var(--sp-border-width-default) solid var(--sp-color-border-on-white);
}

.select-lead .ts-wrapper .ts-dropdown .optgroup-header{
    position: sticky;
    top: 0;
    z-index: 1;
    display: flex;
    align-items: center;
    gap: var(--sp-space-2);
    padding: var(--sp-space-3) var(--sp-space-4) var(--sp-space-1);
    background: var(--sp-color-bg-surface);
    color: var(--sp-color-text-brown);
    font-size: var(--sp-font-size-meta);
    font-weight: var(--sp-font-weight-title);
    line-height: 16px;
    letter-spacing: var(--sp-font-tracking-meta);
}

.select-lead .ts-wrapper .ts-dropdown .optgroup-glyph{
    display: inline-flex;
    flex: 0 0 auto;
    color: var(--sp-color-text-default);
}

/* Le libellé d'une discipline s'aligne sur le NOM du sport, pas sur son glyphe : la liste se lit
   comme un sommaire, l'enfant sous le parent (18px de glyphe, 8px d'écart). */
.select-lead .ts-wrapper .ts-dropdown .option{
    padding: 11px var(--sp-space-4) 11px calc(var(--sp-space-4) + 18px + var(--sp-space-2));
    line-height: 18px;
    letter-spacing: var(--sp-font-tracking-tight);
}

/* Survol et clavier sont le même état : la ligne visée (comme les suggestions de lieu). */
.select-lead .ts-wrapper .ts-dropdown .option.active{
    background-color: var(--sp-color-bg-cream);
    color: var(--sp-color-text-default);
}

.select-lead .ts-wrapper .ts-dropdown .option.selected{
    font-weight: var(--sp-font-weight-title);
}

.select-lead .ts-wrapper .ts-dropdown [data-selectable] .highlight{
    background: none;
    border-radius: 0;
    color: inherit;
    font-weight: var(--sp-font-weight-title);
}

.select-lead .ts-wrapper .ts-dropdown .no-results{
    padding: var(--sp-space-4);
    color: var(--sp-color-text-muted);
}

@media (max-width: 767px) {
    .select-lead .ts-wrapper .ts-dropdown{
        font-size: var(--sp-font-size-16);
    }
}

/* Les messages flash passent au-dessus de la page : sans niveau, le voile d'une carte photo
   (z-index 1) recouvrait le début du message — « …il mis à jour. » sur la section Profil.
   1090 est le niveau que Bootstrap réserve à ses toasts, au-dessus des panneaux et des modales. */
.flash-stack{
    z-index: 1090;
}

/* --- Mes photos : En ligne / Expirés (retours client d'octobre) ----------------------------- */

/* La liste commence sous son titre, sans le retrait de 16 d'une ligne : la carte en a déjà 24
   (« réduire l'espace en haut de la zone résultats »). */
.photo-uploads-section > .list-item:first-of-type{
    padding-top: 0;
}

/* « Voir plus (N) » devient « Voir moins » une fois la suite dépliée */
.photo-uploads-more .photo-uploads-more-hide,
.photo-uploads-more[aria-expanded="true"] .photo-uploads-more-show{
    display: none;
}

.photo-uploads-more[aria-expanded="true"] .photo-uploads-more-hide{
    display: inline;
}

/* --- Gestion d'un dépôt : un onglet par album où vivent ses photos (retour client) --------- */
/* Même langage que les onglets de dépôts au-dessus : pilule crème pour le courant, le nombre
   de photos en méta. Ils défilent s'ils débordent. */
.deposit-album-tabs{
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-space-2);
}

.deposit-album-tab{
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: var(--sp-space-2) var(--sp-space-3);
    border: 1px solid var(--sp-color-border-default);
    border-radius: var(--sp-radius-md);
    font-size: var(--sp-font-size-label);
    font-weight: var(--sp-font-weight-title);
    line-height: 18px;
    color: var(--sp-color-text-default);
    text-decoration: none;
}

.deposit-album-tab:hover{
    background-color: var(--sp-color-bg-cream);
}

.deposit-album-tab.is-current{
    border-color: transparent;
    background-color: var(--sp-color-bg-sunken);
}

.deposit-album-tab-count{
    font-weight: var(--sp-font-weight-body);
    color: var(--sp-color-text-muted);
}

/* Une suppression en cours : la grille se grise et ne se clique plus (retour client) */
.photo-manage-grid.is-pending{
    opacity: .45;
    filter: grayscale(1);
    pointer-events: none;
    transition: opacity .2s ease;
}

/* Dépôt en cours de suppression : son onglet, ses albums et ses cartes se grisent et ne se cliquent plus */
.deposit-tab.is-deleting,
.is-deleting .deposit-album-tab,
.is-deleting .deposit-info{
    opacity: .45;
    pointer-events: none;
}

.deposit-tab.is-deleting .deposit-tab-meta{
    font-weight: var(--sp-font-weight-title);
}

/* --- Albums d'un évènement publié, en accordéon (retours client d'octobre, maquette « Album » du
       dépôt, Figma DEPOT) -------------------------------------------------------------------- */
.am-rule{
    margin: var(--sp-space-4) 0;
    border: 0;
    border-top: 1px solid var(--sp-color-brown-border-light);
    opacity: 1;
}

.am-days{
    display: flex;
    flex-direction: column;
    gap: 12px;
}

/* La journée repliée : un bandeau crème très clair au coin de 16, 20px 20px 20px 16px ; le titre
   16/19 semibold, « · 4 albums » en 13/16 medium gris foncé. Dépliée, le bandeau prend un filet
   et le panneau de ses albums se pose dessous. */
.am-day-head{
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    width: 100%;
    padding: 20px 20px 20px 16px;
    border: 1px solid transparent;
    border-radius: 16px;
    background-color: #FAF9F5;
    color: var(--sp-color-text-default);
    text-align: left;
}

.am-day.is-open .am-day-head{
    border-color: #A29689;
    border-radius: 12px;
}

.am-day-title{
    display: inline-flex;
    align-items: baseline;
    gap: 6px;
    min-width: 0;
}

.am-day-name{
    font-size: 16px;
    font-weight: var(--sp-font-weight-title);
    line-height: 19px;
    letter-spacing: -0.02em;
}

.am-day-meta{
    white-space: nowrap;
    font-size: 13px;
    font-weight: var(--sp-font-weight-body);
    line-height: 16px;
    letter-spacing: -0.01em;
    color: #464646;
}

/* Repliée, le chevron pointe vers la gauche ; dépliée, vers le bas (maquette) */
.am-day-chevron{
    display: inline-flex;
    transform: rotate(180deg);
    transition: transform .2s ease;
}

.am-day.is-open .am-day-chevron{
    transform: rotate(90deg);
}

/* Le panneau d'une journée : un filet brun clair au coin de 16, 20px 16px 16px ; les albums
   séparés d'un filet BROWN_BORDER_LIGHT. */
.am-day-panel{
    margin-top: 12px;
    padding: 4px 16px 16px;
    border: 1px solid var(--sp-color-border-cream);
    border-radius: 16px;
}

.am-item{
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 16px 0;
    border-bottom: 1px solid var(--sp-color-brown-border-light);
}

.am-item-text{
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}

.am-item-name{
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 15px;
    font-weight: var(--sp-font-weight-title);
    line-height: 18px;
    letter-spacing: -0.02em;
    color: var(--sp-color-text-default);
}

.am-item-icon{
    display: inline-flex;
}

.am-item-meta{
    font-size: 13px;
    font-weight: var(--sp-font-weight-body);
    line-height: 16px;
    letter-spacing: -0.01em;
    color: #757575;
}

.am-item-meta strong{
    font-weight: var(--sp-font-weight-title);
}

/* L'album d'un autre photographe se lit éteint, en GREY_FADE (retour client) */
.am-item--other .am-item-name,
.am-item--other .am-item-meta{
    color: #D1D1D1;
}

.am-item--other .vs-badge{
    background-color: #D1D1D1;
}

.am-item-actions{
    display: flex;
    align-items: center;
    gap: 8px;
    flex-shrink: 0;
}

/* Les gestes de ligne : pilules crème de 28px (TRASH, MODIFIER, UP_DOWN de la maquette) */
.am-btn{
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: 28px;
    padding: 3px 10px;
    border: 0;
    border-radius: 32px;
    background-color: var(--sp-color-bg-cream);
    color: var(--sp-color-text-default);
    font-size: 13px;
    font-weight: var(--sp-font-weight-title);
    line-height: 16px;
    letter-spacing: -0.01em;
}

.am-btn:hover,
.am-btn:focus-visible{
    background-color: var(--sp-color-bg-sunken);
}

.am-btn--icon{
    width: 28px;
    padding: 0;
}

.am-move{
    display: inline-flex;
    gap: 1px;
}

.am-move-btn{
    width: 30px;
    padding: 0;
}

.am-move-btn--up{
    border-radius: 30px 0 0 30px;
}

.am-move-btn--down{
    border-radius: 0 30px 30px 0;
}

.am-move-btn--up svg{
    transform: rotate(-90deg);
}

.am-move-btn--down svg{
    transform: rotate(90deg);
}

.am-move-btn:disabled{
    color: var(--sp-color-border-cream);
    opacity: 1;
}

.album-manager .am-create{
    margin-top: 16px;
}

/* --- Modales d'album sur desktop (retour client : « trop étroites, dimensionnées pour le
       mobile ») : une fois et demie la largeur, les deux boutons côte à côte. --------------- */
.dialog-album-actions{
    display: grid;
    gap: var(--sp-space-2);
}

@media (min-width: 992px){
    .dialog--album .modal-dialog{
        max-width: 760px;
    }

    .dialog--album .dialog-album-actions{
        grid-template-columns: 1fr 1fr;
    }
}

/* L'aperçu de création : le nom d'un évènement classique ne prend pas les 4px qu'un match gagne
   au-dessus de son affiche et de sa ligue */
.event-highlighted-preview .event-highlighted-heading:has(> .event-highlighted-subtitle[hidden]){
    margin-top: 0;
}

/* Paramètres › Informations, rangées compactes (retour client) : les champs à libellé
   au-dessus (date de naissance, genre) et le lieu ne gardent pas leur marge basse — la grille
   et la carte font l'écart. */
.settings-compact .row > .col > .mb-3,
.settings-compact fieldset.mb-3,
.settings-compact .places-anchor{
    margin-bottom: 0 !important;
}

/* Paramètres › Paiement (retour client) : 16px entre les champs, dans les deux sens, et rien
   sous le dernier — la gouttière de la carte (24) l'entoure comme elle entoure le reste. */
.settings-fields{
    display: flex;
    flex-direction: column;
    gap: var(--sp-space-4);
}

.settings-fields .form-floating,
.settings-fields .mb-3,
.settings-fields .row > [class*="col"] > div{
    margin-bottom: 0 !important;
}

/* --- Remises de quantité aux boutons + / − (retour client d'octobre) ----------------------- */
/* Des lignes plus basses : la pilule et deux disques de 32px, plus de champ à saisir. */
[data-controller~="tier-stepper"] .tier-row{
    padding-top: 10px;
    padding-bottom: 10px;
}

.tier-stepper{
    display: inline-flex;
    gap: var(--sp-space-2);
}

.tier-stepper-btn{
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    padding: 0;
    border: 0;
    border-radius: var(--sp-radius-full);
    background-color: #D9D9D9;
    color: var(--sp-color-text-default);
}

.tier-stepper-btn:hover:not(:disabled),
.tier-stepper-btn:focus-visible{
    background-color: var(--sp-color-border-cream);
}

/* À la borne, le disque s'éteint : blanc, glyphe gris clair (maquette « 50 % de remise ») */
.tier-stepper-btn:disabled{
    background-color: var(--sp-color-bg-surface);
    color: #D1D1D1;
}

/* Sans remise, la pilule s'efface d'un cran : elle dit 0 %, elle ne promet rien */
.deal-pill.deal-pill--none{
    background-color: var(--sp-color-bg-surface);
    color: var(--sp-color-text-muted);
}

/* --- Dépôt › Mes évènements enregistrés (retour client d'octobre, maquette) ----------------- */
/* « Publier mes photos » à la hauteur des tags de la tuile (24px), 13/16 medium et « + » de 14
   (maquette EVENT_SELECT). */
.event-rail-section--in-card .event-highlighted-action .btn-marketing{
    display: inline-flex;
    align-items: center;
    gap: 4px;
    height: 24px;
    min-height: 24px;
    padding: 0 8px;
    border-radius: var(--sp-radius-sm);
    font-size: 13px;
    font-weight: 500;
    line-height: 16px;
    letter-spacing: -0.01em;
}

.event-rail-section--in-card .event-highlighted-action .btn-marketing svg{
    width: 14px;
    height: 14px;
    margin-left: 0 !important;
}

/* --- Dépôt, retours d'octobre (DP5 à DP7) --- */

/* « ajoutés au prix de vente… » en regular : la présentation de l'option, juste dessous, reste
   en medium, et les deux phrases ne se confondent plus. Le supplément garde son 20 bold. */
.upload-flow .bib-fee{
    font-weight: var(--sp-font-weight-prose);
}

/* Le verrou Spicto Pro réduit d'un cran, à la mesure du compteur de photos restantes (13px) :
   même logotype de 11px et sceau de 12 que le widget du dashboard — un seul verrou compact. */
.quota-card .pro-mention,
.upload-flow .pro-mention--compact{
    gap: var(--sp-space-1);
    font-size: var(--sp-font-size-meta);
    line-height: 16px;
}

.quota-card .pro-mention > strong{
    font-size: var(--sp-font-size-meta);
}

.quota-card .pro-lockup,
.upload-flow .pro-mention--compact .pro-lockup{
    gap: 3px;
}

.quota-card .pro-lockup-logotype,
.upload-flow .pro-mention--compact .pro-lockup-logotype{
    height: 11px;
}

.quota-card .pro-lockup-seal svg,
.upload-flow .pro-mention--compact .pro-lockup-seal svg{
    width: 12px;
    height: 12px;
}

.upload-flow .pro-mention--compact .pro-lockup-tier{
    font-size: 10px;
}

/* Widget quota : « Passez à Spicto Pro · Photos illimitées » tient sur UNE ligne jusque dans la
   colonne étroite de 992-1199px (retour client), aux cotes de la maquette DASHBOARD : logo 10px,
   sceau 9, PRO 8px, verrou serré à 1px et point de 2px — c'est ce qui libère la place du logo. */
.quota-card .pro-mention{
    flex-wrap: nowrap;
    white-space: nowrap;
    font-size: 12px;
    line-height: 15px;
    letter-spacing: -0.02em;
}

.quota-card .pro-mention > strong,
.quota-card .pro-mention .pro-mention-claim{
    font-size: 12px;
}

.quota-card .pro-mention .pro-lockup{
    gap: 1px;
}

.quota-card .pro-mention .pro-lockup-logotype{
    height: 10px;
}

.quota-card .pro-mention-dot{
    flex-shrink: 0;
    width: 2px;
    height: 2px;
    border-radius: 50%;
    background-color: #1E1C1A;
}

.quota-card .pro-mention .pro-lockup-seal svg{
    width: 9px;
    height: 9px;
}

.quota-card .pro-mention .pro-lockup-tier{
    height: 12px;
    padding: 0 1px;
    border-width: 1px;
    border-radius: 3px;
    font-size: 8px;
    line-height: 10px;
    letter-spacing: 0.03em;
}

/* --- Dépôt, retours d'octobre (DP8 à DP14) --- */

/* Carte de transfert FIDÈLE À LA MAQUETTE : plus de contour, « Dépôt 4 · journée › album » sur
   une ligne avec la croix en face — un IconButton de 44px la faisait tomber sous le titre —, le
   pourcentage et l'état en gris foncé (#464646), le point médian aéré. Vaut aussi pour les
   dépôts terminés. */
.deposit-transfers .upload-item{
    border: 0;
}

.deposit-transfers .upload-item-title{
    display: block;
    min-width: 0;
}

.deposit-transfers .upload-item-head{
    align-items: flex-start;
}

.deposit-transfers .upload-item-target .summary-chevron{
    margin: 0 4px;
}

.upload-item-abandon{
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    position: relative;
    width: 18px;
    height: 18px;
    padding: 0;
    border: 0;
    background: none;
    color: var(--sp-color-text-default);
}

/* La cible reste confortable sans pousser la ligne : elle déborde, invisible, autour du glyphe. */
.upload-item-abandon::after{
    content: "";
    position: absolute;
    inset: -13px;
}

.deposit-transfers .upload-item-pct,
.deposit-transfers .upload-item-status{
    color: var(--sp-color-text-meta);
}

.deposit-transfers .upload-item-pct{
    font-weight: var(--sp-font-weight-bold);
}

.deposit-transfers .upload-item-status,
.deposit-transfers .upload-item-status--done{
    font-weight: var(--sp-font-weight-title);
    color: var(--sp-color-text-meta);
}

/* « Terminer mes dépôts » : le libellé au milieu des 45px — un <a> ne centre pas son texte dans
   une hauteur imposée comme le fait un <button>, il restait trop haut (retour client). */
.btn.btn-tall{
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

/* Validation du dépôt : la mention d'usage personnel, sous l'engagement, plus petite et en gris
   clair (retour client). */
.upload-flow .deposit-usage-note{
    font-size: var(--sp-font-size-12);
    line-height: 15px;
    color: var(--sp-color-text-muted);
}

/* Fichiers trop lourds : la liste nommée, le poids en vis-à-vis. */
.oversize-list{
    max-height: 220px;
    overflow-y: auto;
    margin: 0;
    padding: 0;
    list-style: none;
    font-size: var(--sp-font-size-meta);
}

.oversize-list li{
    display: flex;
    justify-content: space-between;
    gap: var(--sp-space-3);
    padding: 6px 0;
    border-bottom: var(--sp-border-width-default) solid var(--sp-color-border-on-white);
}

.oversize-name{
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.oversize-size{
    flex-shrink: 0;
    font-weight: var(--sp-font-weight-title);
    color: var(--sp-color-feedback-danger);
}

/* « D'autres photos arrivent ? » puis le partage (maquette, retour client) : le blanc des
   Dialog `done`, la ligne du photographe centrée à la largeur de son contenu, le badge mis en
   avant par un halo orange (0 0 10), moins d'air autour du filet, la réponse qui garde le badge
   en orange et celle qui le retire en gris. */
.modal.dialog--more-photos{
    --bs-modal-bg: var(--sp-color-bg-surface);
    --bs-modal-header-bg: var(--sp-color-bg-surface);
    --bs-modal-border-radius: var(--sp-radius-2xl);
    --bs-modal-inner-border-radius: var(--sp-radius-2xl);
}

@media (min-width: 768px) {
    .modal.dialog--more-photos{
        --bs-modal-width: 509px;
    }
}

.dialog--more-photos .dialog-body{
    gap: var(--sp-space-3);
}

.dialog--more-photos .share-link{
    background-color: var(--sp-color-bg-sunken);
    border-color: transparent;
}

.dialog--more-photos .dialog-preview{
    display: flex;
    justify-content: center;
    padding: var(--sp-space-1) 0;
    background: none;
}

.dialog-preview-profile{
    display: inline-flex;
    align-items: center;
    gap: var(--sp-space-3);
    max-width: 100%;
    padding: var(--sp-space-2) var(--sp-space-4) var(--sp-space-2) var(--sp-space-2);
    border-radius: var(--sp-radius-lg);
    background-color: var(--sp-color-bg-sunken);
}

.dialog-preview-profile .list-item-meta{
    display: flex;
    align-items: center;
    flex-wrap: wrap;
}

.badge-glow{
    box-shadow: 0 0 10px var(--sp-color-orange-400);
}

.dialog--more-photos .dialog-rule{
    margin: var(--sp-space-1) 0;
}

.dialog-stack-actions{
    display: flex;
    flex-direction: column;
    gap: var(--sp-space-3);
}

.dialog-stack-actions .btn{
    min-height: 48px;
    border-radius: var(--sp-radius-md);
    font-weight: var(--sp-font-weight-title);
}

.btn-quiet{
    --bs-btn-bg: var(--sp-color-grey-300);
    --bs-btn-border-color: var(--sp-color-grey-300);
    --bs-btn-color: var(--sp-color-text-meta);
    --bs-btn-hover-bg: var(--sp-color-grey-300);
    --bs-btn-hover-border-color: var(--sp-color-grey-300);
    --bs-btn-hover-color: var(--sp-color-text-default);
    --bs-btn-active-bg: var(--sp-color-grey-300);
    --bs-btn-active-border-color: var(--sp-color-grey-300);
    --bs-btn-active-color: var(--sp-color-text-default);
}

/* La photo de la fenêtre de partage (maquette, 508 × 192 au coin de 16). */
.dialog-share-photo{
    display: block;
    width: 100%;
    height: auto;
    aspect-ratio: 508 / 192;
    object-fit: cover;
    border-radius: var(--sp-radius-lg);
}

/* Carte de l'évènement du dépôt : la date reste entière, le libellé de retour se tronque à sa
   place (fiche event-card-highlighted : « le libellé cède avant la carte »). */
.event-aside-badges{
    flex-shrink: 0;
}

.event-aside-badges .badge{
    overflow: visible;
}

/* « · prix de l'album » : l'onglet courant a son propre prix dans le dépôt (monétisation par album). */
.deposit-info-note{
    font-weight: var(--sp-font-weight-body);
    color: var(--sp-color-text-muted);
}

/* « Appliquer ce prix » : un libellé de champ, pas le titre de la fenêtre (Bootstrap grossit
   la légende d'un fieldset). */
.price-scope legend{
    float: none;
    margin-bottom: var(--sp-space-2);
    font-size: var(--sp-font-size-label);
    font-weight: var(--sp-font-weight-title);
}

/* Texte rédigé au back-office (articles) : une image insérée par adresse garde la largeur choisie
   sans jamais dépasser la colonne, sa légende reste discrète. */
.rich-content figure.attachment { margin: var(--sp-space-6) 0; }
.rich-content img { max-width: 100%; height: auto; border-radius: 8px; }
.rich-content figcaption { margin-top: var(--sp-space-2); font-size: 13px; color: var(--sp-color-text-muted); }
.rich-content figcaption:empty { display: none; }

/* Titres 1 à 3 de l'éditeur (CGV, CGU, articles) : sous le titre de la page, jamais à sa taille. */
.rich-content h1, .rich-content h2, .rich-content h3 { font-weight: 600; letter-spacing: -0.02em; margin: var(--sp-space-8) 0 var(--sp-space-2); }
.rich-content h1 { font-size: var(--sp-font-size-20); line-height: 24px; }
.rich-content h2 { font-size: var(--sp-font-size-16); line-height: 19px; margin-top: var(--sp-space-6); }
.rich-content h3 { font-size: var(--sp-font-size-15); line-height: 18px; margin-top: var(--sp-space-5); }
.rich-content > :first-child { margin-top: 0; }

/* Bouton d'envoi de fichier en attente (retour client du 27/10) : il le dit, et ne se reclique pas. */
label.btn.is-busy{
    pointer-events: none;
    opacity: .8;
}

/* Mes évènements : recherche par nom ou ville (retour client du 27/10). */
.events-search{
    position: relative;
    width: 220px;
}
/* Même gabarit que les chips voisines : 34px de haut, coins de 12px, texte à 14px. */
.photo-filter-bar .events-search .form-control{
    height: 34px;
    min-height: 34px;
    padding: 0 12px 0 36px;
    border-radius: 12px;
    font-size: 14px;
}
.events-search-icon{
    position: absolute;
    top: 50%;
    left: 14px;
    transform: translateY(-50%);
    pointer-events: none;
}
@media (max-width: 991.98px){
    .events-search{ width: 100%; }
}

/* Écrire aux abonnés (retour du 27/10) : recherche d'évènement à suggestions, relecture, historique dépliable. */
.event-picker-field{
    position: relative;
}

.event-picker-list{
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    right: 0;
    z-index: 20;
    max-height: 340px;
    overflow-y: auto;
    margin: 0;
    padding: 6px;
    list-style: none;
    background-color: var(--sp-color-bg-surface, #FFFFFF);
    border: 1px solid #E3E3E3;
    border-radius: 16px;
    box-shadow: 0 4px 20px rgba(0, 0, 0, .12);
}

.event-picker-option{
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 8px;
    border-radius: 10px;
    cursor: pointer;
}

.event-picker-option:hover,
.event-picker-option.is-active{
    background-color: #F5F3EB;
}

.event-picker-option img,
.newsletter-review-event img{
    flex-shrink: 0;
    border-radius: 8px;
    object-fit: cover;
}

.event-picker-name{
    display: block;
    font-weight: 600;
    color: #1E1C1A;
}

.event-picker-meta,
.newsletter-review-meta{
    font-size: 13px;
    color: #757575;
}

.event-picker-empty{
    padding: 8px;
    font-size: 13px;
    color: #757575;
}

.newsletter-review{
    padding: 16px;
    border: 1px solid #E3E3E3;
    border-radius: 16px;
}

.newsletter-review-event{
    display: flex;
    align-items: center;
    gap: 12px;
    padding-bottom: 12px;
    margin-bottom: 12px;
    border-bottom: 1px solid #E3E3E3;
}

.newsletter-review-message{
    white-space: normal;
    overflow-wrap: anywhere;
    color: #1E1C1A;
}

.newsletter-sent summary{
    list-style: none;
    cursor: pointer;
}

.newsletter-sent summary::-webkit-details-marker{
    display: none;
}

.newsletter-sent .chevron-toggle{
    transform: rotate(180deg);
    transition: transform .2s;
}

.newsletter-sent[open] .chevron-toggle{
    transform: none;
}

/* Statistiques Pro (retour du 27/10) : onglets année puis mois, graphiques, détail en grille. */
.stats-tabs{
    display: flex;
    gap: 8px;
    overflow-x: auto;
    scrollbar-width: none;
}

.stats-tab{
    flex-shrink: 0;
    padding: 6px 12px;
    border-radius: 999px;
    background-color: #EEECE6;
    color: #464646;
    font-size: 14px;
    font-weight: 500;
    text-decoration: none;
}

.stats-tab:hover{
    color: #1E1C1A;
}

.stats-tab.is-active{
    background-color: #1E1C1A;
    color: #FFFFFF;
}

.stats-tabs--months .stats-tab{
    padding: 4px 10px;
    font-size: 13px;
}

.stats-chart-head{
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    margin-bottom: 8px;
}

.stats-chart-head .sec-header-title{
    margin-right: auto;
}

.stats-chart-total{
    padding: 2px 8px;
    border-radius: 6px;
    font-size: 12px;
    font-weight: 600;
}

.stats-chart-total--sales{
    background-color: #EEF2E8;
    color: #4E6339;
}

.stats-chart-total--ads,
.stats-chart-total--views{
    background-color: #FDEFE1;
    color: #9A5A1E;
}

.stats-row{
    display: grid;
    grid-template-columns: minmax(0, 2fr) repeat(4, minmax(0, 1fr));
    gap: 12px;
    padding: 12px 0;
    border-top: 1px solid #EEECE6;
    font-size: 14px;
}

.stats-row > span:not(:first-child){
    text-align: right;
    font-variant-numeric: tabular-nums;
}

.stats-row--head{
    border-top: 0;
    padding-top: 0;
    font-size: 12px;
    font-weight: 600;
    color: #757575;
}

.stats-row--total{
    font-weight: 700;
    border-top-color: #1E1C1A;
}

.stats-row-label{
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.stats-row-label a{
    color: #1E1C1A;
    font-weight: 600;
}

@media (max-width: 575.98px) {
    .stats-row{
        grid-template-columns: minmax(0, 1fr) repeat(2, auto);
    }

    .stats-row > span:nth-child(2),
    .stats-row > span:nth-child(4){
        display: none;
    }
}

/* Paramètres › Spicto Pro (retour du 27/10, visuels 47-49) : groupe de navigation, statut, carte, factures. */
.settings-nav-group{
    display: flex;
    align-items: center;
    gap: var(--sp-space-3);
    margin: var(--sp-space-2) 0 0;
    padding: var(--sp-space-3) var(--sp-space-4);
    font-weight: var(--sp-font-weight-title);
    color: var(--sp-color-text-default);
}

.settings-nav-item--child{
    margin-left: var(--sp-space-6);
}

.pro-status{
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 2px 10px;
    border-radius: 8px;
    font-size: 14px;
    font-weight: 600;
}

.pro-status--active{
    background-color: #FDE3D3;
    color: #E8642C;
}

.pro-status--ending,
.pro-status--failed{
    background-color: #FBD9D9;
    color: #D23F3F;
}

.pro-status-lead{
    font-weight: 600;
    color: #1E1C1A;
}

.pro-status-date{
    color: #E8642C;
}

.pro-card{
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 6px 10px;
    border-radius: 8px;
    background-color: #EEECE6;
    color: #464646;
    font-size: 14px;
    font-weight: 500;
}

.pro-card--failed{
    background-color: #FBD9D9;
    color: #D23F3F;
}

/* Plus large, pour que les avantages tiennent sur une ligne ; la croix sans fond (retour du 29/10). */
.pro-cancel-dialog .modal-dialog{
    max-width: min(640px, calc(100% - var(--sp-space-4) * 2));
}

.pro-cancel-dialog .btn-close,
.pro-cancel-dialog .btn-close:hover{
    background-color: transparent;
}

.pro-cancel-losses{
    padding: 20px;
    border-radius: 16px;
    background-color: #F5F3EB;
}

.pro-cancel-list{
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 10px 16px;
    margin: 0;
    padding: 0;
    list-style: none;
    font-size: 14px;
}

.pro-cancel-list li{
    display: flex;
    align-items: center;
    gap: 8px;
}

.pro-cancel-list svg{
    flex-shrink: 0;
    color: #E8642C;
}

.btn.pro-cancel-keep{
    border-color: #E8642C;
    color: #E8642C;
}

.pro-invoice-row{
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px 0;
    border-top: 1px solid #EEECE6;
}

/* Le filet suit les lignes visibles : la première de chaque année n'en porte pas. */
.pro-history-row:not([hidden]) ~ .pro-history-row:not([hidden]){
    border-top: var(--bs-border-width) var(--bs-border-style) var(--bs-border-color);
}

.pro-invoice-glyph{
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: 32px;
    height: 32px;
    border-radius: 8px;
    background-color: #EEECE6;
    color: #757575;
}

.pro-invoice-meta{
    font-size: 13px;
    color: #757575;
}

.pro-invoice-meta a{
    color: #1E1C1A;
    font-weight: 600;
}

.btn.pro-cancel-open{
    display: inline-flex;
    align-self: flex-start;
    align-items: center;
    gap: 8px;
}

/* Souscription Spicto Pro (retour du 27/10) : quatre étapes repliables, recherche d'entreprise, récapitulatif. */
.signup-step-summary{
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    font-size: 14px;
    color: #464646;
}

.signup-step-label{
    margin-right: 8px;
    font-weight: 600;
    color: #1E1C1A;
}

.signup-step-actions{
    display: none;
}

.pro-signup.is-stepped .signup-step-actions{
    display: flex;
    justify-content: flex-end;
    margin-top: 24px;
}

.signup-plans,
.signup-holder{
    display: grid;
    gap: 12px;
}

.signup-plan,
.signup-holder-option{
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 16px;
    border: 1px solid #D1D1D1;
    border-radius: 16px;
    cursor: pointer;
}

.signup-plan:has(:checked),
.signup-holder-option:has(:checked){
    border-color: #1E1C1A;
    box-shadow: inset 0 0 0 1px #1E1C1A;
}

.signup-plan .form-check-input,
.signup-holder-option .form-check-input{
    flex-shrink: 0;
    margin: 0;
}

.signup-plan-text{
    display: flex;
    flex-direction: column;
    flex-grow: 1;
}

.signup-plan-name{
    font-weight: 600;
    color: #1E1C1A;
}

.signup-plan-saving{
    margin-left: 6px;
    padding: 1px 8px;
    border-radius: 999px;
    background-color: #FF6204;
    color: #FFFFFF;
    font-size: 12px;
    font-weight: 600;
}

.signup-plan-cadence,
.signup-plan-equivalent{
    font-size: 13px;
    color: #757575;
}

.signup-plan-price{
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    white-space: nowrap;
}

.signup-plan-price strong{
    font-size: 18px;
    color: #1E1C1A;
}

.signup-notice{
    display: flex;
    gap: 8px;
    padding: 12px 16px;
    border-radius: 12px;
    background-color: #F5F3EB;
    font-size: 13px;
    color: #464646;
}

.signup-notice svg{
    flex-shrink: 0;
    margin-top: 2px;
}

.signup-subtitle{
    margin-bottom: 12px;
    font-size: 16px;
    font-weight: 600;
}

.signup-company-anchor{
    position: relative;
}

.signup-company-list{
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    right: 0;
    z-index: 20;
    max-height: 320px;
    overflow-y: auto;
    padding: 6px;
    background-color: #FFFFFF;
    border: 1px solid #E3E3E3;
    border-radius: 16px;
    box-shadow: 0 4px 20px rgba(0, 0, 0, .12);
}

.signup-company-option{
    display: flex;
    flex-direction: column;
    width: 100%;
    padding: 8px 10px;
    border: 0;
    border-radius: 10px;
    background: none;
    text-align: left;
}

.signup-company-option:hover,
.signup-company-option.is-active{
    background-color: #F5F3EB;
}

.signup-company-option small{
    color: #757575;
}

.signup-company-status{
    margin: 8px 0 12px;
    font-size: 13px;
    color: #757575;
}

.signup-error{
    margin-top: 4px;
    font-size: 13px;
    color: #D23F3F;
}

.signup-recap{
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 12px 24px;
    margin: 0 0 24px;
}

.signup-recap-row.is-wide{
    grid-column: 1 / -1;
}

.signup-recap-row dt{
    font-size: 12px;
    font-weight: 500;
    color: #757575;
}

.signup-recap-row dd{
    margin: 0;
    font-weight: 600;
    color: #1E1C1A;
    overflow-wrap: anywhere;
}

.signup-recap-edit{
    display: flex;
    align-items: flex-end;
    justify-content: flex-end;
}

.signup-terms{
    padding: 16px;
    border-radius: 16px;
    background-color: #F5F3EB;
    font-size: 13px;
    color: #464646;
}

.signup-terms-content{
    max-height: 90px;
    overflow: hidden;
    -webkit-mask-image: linear-gradient(to bottom, #000 55%, transparent);
    mask-image: linear-gradient(to bottom, #000 55%, transparent);
}

.signup-terms-content.text-truncate-expanded{
    max-height: none;
    -webkit-mask-image: none;
    mask-image: none;
}

@media (max-width: 575.98px) {
    .signup-recap{
        grid-template-columns: minmax(0, 1fr);
    }
}

/* Présentation de l'offre (retour du 27/10, visuels 40-43) : étiquettes en verre « Liquid Glass »,
   fondu élargi vers le texte, badge du client avec son ombre, bloc Paiement aux marges égales. */
.pro-feature-tag{
    background-color: rgba(255, 255, 255, .18);
    border: 1px solid rgba(255, 255, 255, .45);
    backdrop-filter: blur(14px) saturate(160%);
    -webkit-backdrop-filter: blur(14px) saturate(160%);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .5), 0 8px 32px rgba(0, 0, 0, .18);
}

.pro-feature-visual::after{
    background: linear-gradient(to right, transparent 20%, var(--sp-color-bg-surface) 100%);
}

.pro-feature--right .pro-feature-visual::after{
    background: linear-gradient(to left, transparent 20%, var(--sp-color-bg-surface) 100%);
}

img.pro-feature-seal{
    display: block;
    filter: none;
}

.pro-feature-quota-seal{
    display: inline-block;
    vertical-align: -3px;
}

.pro-aside-title:has(+ .pro-payment) + .pro-payment,
.pro-payment{
    padding: var(--sp-space-4);
}

@media (max-width: 767.98px) {
    .pro-feature-visual::after,
    .pro-feature--right .pro-feature-visual::after{
        background: linear-gradient(to bottom, transparent 30%, var(--sp-color-bg-surface) 100%);
    }
}

/* Prix d'un abonné Pro au dépôt (retour du 27/10) : « − / + » sans saisie, commission dessous. */
.price-stepper{
    display: inline-flex;
    align-items: center;
    gap: 8px;
}

.price-stepper-button{
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    padding: 0;
    border: 1px solid #D1D1D1;
    border-radius: 12px;
    background-color: #FFFFFF;
}

.price-stepper .price-stepper-value{
    width: 96px;
    text-align: center;
    font-size: 18px;
    font-weight: 600;
    background-color: #FFFFFF;
    pointer-events: none;
}

.price-stepper-unit{
    margin-left: -4px;
    font-weight: 600;
}

.price-commission{
    font-size: 13px;
    font-weight: 600;
    color: #464646;
}

/* Widget « Photos payantes » d'un abonné Pro (retour du 27/10, visuel 36). */
.quota-progress--unlimited{
    background-color: #EEECE6;
}

.quota-progress--unlimited .progress-bar{
    width: 66% !important;
    background: linear-gradient(to right, #FF6204, rgba(255, 98, 4, 0));
}

/* Écran de repli administrable (BO-14 / BO-15) : même règles que
   templates/_partials/unavailable_screen_style.html.twig, en ligne dans la page d'erreur. */
.unavailable-screen{
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    min-height: 100%;
    padding: 32px;
    overflow: hidden;
    text-align: center;
    color: var(--unavailable-color, #FFFFFF);
    background: var(--unavailable-bg-image, none) center / cover no-repeat, var(--unavailable-bg, #1E1C1A);
}

.unavailable-screen-overlay{
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: contain;
    pointer-events: none;
}

.unavailable-screen-body{
    position: relative;
    max-width: 560px;
}

.unavailable-screen-title{
    margin: 0 0 12px;
    color: inherit;
    font-size: 32px;
    font-weight: 700;
    line-height: 1.2;
}

.unavailable-screen-text{
    margin: 0 0 24px;
    font-size: 16px;
    line-height: 1.5;
}

.unavailable-screen-button{
    display: inline-block;
    padding: 12px 24px;
    border: 1px solid currentColor;
    border-radius: 999px;
    color: inherit;
    font-weight: 600;
    text-decoration: none;
}

.unavailable-screen-button:hover{
    color: inherit;
    opacity: .85;
}

/* Vignette de grille dont l'image n'a pas chargé (photo_fallback.js) */
.unavailable-screen--compact{
    position: absolute;
    inset: 0;
    padding: 12px;
}

.unavailable-screen--compact .unavailable-screen-text{
    margin: 0;
    font-size: 12px;
}

.photo-unavailable-page{
    min-height: 60vh;
    display: flex;
}
