/*
 * L'application cartographique.
 *
 * ── CE QUE CETTE FEUILLE NE FAIT PAS ──────────────────────────────────────
 *
 * Elle n'invente aucune couleur. Toutes viennent des jetons du Design System
 * chargés par la feuille vendorisée : le thème « maps », le mode sombre et la
 * prochaine version des jetons s'appliquent donc à cette page sans qu'elle ait
 * à le savoir. Une valeur hexadécimale ici serait une valeur qui cesse de
 * suivre le jour où le Design System change.
 *
 * ── ET POURQUOI ELLE EST SÉPARÉE DE maps.css ──────────────────────────────
 *
 * `maps.css` habille des PAGES DE CONTENU — le laboratoire, le diagnostic —
 * qui coulent dans une colonne. L'application, elle, occupe l'écran et
 * superpose des panneaux à une carte. Mélanger les deux ferait porter à chaque
 * page de contenu le poids d'une mise en page dont elle n'a pas besoin.
 *
 * ── LE PRINCIPE DE LA 0.9.0 : LA CARTE EST L'ÉCRAN ────────────────────────
 *
 * La 0.8.0 posait la carte DANS une page : un en-tête pleine largeur, une
 * figure encadrée, des panneaux qui poussaient le reste. Chaque bande fixe
 * était du territoire en moins, et l'ensemble se lisait comme un banc d'essai
 * parce qu'il en avait la structure.
 *
 * Ici la carte occupe la fenêtre entière, et **tout le reste flotte**. Aucun
 * élément d'interface ne réduit la surface cartographique : ils se posent
 * dessus, se replient, et rendent la place quand on ne les regarde pas.
 */

/* ── LE CADRE ─────────────────────────────────────────────────────────── */

:root {
    /*
     * ── LA HAUTEUR DE L'EN-TÊTE FLOTTANT ──────────────────────────────────
     *
     * Tout ce qui flotte en haut de la carte s'en écarte : la recherche, le
     * rail d'outils, les commandes du moteur. Cette valeur était écrite trois
     * fois en dur — `3.75rem` — et c'est ainsi qu'elle a fini par mentir.
     *
     * Mesuré sur un écran de 375 px : l'en-tête passe à DEUX lignes — la marque
     * puis la navigation —, occupe 104 px, et la recherche posée à 60 px lui
     * rentrait dedans sur 36 px de haut. Une constante ne peut pas suivre un
     * contenu qui se replie.
     *
     * Elle reste donc une valeur par défaut RAISONNABLE, et le navigateur la
     * remplace par la hauteur réellement mesurée — voir `tibius-app.js`, qui
     * observe l'en-tête. La page est juste sans JavaScript, et exacte avec.
     */
    --app-header-h: 3.25rem;
}

body[data-layout="app"] {
    /*
     * `100dvh` et non `100vh` : sur un téléphone, la barre d'adresse se
     * rétracte au défilement et `100vh` compte une hauteur que l'écran n'a pas.
     * La différence est de l'ordre de 60 px, et elle se voit — c'est
     * exactement la hauteur de la feuille montante qui passait sous le pli.
     */
    height: 100dvh;
    overflow: hidden;
    margin: 0;
}

/*
 * L'en-tête du site FLOTTE au lieu de pousser.
 *
 * L'identité et le compte restent dans un cadre compact Précision. La carte
 * demeure plein écran derrière les commandes ; la hauteur mesurée de ce cadre
 * réserve la place de la recherche, y compris sur téléphone.
 */
body[data-layout="app"] .site-header {
    position: fixed;
    inset-block-start: 0;
    inset-inline: 0;
    z-index: 6;
    margin: 0;
    padding: var(--tds-space-2) var(--tds-space-4);
    padding-block-start: max(var(--tds-space-2), env(safe-area-inset-top));
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--tds-space-3);
    /* Le repli garde la connexion accessible à 200 % texte. L'observateur
     * de hauteur dégage la recherche lorsque l'en-tête gagne une ligne. */
    flex-wrap: wrap;
    min-width: 0;
    /* L'identité appartient au cadre ; le territoire garde ses couleurs métier. */
    border: 0;
    border-block-end: var(--tds-border-width-accent) solid var(--tds-brand-primary);
    background: var(--tds-brand-subtle);
    color: var(--tds-text-primary);
    pointer-events: none;
}

body[data-layout="app"] .site-header > * {
    pointer-events: auto;
}

/*
 * Ce que l'en-tête flottant contient : l'identité à gauche, puis — toujours en
 * dernier — la marque d'environnement et la zone compte `tds-account` de la
 * structure commune. Seule la BOÎTE est propre à la carte.
 */
.site-header__brand {
    display: flex;
    align-items: center;
    gap: var(--tds-space-2);
    margin: 0;
    font-size: var(--tds-font-size-body-large);
}

.site-header__home {
    display: inline-flex;
    align-items: center;
    gap: var(--tds-space-2);
    color: inherit;
    text-decoration: none;
}

.site-header__home:focus-visible {
    outline: var(--tds-focus-width) solid var(--tds-border-focus);
    outline-offset: var(--tds-focus-offset);
    border-radius: var(--tds-radius-role-control);
}

.site-header__lockup {
    display: block;
    flex: none;
    width: auto;
    height: var(--tds-lockup-height-sm);
    max-width: 100%;
}

.site-header__end {
    display: flex;
    flex-wrap: wrap;
    max-width: 100%;
    flex: none;
    align-items: center;
    gap: var(--tds-space-3);
    margin-inline-start: auto;
}

.site-header__end .tds-account__signin {
    max-width: 100%;
    white-space: normal;
}

/*
 * « Signaler un problème » — 0.30.0. Discret : un lien de l'en-tête, pas un
 * bouton d'action ; la cible tactile du Design System reste pleine.
 */
.site-header__report {
    display: inline-flex;
    align-items: center;
    gap: var(--tds-space-1);
    justify-content: center;
    min-height: var(--tds-touch-target-web);
    min-width: var(--tds-touch-target-web);
    padding: 0 var(--tds-space-2);
    border-radius: var(--tds-radius-role-control);
    color: var(--tds-text-secondary);
    font-size: var(--tds-font-size-body-small);
    text-decoration: none;
    white-space: nowrap;
    /* Collé au nom du produit : l'en-tête reste « nom à gauche, compte à droite ». */
    margin-inline-end: auto;
}
.site-header__report:hover { background: var(--tds-action-ghost-hover); color: var(--tds-text-primary); }
.site-header__report:focus-visible {
    outline: var(--tds-focus-width) solid var(--tds-border-focus);
    outline-offset: var(--tds-focus-offset);
}

.app-shell {
    height: 100dvh;
    margin: 0;
    padding: 0;
    max-width: none;
}

.app {
    position: relative;
    height: 100%;
    display: grid;
    /*
     * Une seule cellule, et tout le monde dedans. C'est ce qui permet à la
     * carte d'occuper le fond et aux commandes de se placer par rapport à
     * l'écran plutôt que les unes après les autres.
     */
    grid-template: 1fr / 1fr;
    /*
     * PAS d'`isolation: isolate` ici.
     *
     * Elle paraissait prudente — enfermer les `z-index` de l'application dans
     * leur propre contexte — et elle produisait exactement l'inverse de ce
     * qu'on voulait : le contexte entier passait alors SOUS l'en-tête fixe du
     * site, et l'en-tête du panneau se retrouvait recouvert par la navigation.
     *
     * Les couches de cette page se rangent donc dans le contexte racine, où
     * l'en-tête (6) et les panneaux (7) se comparent réellement.
     */
}

.app > * {
    grid-area: 1 / 1;
}

/* ── LA CARTE ─────────────────────────────────────────────────────────── */

.app__map {
    position: relative;
    margin: 0;
    padding: 0;
    height: 100%;
    border: 0;
    border-radius: 0;
    background: var(--tds-surface-sunken);
}

.app__canvas {
    height: 100%;
    width: 100%;
    border: 0;
    border-radius: 0;
}

/*
 * Les commandes du moteur, réalignées sur le rail.
 *
 * MapLibre pose ses boutons en haut à droite. Le rail d'outils les prolonge
 * vers le bas : les deux forment UNE colonne, et non deux familles de boutons
 * qui se disputent le coin. L'habillage est donc repris ici pour que la
 * frontière entre « ce que le moteur fournit » et « ce que Maps ajoute » ne se
 * voie pas.
 */
.app .maplibregl-ctrl-top-right {
    inset-block-start: calc(env(safe-area-inset-top) + var(--app-header-h) + var(--tds-space-2));
    inset-inline-end: var(--tds-space-3);
}

.app .maplibregl-ctrl-group {
    /* Le moteur pose une marge de 10 px qui lui est propre. Sans cette remise
     * à zéro, sa colonne de boutons est décalée de 10 px par rapport au rail,
     * et les deux ne forment plus une seule colonne mais deux presque
     * alignées — ce qui se voit davantage qu'un franc décalage. */
    margin: 0;
    border-radius: var(--tds-radius-lg);
    box-shadow: var(--tds-elevation-medium);
    border: var(--tds-border-width-default) solid var(--tds-border-default);
    background: var(--tds-surface-default);
    overflow: hidden;
}

.app .maplibregl-ctrl-group button {
    width: 2.75rem;
    height: 2.75rem;
}

.app .maplibregl-ctrl-bottom-left {
    inset-block-end: calc(env(safe-area-inset-bottom) + var(--app-attribution-h, 2.25rem));
}

/*
 * L'attribution vit DANS la figure, et non dans la grille de l'application.
 *
 * Ce n'est pas un détail de rangement : elle est rendue par le serveur à
 * l'intérieur du `<figure>`, avant tout script, pour qu'une carte dont le
 * moteur tombe garde sa mention. Elle se positionne donc par rapport à la
 * figure, et non par rapport à l'écran.
 */
.app__attribution {
    position: absolute;
    inset-block-end: 0;
    inset-inline-start: 0;
    z-index: 3;
    margin: 0;
    padding: var(--tds-space-1) var(--tds-space-3);
    padding-inline-start: max(var(--tds-space-3), env(safe-area-inset-left));
    padding-block-end: max(var(--tds-space-1), env(safe-area-inset-bottom));
    max-width: min(100%, 46rem);
    background: color-mix(in srgb, var(--tds-surface-default) 88%, transparent);
    color: var(--tds-text-muted);
    font-size: var(--tds-font-size-caption);
    line-height: var(--tds-line-height-tight);
    border-start-end-radius: var(--tds-radius-md);
    pointer-events: auto;
}

.app__attribution a {
    color: inherit;
}

/*
 * La légende d'une couche raster posée (0.24.0). Un seul bandeau, en bas à
 * droite, au-dessus de l'attribution ; une seule légende à la fois ; repliable.
 * L'image du producteur garde sa taille : une échelle réduite deviendrait
 * illisible, elle défile donc horizontalement sur un écran étroit.
 * Candidate au Design System (docs/legendes.md) — pas un composant de celui-ci.
 */
.app__legend {
    position: absolute;
    /* Au-dessus de l'attribution, quelle que soit sa hauteur : elle passe sur deux
       lignes dès que la vue cite trois producteurs (mesuré : 35 px). */
    inset-block-end: calc(var(--app-attribution-block, var(--tds-space-6)) + var(--tds-space-2));
    inset-inline-end: max(var(--tds-space-3), env(safe-area-inset-right));
    z-index: 3;
    display: grid;
    gap: var(--tds-space-1);
    max-width: min(calc(100% - 2 * var(--tds-space-3)), 56rem);
    padding: var(--tds-space-2) var(--tds-space-3);
    background: color-mix(in srgb, var(--tds-surface-default) 94%, transparent);
    border: var(--tds-border-width-default) solid var(--tds-border-default);
    border-radius: var(--tds-radius-md);
    box-shadow: var(--tds-elevation-low);
    font-size: var(--tds-font-size-caption);
    line-height: var(--tds-line-height-tight);
    color: var(--tds-text-primary);
}

.app__legend[hidden] {
    display: none;
}

.app__legend-head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--tds-space-2);
}

.app__legend-title {
    margin: 0;
    font-weight: var(--tds-font-weight-semibold);
}

.app__legend-choices {
    display: flex;
    flex-wrap: wrap;
    gap: var(--tds-space-1);
}

.app__legend-choice,
.app__legend-toggle {
    min-height: 1.75rem;
    padding: 0 var(--tds-space-2);
    border: var(--tds-border-width-default) solid var(--tds-border-default);
    border-radius: var(--tds-radius-full);
    background: var(--tds-surface-default);
    color: var(--tds-text-primary);
    font: inherit;
    cursor: pointer;
}

.app__legend-choice[aria-pressed="true"] {
    background: var(--tds-brand-primary);
    border-color: var(--tds-brand-primary);
    color: var(--tds-brand-on-primary);
}

.app__legend-toggle {
    margin-inline-start: auto;
}

.app__legend-choice:focus-visible,
.app__legend-toggle:focus-visible,
.app__legend-scroll:focus-visible {
    outline: var(--tds-focus-width) solid var(--tds-border-focus);
    outline-offset: var(--tds-focus-offset);
}

.app__legend-scroll {
    overflow-x: auto;
    max-width: 100%;
}

.app__legend-image {
    display: block;
    max-width: none;
    height: auto;
    /* L'image du producteur est un PNG RGB opaque, fond blanc compris (mesuré) :
       elle reste lisible en thème sombre sans que Maps lui en ajoute un. */
}

.app__legend-caption,
.app__legend-source {
    margin: 0;
    color: var(--tds-text-muted);
}

.app__fallback {
    position: absolute;
    inset-block-start: 50%;
    inset-inline: var(--tds-space-4);
    transform: translateY(-50%);
    z-index: 5;
    max-width: 28rem;
    margin-inline: auto;
}

/* ── LA RECHERCHE ─────────────────────────────────────────────────────── */

.app__search {
    position: relative;
    z-index: 2;
    pointer-events: auto;
}

.app__search-icon {
    position: absolute;
    inset-block-start: 0.9rem;
    inset-inline-start: var(--tds-space-3);
    color: var(--tds-text-muted);
    pointer-events: none;
}

.app__search-input {
    width: 100%;
    /* La cible tactile du Design System, et non une hauteur choisie à l'œil. */
    min-height: var(--tds-touch-target-web);
    padding: var(--tds-space-2) var(--tds-space-3);
    padding-inline-start: calc(var(--tds-space-3) * 2 + 18px);
    border: var(--tds-border-width-default) solid var(--tds-border-default);
    border-radius: var(--tds-radius-full);
    background: var(--tds-surface-default);
    color: var(--tds-text-primary);
    font: inherit;
    font-size: var(--tds-font-size-body);
    box-shadow: var(--tds-elevation-medium);
}

.app__search-input::placeholder {
    color: var(--tds-text-muted);
}

.app__search-input:focus-visible {
    outline: var(--tds-focus-width) solid var(--tds-border-focus);
    outline-offset: var(--tds-focus-offset);
}

.app__suggestions {
    position: absolute;
    inset-inline: 0;
    inset-block-start: calc(100% + var(--tds-space-2));
    margin: 0;
    padding: var(--tds-space-1);
    list-style: none;
    max-height: 60vh;
    overflow-y: auto;
    background: var(--tds-surface-default);
    border: var(--tds-border-width-default) solid var(--tds-border-default);
    border-radius: var(--tds-radius-lg);
    box-shadow: var(--tds-elevation-high);
}

.app__suggestion {
    display: flex;
    flex-direction: column;
    gap: 0.1rem;
    padding: var(--tds-space-2) var(--tds-space-3);
    border-radius: var(--tds-radius-md);
    cursor: pointer;
    min-height: var(--tds-touch-target-web);
    justify-content: center;
}

.app__suggestion:hover,
.app__suggestion:focus-visible {
    background: var(--tds-action-ghost-hover);
    outline: none;
}

.app__suggestion--empty {
    cursor: default;
    color: var(--tds-text-muted);
    font-size: var(--tds-font-size-body-small);
}

.app__suggestion-label {
    font-weight: var(--tds-font-weight-medium);
    display: flex;
    align-items: baseline;
    gap: var(--tds-space-2);
    justify-content: space-between;
}

/*
 * La NATURE du résultat — adresse, rue, commune, lieu.
 *
 * Elle est à droite et discrète, parce qu'elle sert à distinguer deux
 * résultats qui portent le même nom : « Namur » la commune et « Namur » la
 * province arrivent tous deux, et rien d'autre ne les sépare à l'œil.
 *
 * Ce n'est PAS une note de qualité. « Adresse » ne veut pas dire « plus
 * exact » — voir Tibius\Maps\Search\ResultKind.
 */
.app__suggestion-kind {
    font-weight: var(--tds-font-weight-regular);
    font-size: var(--tds-font-size-caption);
    color: var(--tds-text-muted);
    white-space: nowrap;
    flex: none;
}

.app__suggestion.is-active {
    background: var(--tds-action-ghost-hover);
}

/*
 * La note de provenance, sous les résultats.
 *
 * Elle dit qui a répondu et ce que ce service reçoit. Elle n'est pas
 * sélectionnable — ce n'est pas un résultat — et la navigation au clavier
 * l'ignore.
 */
.app__suggestion--note {
    cursor: default;
    color: var(--tds-text-muted);
    font-size: var(--tds-font-size-caption);
    line-height: 1.4;
    border-top: var(--tds-border-width-default) solid var(--tds-border-default);
    margin-top: var(--tds-space-1);
    padding-top: var(--tds-space-2);
}

.app__suggestion-sub {
    font-size: var(--tds-font-size-caption);
    color: var(--tds-text-muted);
}

/* ── LE RAIL D'OUTILS ─────────────────────────────────────────────────── */

.app__rail {
    z-index: 5;
    justify-self: end;
    align-self: start;
    /*
     * Sous les commandes de zoom du moteur : la hauteur mesurée de l'en-tête,
     * puis celle du groupe MapLibre (deux boutons de 2,75rem) et son
     * espacement.
     */
    margin: var(--tds-space-3);
    margin-block-start: calc(
        env(safe-area-inset-top) + var(--app-header-h)
        + var(--tds-space-2) + 5.5rem + var(--tds-space-3)
    );
    display: flex;
    flex-direction: column;
    gap: var(--tds-space-2);
}

.app__tool {
    width: 2.75rem;
    height: 2.75rem;
    display: grid;
    place-items: center;
    position: relative;
    border: var(--tds-border-width-default) solid var(--tds-border-default);
    border-radius: var(--tds-radius-lg);
    background: var(--tds-surface-default);
    color: var(--tds-text-secondary);
    box-shadow: var(--tds-elevation-medium);
    cursor: pointer;
    /* Le mouvement RÉPOND, il n'anime pas : règle `motion-responds` du DS. */
    transition: background-color 120ms ease, color 120ms ease;
}

.app__tool:hover {
    background: var(--tds-action-ghost-hover);
    color: var(--tds-text-primary);
}

.app__tool:focus-visible {
    outline: var(--tds-focus-width) solid var(--tds-border-focus);
    outline-offset: var(--tds-focus-offset);
}

.app__tool[aria-pressed="true"],
.app__tool[aria-expanded="true"] {
    background: var(--tds-brand-primary);
    border-color: var(--tds-brand-primary);
    color: var(--tds-brand-on-primary);
}

/* L'état « en cours » de la géolocalisation : visible, et sans animation folle. */
.app__tool[data-app-busy="true"] {
    opacity: 0.7;
    cursor: progress;
}

.app__tool[data-app-located="true"] {
    color: var(--tds-brand-primary);
    border-color: var(--tds-brand-primary);
}

.app__tool-count {
    position: absolute;
    inset-block-start: -0.35rem;
    inset-inline-end: -0.35rem;
    min-width: 1.25rem;
    height: 1.25rem;
    padding-inline: 0.25rem;
    display: grid;
    place-items: center;
    border-radius: var(--tds-radius-full);
    background: var(--tds-brand-primary);
    color: var(--tds-brand-on-primary);
    font-size: var(--tds-font-size-caption);
    font-weight: var(--tds-font-weight-semibold);
    line-height: 1;
}

/* ── LE CHOIX DU FOND ─────────────────────────────────────────────────── */

/*
 * ── LE CATALOGUE DE FONDS ─────────────────────────────────────────────────
 *
 * C'était une barrette de deux vignettes côte à côte. C'est devenu une liste,
 * parce que le contenu a changé de nature : deux besoins, plus les
 * référentiels institutionnels et les prises de vue, chacun avec son
 * producteur et sa couverture.
 *
 * Une hauteur maximale et un défilement propre : le catalogue va grandir, et
 * un panneau qui pousse hors de l'écran est un panneau dont on ne voit plus le
 * bas sans le savoir.
 */
.app__bases {
    z-index: 5;
    justify-self: end;
    align-self: end;
    margin: var(--tds-space-3);
    margin-block-end: calc(env(safe-area-inset-bottom) + var(--tds-space-3));
    display: flex;
    flex-direction: column;
    gap: var(--tds-space-3);
    padding: var(--tds-space-3);
    width: min(20rem, calc(100vw - 2 * var(--tds-space-3)));
    max-height: min(32rem, 70vh);
    overflow-y: auto;
    overscroll-behavior: contain;
    background: var(--tds-surface-default);
    border: var(--tds-border-width-default) solid var(--tds-border-default);
    border-radius: var(--tds-radius-lg);
    box-shadow: var(--tds-elevation-high);
}

.app__base-family {
    display: flex;
    flex-direction: column;
    gap: var(--tds-space-1);
}

.app__base-family-title {
    margin: 0;
    font-size: var(--tds-font-size-label);
    font-weight: var(--tds-font-weight-semibold);
    letter-spacing: var(--tds-letter-spacing-label);
    text-transform: uppercase;
    color: var(--tds-text-secondary);
}

.app__base-family-note {
    margin: 0 0 var(--tds-space-1);
    font-size: var(--tds-font-size-caption);
    color: var(--tds-text-muted);
}

.app__base {
    display: flex;
    align-items: center;
    gap: var(--tds-space-2);
    padding: var(--tds-space-2);
    border: var(--tds-border-width-default) solid transparent;
    border-radius: var(--tds-radius-md);
    background: none;
    color: var(--tds-text-secondary);
    font: inherit;
    font-size: var(--tds-font-size-caption);
    text-align: start;
    cursor: pointer;
}

.app__base-text {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.app__base-title {
    font-size: var(--tds-font-size-body-small);
    color: var(--tds-text-primary);
}

/*
 * Le producteur, la couverture et le millésime, en second rang. Ils sont
 * INDISPENSABLES — choisir « GRB » sans savoir qu'il s'arrête à la Flandre est
 * un choix qu'on regrette — et ils ne doivent pas pour autant transformer le
 * sélecteur en fiche technique. D'où la seconde ligne, plus petite et plus
 * pâle, tronquée plutôt que repliée.
 */
.app__base-sub {
    font-size: var(--tds-font-size-caption);
    color: var(--tds-text-muted);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/*
 * L'avertissement de couverture, SUR la carte.
 *
 * Le cas qu'il traite est celui où le panneau des fonds est fermé : on choisit
 * un référentiel régional, on referme, on fait glisser la carte au-delà de sa
 * compétence — et l'écran devient vide sans un mot. Rangé dans le panneau, il
 * n'aurait été lisible que dans le seul cas où il ne sert à rien.
 *
 * Posé en haut et centré : c'est la zone que le pouce ne couvre pas, et celle
 * où l'œil revient quand quelque chose a changé.
 */
.app__coverage {
    z-index: 6;
    justify-self: center;
    align-self: start;
    margin-block-start: calc(var(--tds-space-3) + 5.25rem);
    max-width: min(28rem, calc(100vw - 2 * var(--tds-space-4)));
    margin-inline: var(--tds-space-4);
    padding: var(--tds-space-2) var(--tds-space-3);
    border: var(--tds-border-width-default) solid var(--tds-status-warning);
    border-radius: var(--tds-radius-md);
    background: var(--tds-status-warning-subtle);
    color: var(--tds-status-warning);
    font-size: var(--tds-font-size-caption);
    box-shadow: var(--tds-elevation-low);
}

.app__base.is-active {
    border-color: var(--tds-brand-primary);
    color: var(--tds-text-primary);
    font-weight: var(--tds-font-weight-medium);
}

.app__base:focus-visible {
    outline: var(--tds-focus-width) solid var(--tds-border-focus);
    outline-offset: var(--tds-focus-offset);
}

/*
 * Les vignettes ne sont pas des photographies : ce sont deux aplats de jetons.
 * Embarquer une miniature d'orthophoto aurait fait entrer une image de
 * fournisseur dans le dépôt, avec sa licence et sa date de péremption, pour
 * décorer un bouton.
 */
.app__base-swatch {
    flex: none;
    width: 2.75rem;
    height: 1.75rem;
    border-radius: var(--tds-radius-sm);
    border: var(--tds-border-width-default) solid var(--tds-border-default);
}

.app__base-swatch--plan {
    background:
        linear-gradient(115deg, transparent 46%, var(--tds-border-strong) 46%, var(--tds-border-strong) 52%, transparent 52%),
        linear-gradient(15deg, transparent 60%, var(--tds-border-default) 60%, var(--tds-border-default) 66%, transparent 66%),
        var(--tds-surface-sunken);
}

.app__base-swatch--gray {
    background:
        linear-gradient(115deg, transparent 46%, var(--tds-border-strong) 46%, var(--tds-border-strong) 52%, transparent 52%),
        var(--tds-surface-sunken);
}

.app__base-swatch--colour {
    background:
        linear-gradient(115deg, transparent 46%, var(--tds-data-3) 46%, var(--tds-data-3) 52%, transparent 52%),
        linear-gradient(15deg, transparent 60%, var(--tds-data-6) 60%, var(--tds-data-6) 66%, transparent 66%),
        var(--tds-surface-sunken);
}

.app__base-swatch--aerial {
    background:
        radial-gradient(circle at 30% 40%, var(--tds-data-3) 0 22%, transparent 23%),
        radial-gradient(circle at 70% 65%, var(--tds-data-2) 0 26%, transparent 27%),
        var(--tds-data-6);
}

/* ── LE PANNEAU ───────────────────────────────────────────────────────── */

.app__panel {
    z-index: 7;
    justify-self: end;
    align-self: stretch;
    width: min(23rem, 100vw);
    display: flex;
    flex-direction: column;
    background: var(--tds-surface-default);
    border-inline-start: var(--tds-border-width-default) solid var(--tds-border-default);
    box-shadow: var(--tds-elevation-high);
    overflow: hidden;
}

/*
 * ── `hidden` GAGNE, TOUJOURS ──────────────────────────────────────────────
 *
 * Cette page pilote une douzaine d'éléments par l'attribut `hidden` : le
 * panneau, le laboratoire, la fiche, l'annonce, le sélecteur de fond, chaque
 * ligne de couche filtrée, la pastille du compteur.
 *
 * Or `[hidden] { display: none }` de la feuille du navigateur a la
 * spécificité d'un simple attribut : **n'importe quelle règle de classe qui
 * pose un `display` la bat**. Le défaut est passé en revue une fois, et il
 * était typique : `.app__tool-count { display: grid }` faisait apparaître une
 * pastille de compteur sur le bouton des couches alors que le compteur valait
 * zéro et que l'élément portait bien `hidden`. Mesuré : `hidden` à vrai,
 * `display` calculé à `grid`.
 *
 * Une règle unique, portée à `!important`, rend la classe entière de défauts
 * impossible plutôt que de la corriger cas par cas — et c'est exactement ce
 * que fait la feuille de réinitialisation des artefacts, pour la même raison.
 */
.app [hidden],
.app[hidden] {
    display: none !important;
}

.app__panel-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--tds-space-3);
    padding: var(--tds-space-3) var(--tds-space-4);
    padding-block-start: max(var(--tds-space-3), env(safe-area-inset-top));
    border-block-end: var(--tds-border-width-default) solid var(--tds-border-default);
}

.app__panel-title {
    margin: 0;
    font-size: var(--tds-font-size-heading4);
    font-weight: var(--tds-font-weight-semibold);
}

.app__close {
    width: 44px;
    height: 44px;
    min-width: 44px;
    min-height: 44px;
    flex-shrink: 0;
    display: grid;
    place-items: center;
    border: 0;
    border-radius: var(--tds-radius-md);
    background: none;
    color: var(--tds-text-secondary);
    cursor: pointer;
}

.app__close:hover {
    background: var(--tds-action-ghost-hover);
    color: var(--tds-text-primary);
}

.app__close:focus-visible {
    outline: var(--tds-focus-width) solid var(--tds-border-focus);
    outline-offset: var(--tds-focus-offset);
}

.app__panel-foot {
    flex: 0 0 auto;
    padding: var(--tds-space-3) var(--tds-space-4);
    padding-block-end: max(var(--tds-space-3), env(safe-area-inset-bottom));
    border-block-start: var(--tds-border-width-default) solid var(--tds-border-default);
}

.app__link {
    border: 0;
    background: none;
    padding: 0;
    color: var(--tds-brand-link);
    font: inherit;
    font-size: var(--tds-font-size-body-small);
    cursor: pointer;
    text-decoration: underline;
    text-underline-offset: 0.2em;
}

.app__group + .app__group {
    margin-block-start: var(--tds-space-5);
}

.app__group-title {
    margin: 0 0 var(--tds-space-2);
    font-size: var(--tds-typography-overline-font-size, 0.75rem);
    font-weight: var(--tds-typography-overline-font-weight, 600);
    letter-spacing: var(--tds-typography-overline-letter-spacing, 0.08em);
    text-transform: var(--tds-typography-overline-text-transform, uppercase);
    color: var(--tds-text-muted);
}

/* ── UN PARENT REPLIABLE ──────────────────────────────────────────────────
 *
 * `.app__group` est un <details> depuis la 0.14.0. La <summary> porte le titre
 * du parent et le rend cliquable ; le chevron dit l'état sans une ligne de
 * script, et il respecte `prefers-reduced-motion` par le jeton de durée.
 */
summary.app__group-title {
    display: flex;
    align-items: center;
    gap: var(--tds-space-2);
    cursor: pointer;
    list-style: none;
    user-select: none;
    min-height: var(--tds-touch-target-web);
}

summary.app__group-title::-webkit-details-marker { display: none; }

summary.app__group-title::before {
    content: "\25B8"; /* ▸ */
    color: var(--tds-text-muted);
    transition: transform var(--tds-motion-duration-short) var(--tds-motion-easing-standard, ease);
}

.app__group[open] > summary.app__group-title::before {
    transform: rotate(90deg);
}

/* ── UNE COUCHE, ET SON ÉTAT ──────────────────────────────────────────── */

.app__layers {
    margin: 0;
    padding: 0;
    list-style: none;
    display: flex;
    flex-direction: column;
    gap: var(--tds-space-1);
}

.app__empty {
    margin: var(--tds-space-4) 0 0;
    color: var(--tds-text-muted);
    font-size: var(--tds-font-size-body-small);
}

/* ── LES FILTRES DE LA RECHARGE ───────────────────────────────────────── */

.app__group--filters {
    margin-block-start: var(--tds-space-5);
    padding-block-start: var(--tds-space-4);
    border-block-start: var(--tds-border-width-default) solid var(--tds-border-default);
}

.app__chips {
    display: flex;
    flex-wrap: wrap;
    gap: var(--tds-space-2);
    margin-block-end: var(--tds-space-2);
}

.app__chip {
    min-height: 2rem;
    padding: var(--tds-space-1) var(--tds-space-3);
    border: var(--tds-border-width-default) solid var(--tds-border-default);
    border-radius: var(--tds-radius-full);
    background: var(--tds-surface-default);
    color: var(--tds-text-secondary);
    font: inherit;
    font-size: var(--tds-font-size-caption);
    cursor: pointer;
}

.app__chip[aria-pressed="true"] {
    background: var(--tds-brand-primary);
    border-color: var(--tds-brand-primary);
    color: var(--tds-brand-on-primary);
}

.app__chip:focus-visible {
    outline: var(--tds-focus-width) solid var(--tds-border-focus);
    outline-offset: var(--tds-focus-offset);
}

.app__hint {
    margin: var(--tds-space-3) 0 0;
    font-size: var(--tds-font-size-caption);
    line-height: var(--tds-line-height-body);
    color: var(--tds-text-muted);
}

.app__count {
    margin: var(--tds-space-3) 0 0;
    font-size: var(--tds-font-size-body-small);
    color: var(--tds-text-secondary);
}

.app__sources {
    margin: 0 0 var(--tds-space-4);
    padding-inline-start: var(--tds-space-5);
    font-size: var(--tds-font-size-caption);
    color: var(--tds-text-muted);
}

/* ── LA FICHE ─────────────────────────────────────────────────────────── */

.app__card {
    /*
     * Dans la colonne d'exploration depuis la 0.23.0 : elle prend la hauteur
     * qui reste sous la recherche et les thèmes, et défile seule. Voir
     * « LA COLONNE D'EXPLORATION » plus bas.
     */
    position: relative;
    pointer-events: auto;
    flex: 0 1 auto;
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: var(--tds-space-4);
    background: var(--tds-surface-default);
    border: var(--tds-border-width-default) solid var(--tds-border-default);
    border-radius: var(--tds-radius-lg);
    box-shadow: var(--tds-elevation-high);
}

.app__card-close {
    position: absolute;
    inset-block-start: var(--tds-space-2);
    inset-inline-end: var(--tds-space-2);
}

.app__card-title {
    margin: 0 var(--tds-space-6) var(--tds-space-1) 0;
    font-size: var(--tds-font-size-heading4);
}

.app__card-address {
    margin: 0 0 var(--tds-space-3);
    color: var(--tds-text-muted);
    font-size: var(--tds-font-size-body-small);
}

.app__card-heading {
    margin: var(--tds-space-4) 0 var(--tds-space-2);
    font-size: var(--tds-font-size-label);
    text-transform: uppercase;
    letter-spacing: var(--tds-letter-spacing-overline);
    color: var(--tds-text-muted);
}

.app__card-line,
.app__card-empty {
    margin: 0 0 var(--tds-space-1);
    font-size: var(--tds-font-size-body-small);
}

.app__connectors {
    margin: 0;
    padding: 0;
    list-style: none;
    display: flex;
    flex-direction: column;
    gap: var(--tds-space-2);
}

.app__connector {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    padding: var(--tds-space-2);
    border: var(--tds-border-width-default) solid var(--tds-border-default);
    border-radius: var(--tds-radius-md);
    font-size: var(--tds-font-size-body-small);
}

.app__connector-standard {
    font-weight: var(--tds-font-weight-medium);
}

.app__connector-facts {
    display: flex;
    flex-wrap: wrap;
    gap: var(--tds-space-2);
    color: var(--tds-text-muted);
    font-size: var(--tds-font-size-caption);
}

.app__badge {
    align-self: flex-start;
    padding: 0.05rem var(--tds-space-2);
    border-radius: var(--tds-radius-full);
    font-size: var(--tds-font-size-caption);
    background: var(--tds-surface-sunken);
    color: var(--tds-text-muted);
}

.app__badge[data-voltage="at-least-800v"] {
    background: var(--tds-status-success-subtle);
    color: var(--tds-status-success);
}

/*
 * ── LA DISPONIBILITÉ (0.26.0) ─────────────────────────────────────────────
 *
 * Un état porte TOUJOURS un mot : la teinte ne fait que le souligner. Un
 * relevé qui vieillit perd sa teinte — `stale` et au-delà sont neutres —,
 * pour qu'un vert ne survive pas à l'information qui le justifiait.
 */
.app__availability {
    margin: var(--tds-space-2) 0 var(--tds-space-1);
    padding: var(--tds-space-2);
    border-radius: var(--tds-radius-md);
    background: var(--tds-surface-sunken);
}

.app__availability[data-freshness="live"],
.app__availability[data-freshness="aging"] {
    background: var(--tds-status-info-subtle);
}

.app__availability-title {
    margin: 0;
    font-weight: var(--tds-font-weight-medium);
    font-size: var(--tds-font-size-body-small);
}

.app__availability-detail {
    margin: 0.15rem 0 0;
    color: var(--tds-text-muted);
    font-size: var(--tds-font-size-caption);
}

.app__point-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--tds-space-2);
}

.app__point-facts {
    color: var(--tds-text-muted);
    font-size: var(--tds-font-size-caption);
    overflow-wrap: anywhere;
}

.app__status {
    padding: 0.05rem var(--tds-space-2);
    border-radius: var(--tds-radius-full);
    font-size: var(--tds-font-size-caption);
    font-weight: var(--tds-font-weight-medium);
    background: var(--tds-surface-sunken);
    color: var(--tds-text-secondary);
    white-space: nowrap;
}

.app__status[data-status="available"] {
    background: var(--tds-status-success-subtle);
    color: var(--tds-status-success);
}

.app__status[data-status="occupied"],
.app__status[data-status="reserved"] {
    background: var(--tds-status-warning-subtle);
    color: var(--tds-text-secondary);
}

.app__status[data-status="out-of-order"],
.app__status[data-status="unavailable"],
.app__status[data-status="blocked"] {
    background: var(--tds-status-danger-subtle);
    color: var(--tds-status-danger);
}

.app__details {
    margin-block-start: var(--tds-space-3);
    font-size: var(--tds-font-size-caption);
}

.app__details summary {
    cursor: pointer;
    color: var(--tds-text-secondary);
}

/*
| Le contour de focus du Design System, comme `.app__facets-more > summary`.
| Mesuré au clavier dans Chromium le 2026-09-22 (0.27.0) : le résumé « D'où
| vient cette fiche » était le seul contrôle de la fiche à garder le contour
| NATIF du navigateur (auto, 1 px) entre « Copier le lien » et les
| attributions, tous deux en 2 px — un focus visible, mais qui changeait de
| forme au milieu du parcours.
*/
.app__details summary:focus-visible {
    outline: var(--tds-focus-width) solid var(--tds-border-focus);
    outline-offset: var(--tds-focus-offset);
    border-radius: var(--tds-radius-sm);
}

/* ── L'ANNONCE ────────────────────────────────────────────────────────── */

/*
 * Elle est au CENTRE BAS, au-dessus de tout, et elle est visible.
 *
 * La 0.8.0 écrivait ses échecs dans un compteur logé au fond d'une section
 * repliée : mesuré, l'élément recevait bien le texte, avec une hauteur de zéro
 * pixel. C'est de là que venait « la géolocalisation ne fonctionne pas » —
 * elle échouait, et le disait à personne.
 */
.app__toast {
    z-index: 9;
    justify-self: center;
    align-self: end;
    display: flex;
    align-items: center;
    gap: var(--tds-space-3);
    max-width: min(34rem, calc(100vw - 2 * var(--tds-space-4)));
    margin-block-end: calc(env(safe-area-inset-bottom) + 3rem);
    padding: var(--tds-space-3) var(--tds-space-4);
    background: var(--tds-surface-raised);
    border: var(--tds-border-width-default) solid var(--tds-border-default);
    border-radius: var(--tds-radius-lg);
    box-shadow: var(--tds-elevation-high);
    font-size: var(--tds-font-size-body-small);
    color: var(--tds-text-primary);
}

.app__toast[data-app-tone="error"] {
    border-color: var(--tds-status-danger);
    background: var(--tds-status-danger-subtle);
}

.app__toast[data-app-tone="info"] {
    border-color: var(--tds-status-info);
    background: var(--tds-status-info-subtle);
}

.app__toast-action {
    flex: 0 0 auto;
    min-height: 2rem;
    padding: var(--tds-space-1) var(--tds-space-3);
    border: var(--tds-border-width-default) solid var(--tds-border-default);
    border-radius: var(--tds-radius-md);
    background: var(--tds-surface-default);
    color: var(--tds-text-primary);
    font: inherit;
    font-size: var(--tds-font-size-caption);
    cursor: pointer;
}

/* ── LA POSITION DU LECTEUR ───────────────────────────────────────────── */

/*
 * Un point, et le rayon de son incertitude. Les deux, parce que l'un sans
 * l'autre ment : un point seul affirme une précision que le navigateur n'a pas
 * promise, et un cercle seul ne dit pas où l'on est.
 */
.app__me {
    width: 1.125rem;
    height: 1.125rem;
    border-radius: 50%;
    background: var(--tds-brand-primary);
    border: 3px solid var(--tds-surface-default);
    box-shadow: var(--tds-elevation-medium);
}

/* ── LE TÉLÉPHONE ─────────────────────────────────────────────────────── */

/*
 * Ce n'est pas la version de bureau rétrécie.
 *
 * Trois choses changent de nature, et non de taille :
 *
 *   1. le panneau devient une FEUILLE MONTANTE. Sur un téléphone tenu à une
 *      main, le bas de l'écran est ce que le pouce atteint et le haut est ce
 *      que la paume cache ;
 *   2. la fiche fait de même, pour la même raison ;
 *   3. les zones sûres sont respectées partout — encoche en haut, barre
 *      gestuelle en bas.
 */
@media (max-width: 47.99rem) {
    /*
     * L'en-tête est compact sur téléphone et peut se replier avec le texte
     * agrandi. Le nom du
     * compte, lui, se replie de lui-même dans le menu ouvert (`tds-account`) ;
     * l'avatar reste.
     */
    body[data-layout="app"] .site-header {
        gap: var(--tds-space-2);
        padding: var(--tds-space-2) var(--tds-space-3);
        padding-block-start: max(var(--tds-space-2), env(safe-area-inset-top));
    }

    body[data-layout="app"] .site-header__brand {
        font-size: var(--tds-font-size-body-small);
        max-width: 100%;
        flex: 0 0 auto;
    }

    body[data-layout="app"] .site-header__end {
        gap: var(--tds-space-2);
    }

    body[data-layout="app"] .site-header__report-label {
        /* Le lien perd son libellé avant sa cible tactile ; son nom accessible
         * reste, et l'entrée en toutes lettres vit au pied du panneau
         * « Couches », à côté de « Aide ». */
        position: absolute;
        width: 1px;
        height: 1px;
        overflow: hidden;
        clip-path: inset(50%);
        white-space: nowrap;
    }

    /*
     * L'identité, le signalement et la connexion ont priorité sur le
     * territoire. Sous 26 rem, la marque d'environnement se
     * retire de l'en-tête de la CARTE plutôt que de pousser le compte hors de
     * l'écran ; elle reste sur la page « Version » et sur toute page hors
     * carte. La Production n'en porte pas : rien ne change pour elle.
     */
    @media (max-width: 26rem) {
        .site-header__env {
            display: none;
        }
    }

    /* À 320 px, réduire les marges avant les commandes ; le lockup complet
     * garde l’échelle commune. L’en-tête peut passer sur plusieurs lignes. */
    @media (max-width: 23.5rem) {
        body[data-layout="app"] .site-header {
            gap: var(--tds-space-1);
            padding-inline: var(--tds-space-2);
        }
        body[data-layout="app"] .site-header__home { gap: var(--tds-space-1); }
    }

    /*
     * ── LES COMMANDES DESCENDENT ──────────────────────────────────────────
     *
     * En haut à droite, elles se battaient avec la recherche pour la même
     * bande de 44 px. Mais ce n'est pas la raison principale de les déplacer :
     * sur un téléphone tenu à une main, **le haut de l'écran est hors de
     * portée du pouce**. Zoomer et ouvrir les couches sont les deux gestes les
     * plus fréquents ; ils descendent là où la main est.
     *
     * Le rail et le groupe du moteur restent une seule colonne, comme sur
     * grand écran — c'est la même idée, à l'autre bout de l'écran.
     */
    .app .maplibregl-ctrl-top-right {
        inset-block-start: auto;
        /* Au-dessus de l'attribution MESURÉE — voir `measureHeader()`. */
        inset-block-end: calc(env(safe-area-inset-bottom) + var(--app-attribution-h, 2.75rem) + var(--tds-space-2));
        inset-inline-end: var(--tds-space-3);
    }

    .app__rail {
        align-self: end;
        margin-block-start: 0;
        margin-block-end: calc(
            env(safe-area-inset-bottom) + var(--app-attribution-h, 2.75rem) + var(--tds-space-2)
            + 5.5rem + var(--tds-space-3)
        );
    }

    .app__explore {
        width: auto;
        justify-self: stretch;
        margin-inline: var(--tds-space-3);
    }

    .app__panel {
        justify-self: stretch;
        align-self: end;
        width: auto;
        max-height: 72dvh;
        border-inline-start: 0;
        border-block-start: var(--tds-border-width-default) solid var(--tds-border-default);
        border-start-start-radius: var(--tds-radius-xl, 1rem);
        border-start-end-radius: var(--tds-radius-xl, 1rem);
    }

    .app__panel-head {
        padding-block-start: var(--tds-space-3);
    }

    .app__card {
        /*
         * La fiche QUITTE la colonne et se pose en bas de l'écran : la moitié
         * basse est ce que le pouce atteint. `fixed` plutôt qu'une ligne de la
         * grille, parce qu'elle vit dans la colonne pour l'ordre de lecture et
         * doit en sortir pour la géométrie.
         */
        position: fixed;
        inset-inline: 0;
        inset-block-end: 0;
        z-index: 8;
        width: auto;
        margin: 0;
        max-height: 62dvh;
        border-radius: 0;
        border-start-start-radius: var(--tds-radius-xl, 1rem);
        border-start-end-radius: var(--tds-radius-xl, 1rem);
        padding-block-end: calc(env(safe-area-inset-bottom) + var(--tds-space-4));
    }

    .app__bases {
        justify-self: center;
        margin-block-end: calc(env(safe-area-inset-bottom) + var(--tds-space-6));
    }

    .app__toast {
        margin-block-end: calc(env(safe-area-inset-bottom) + var(--tds-space-6));
    }
}

/* Sur grand écran, la poignée n'a rien à dire : rien ne se tire. */

/*
 * Le mouvement obéit à la préférence système. Ce n'est pas une courtoisie :
 * une carte qui glisse est une carte qui rend malade une partie de ses
 * lecteurs.
 */
@media (prefers-reduced-motion: reduce) {
    .app__tool {
        transition: none;
    }
}

.app__legend {
    margin: var(--tds-space-2) 0 0;
    padding: 0;
    list-style: none;
    display: flex;
    flex-direction: column;
    gap: var(--tds-space-1);
}

.app__legend-item {
    display: flex;
    align-items: center;
    gap: var(--tds-space-2);
}

.app__legend-swatch {
    flex: none;
    width: 1.25rem;
    height: 0.375rem;
    border-radius: var(--tds-radius-sm);
    background: var(--tds-data-missing);
}

.app__chip-count {
    margin-inline-start: var(--tds-space-1);
    opacity: 0.7;
    font-variant-numeric: tabular-nums;
}

/* ── LA LIGNE D'UNE COUCHE ─────────────────────────────────────────────── */

/*
 * L'étiquette « expérimentale » ne dépend PAS de sa couleur : elle porte un
 * mot. C'est la même règle que pour les états — une information portée par la
 * seule teinte est une information que la moitié des lecteurs ne reçoit pas.
 */
.app__badge {
    display: inline-block;
    margin-inline-start: var(--tds-space-2);
    padding: 0 var(--tds-space-2);
    border-radius: var(--tds-radius-full);
    background: var(--tds-status-warning-subtle);
    color: var(--tds-text-secondary);
    font-size: var(--tds-font-size-caption);
    font-weight: var(--tds-font-weight-medium);
    vertical-align: middle;
}

/* ── LA FICHE ──────────────────────────────────────────────────────────── */

.app__sheet {
    width: min(34rem, calc(100vw - 2 * var(--tds-space-4)));
    max-height: min(80vh, 44rem);
    padding: 0;
    border: var(--tds-border-width-default) solid var(--tds-border-default);
    border-radius: var(--tds-radius-lg);
    background: var(--tds-surface-default);
    color: var(--tds-text-primary);
    overflow: hidden;
}

.app__sheet::backdrop {
    background: color-mix(in srgb, var(--tds-text-primary) 45%, transparent);
}

.app__sheet .app__panel-head {
    position: sticky;
    top: 0;
    z-index: 1;
    background: var(--tds-surface-default);
}

.app__sheet-body {
    max-height: calc(min(80vh, 44rem) - 3.5rem);
    overflow-y: auto;
    padding: 0 var(--tds-space-4) var(--tds-space-4);
}

.app__sheet-lead {
    margin: 0 0 var(--tds-space-3);
    font-size: var(--tds-font-size-body-small);
    line-height: var(--tds-line-height-body);
    color: var(--tds-text-secondary);
}

.app__sheet-warning {
    margin: 0 0 var(--tds-space-3);
    padding: var(--tds-space-2) var(--tds-space-3);
    border-radius: var(--tds-radius-md);
    background: var(--tds-status-warning-subtle);
    font-size: var(--tds-font-size-caption);
    line-height: var(--tds-line-height-body);
}

.app__sheet-dl {
    display: grid;
    grid-template-columns: minmax(7rem, auto) 1fr;
    gap: var(--tds-space-1) var(--tds-space-3);
    margin: 0 0 var(--tds-space-4);
    font-size: var(--tds-font-size-caption);
    line-height: var(--tds-line-height-body);
}

.app__sheet-dl dt {
    color: var(--tds-text-muted);
}

.app__sheet-dl dd {
    margin: 0;
    color: var(--tds-text-primary);
    /* Une URL de service ou un nom de jeu ne se coupe nulle part : sans ceci,
       une fiche déborde son propre cadre sur un téléphone. */
    overflow-wrap: anywhere;
}

.app__sheet-dl--tight {
    margin-bottom: var(--tds-space-2);
}

.app__sheet-heading {
    margin: var(--tds-space-4) 0 var(--tds-space-2);
    font-size: var(--tds-font-size-caption);
    font-weight: var(--tds-font-weight-semibold);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--tds-text-secondary);
}

.app__sheet-subheading {
    margin: var(--tds-space-2) 0 var(--tds-space-1);
    font-size: var(--tds-font-size-caption);
    font-weight: var(--tds-font-weight-medium);
    color: var(--tds-text-muted);
}

.app__sheet-producer {
    margin-bottom: var(--tds-space-3);
    padding: var(--tds-space-3);
    border-radius: var(--tds-radius-md);
    background: var(--tds-surface-sunken);
}

.app__sheet-producer-name {
    margin: 0 0 var(--tds-space-2);
    font-size: var(--tds-font-size-body-small);
    font-weight: var(--tds-font-weight-semibold);
}

.app__sheet-link {
    color: var(--tds-brand-link);
}

.app__sheet-note {
    margin: var(--tds-space-2) 0 0;
    font-size: var(--tds-font-size-caption);
    line-height: var(--tds-line-height-body);
    color: var(--tds-text-muted);
}

/* ── CE QUE LA LICENCE AUTORISE ────────────────────────────────────────── */

.app__sheet-rights {
    display: grid;
    gap: var(--tds-space-1);
    margin: 0;
    padding: 0;
    list-style: none;
    font-size: var(--tds-font-size-caption);
}

.app__right {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--tds-space-2);
    padding: var(--tds-space-1) var(--tds-space-2);
    border-radius: var(--tds-radius-sm, 4px);
    background: var(--tds-surface-default);
}

.app__right-what {
    color: var(--tds-text-secondary);
}

/*
 * La position est ÉCRITE — « autorisé », « interdit », « non tranché » — et la
 * couleur ne fait que la redire. « unknown » n'est pas « allowed » : c'est la
 * réponse honnête quand la documentation ne tranche pas, et elle a sa propre
 * teinte pour qu'on ne la lise pas comme une permission.
 */
.app__right-stance {
    font-weight: var(--tds-font-weight-medium);
}

.app__right--allowed .app__right-stance {
    color: var(--tds-status-success);
}

.app__right--conditional .app__right-stance {
    color: var(--tds-status-warning);
}

.app__right--forbidden .app__right-stance {
    color: var(--tds-status-danger);
}

.app__right--unknown .app__right-stance {
    color: var(--tds-text-muted);
}

/* ── SUR TÉLÉPHONE ─────────────────────────────────────────────────────── */

@media (max-width: 48rem) {
    /*
     * La fiche devient une FEUILLE PLEINE, ancrée en bas — la moitié basse de
     * l'écran est ce que le pouce atteint, et le haut est ce que la main cache.
     * C'est la même décision que pour le panneau, prise en 0.9.0.
     */
    .app__sheet {
        width: 100vw;
        max-width: 100vw;
        max-height: 88vh;
        margin: 0;
        margin-top: auto;
        border-radius: var(--tds-radius-lg) var(--tds-radius-lg) 0 0;
        border-bottom: 0;
    }

    .app__sheet-body {
        max-height: calc(88vh - 3.5rem);
    }

    .app__sheet-dl {
        grid-template-columns: 1fr;
        gap: 0 0;
    }

    .app__sheet-dl dt {
        margin-top: var(--tds-space-2);
    }
}

/* ══════════════════════════════════════════════════════════════════════════
 * L'EXPÉRIENCE « RECHARGE »
 * ══════════════════════════════════════════════════════════════════════════
 *
 * Le panneau reprend la boîte du panneau des couches — même largeur, même
 * surface, même ombre — et n'en change que trois choses :
 *
 *   1. il est OUVERT au chargement, parce qu'on n'entre pas dans une
 *      expérience pour y trouver un panneau fermé ;
 *   2. il défile en un seul corps, résultats compris, plutôt que d'avoir une
 *      tête fixe et une liste indépendante — sur un téléphone, deux zones de
 *      défilement imbriquées se disputent le geste ;
 *   3. sur un écran étroit, il occupe le BAS de l'écran et laisse la carte
 *      visible au-dessus. Une expérience cartographique dont le panneau
 *      recouvre la carte n'est plus une expérience cartographique.
 */

.app__panel--charging {
    z-index: 7;
}

.app__charging-body {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: var(--tds-space-4);
    display: flex;
    flex-direction: column;
    gap: var(--tds-space-3);
}

.app__charging-actions {
    display: flex;
    align-items: center;
    gap: var(--tds-space-3);
    flex-wrap: wrap;
}

/*
 * « Autour de moi » est le geste principal de cette page : il porte donc le
 * poids visuel d'un bouton, et une cible tactile réelle — la règle
 * `touch-target-not-hover` du Design System vaut ici comme ailleurs.
 */
.app__around {
    display: inline-flex;
    align-items: center;
    gap: var(--tds-space-2);
    min-height: 2.75rem;
    padding: 0 var(--tds-space-4);
    border: var(--tds-border-width-default) solid var(--tds-border-strong);
    border-radius: var(--tds-radius-full);
    background: var(--tds-surface-raised);
    color: var(--tds-text-primary);
    font: inherit;
    font-weight: var(--tds-font-weight-semibold);
    cursor: pointer;
}

.app__around:hover {
    background: var(--tds-action-ghost-hover);
}

.app__around:focus-visible {
    outline: var(--tds-focus-width) solid var(--tds-border-focus);
    outline-offset: var(--tds-focus-offset);
}

.app__around[aria-pressed="true"] {
    border-color: var(--tds-brand-primary);
    color: var(--tds-brand-primary);
}

/* Le bouton dit qu'il travaille : sans cela, un GPS lent passe pour une panne. */
.app__around[data-app-busy="true"] {
    opacity: 0.6;
    cursor: progress;
}

.app__charging-filters > summary {
    cursor: pointer;
}

.app__charging-filters .app__chips {
    margin-block: var(--tds-space-2);
}

.app__charging-clear {
    margin: var(--tds-space-2) 0 0;
}

.app__field {
    display: flex;
    flex-direction: column;
    gap: var(--tds-space-1);
    margin: var(--tds-space-3) 0 0;
}

.app__field-label {
    font-size: var(--tds-font-size-label);
    color: var(--tds-text-muted);
}

/*
 * Les rangées à case des filtres de mobilité — une par famille.
 *
 * Elles n'avaient AUCUN style, et leur hauteur venait de ce que leur libellé
 * revenait ou non à la ligne : mesuré le 2026-09-11 à 375 px, trois rangées à
 * 43 px et deux à 18 px pour la seule raison que « Vélos partagés » tient sur
 * une ligne et « Parkings de transit (P+R) » non. Une cible tactile qui dépend
 * de la longueur d'un mot n'est pas une cible tactile.
 *
 * La règle est celle que `.app__layer-main` porte déjà, et elle vient du
 * Design System — `touch-target-not-hover` : la cible est la LIGNE, jamais la
 * case de 13 px que le navigateur dessine.
 */
.app__check {
    display: flex;
    align-items: center;
    gap: var(--tds-space-2);
    cursor: pointer;
    min-height: var(--tds-touch-target-web);
    padding-block: var(--tds-space-1);
}

.app__select {
    min-height: 2.75rem;
    padding: 0 var(--tds-space-2);
    border: var(--tds-border-width-default) solid var(--tds-border-default);
    border-radius: var(--tds-radius-md);
    background: var(--tds-surface-default);
    color: var(--tds-text-primary);
    font: inherit;
}

.app__select:focus-visible {
    outline: var(--tds-focus-width) solid var(--tds-border-focus);
    outline-offset: var(--tds-focus-offset);
}

/* ── LA LISTE DES RÉSULTATS ───────────────────────────────────────────── */

.app__charging-list {
    margin: 0;
    padding: 0;
    list-style: none;
    display: flex;
    flex-direction: column;
    gap: var(--tds-space-2);
}

.app__result {
    width: 100%;
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    /*
     * Une ligne de liste est un BOUTON, pas une ligne cliquable : elle est
     * atteignable au clavier, elle s'annonce comme actionnable, et Entrée
     * l'ouvre. Un `<li>` avec un écouteur de clic n'aurait aucune de ces trois
     * propriétés.
     */
    min-height: 2.75rem;
    padding: var(--tds-space-3);
    text-align: start;
    border: var(--tds-border-width-default) solid var(--tds-border-default);
    border-radius: var(--tds-radius-md);
    background: var(--tds-surface-default);
    color: inherit;
    font: inherit;
    cursor: pointer;
}

.app__result:hover {
    background: var(--tds-action-ghost-hover);
}

.app__result:focus-visible {
    outline: var(--tds-focus-width) solid var(--tds-border-focus);
    outline-offset: var(--tds-focus-offset);
}

/*
 * L'emplacement ouvert se voit dans la liste. `aria-current` porte l'état pour
 * les technologies d'assistance ET pour la feuille de style : un seul attribut,
 * donc pas de risque que le visible et l'annoncé divergent.
 */
.app__result[aria-current="true"] {
    border-color: var(--tds-brand-primary);
    box-shadow: inset 0 0 0 1px var(--tds-brand-primary);
}

.app__result-title {
    font-weight: var(--tds-font-weight-semibold);
}

.app__result-place,
.app__result-meta {
    font-size: var(--tds-font-size-body-small);
    color: var(--tds-text-muted);
}

/*
| La disponibilité d'un résultat (0.27.0) : ce que la pastille de la carte dit
| en couleur, écrit en mots. La puce reprend la couleur de la pastille ; le
| texte, lui, reste à la couleur du texte — c'est lui qui porte l'information.
*/
.app__result-availability {
    display: inline-flex;
    align-items: center;
    gap: var(--tds-space-1);
    font-size: var(--tds-font-size-caption);
    color: var(--tds-text-secondary);
}

.app__result-availability::before {
    content: "";
    inline-size: 0.6em;
    block-size: 0.6em;
    border-radius: var(--tds-radius-full);
    background: var(--tds-data-missing);
    flex: none;
}

.app__result-availability--available::before { background: var(--tds-status-success); }
.app__result-availability--occupied::before { background: var(--tds-status-warning); }
.app__result-availability--out-of-service::before { background: var(--tds-status-danger); }

.app__result-flag {
    align-self: start;
    margin-block-start: var(--tds-space-1);
    padding: 0 var(--tds-space-2);
    border-radius: var(--tds-radius-full);
    background: var(--tds-action-ghost-hover);
    border: var(--tds-border-width-default) solid var(--tds-border-default);
    font-size: var(--tds-font-size-caption);
}

/*
 * ── LE TÉLÉPHONE ──────────────────────────────────────────────────────────
 *
 * Le panneau descend en bas de l'écran et n'en prend que la moitié. C'est la
 * règle qui distingue une carte utilisable d'une liste avec une carte derrière :
 * on doit voir OÙ sont les résultats pendant qu'on les lit.
 *
 * `55vh` et non `100%` : la carte garde 45 % de la hauteur, ce qui suffit à
 * situer un quartier. Et le panneau se ferme — sa croix est dans son en-tête,
 * atteignable au pouce comme au clavier.
 */
@media (max-width: 47.99rem) {
    .app__panel--charging {
        width: 100%;
        justify-self: stretch;
        align-self: end;
        max-height: 55vh;
        border-inline-start: 0;
        border-block-start: var(--tds-border-width-default) solid var(--tds-border-default);
        border-start-start-radius: var(--tds-radius-lg);
        border-start-end-radius: var(--tds-radius-lg);
    }

    .app__charging-body {
        padding-block-end: max(var(--tds-space-4), env(safe-area-inset-bottom));
    }

    /*
     * ── LES CIBLES TACTILES DE L'EXPÉRIENCE ───────────────────────────────
     *
     * Mesuré dans un navigateur à 375 pixels de large : les puces de filtre
     * faisaient 32 pixels de haut, et la croix de fermeture 36. La règle
     * `touch-target-not-hover` du Design System en demande 44 — c'est la
     * hauteur en dessous de laquelle un pouce vise à côté.
     *
     * Le relèvement est PORTÉ ICI, dans le panneau de recharge et sur écran
     * étroit, plutôt que sur `.app__chip` en général. Ces mêmes puces servent
     * aussi de facettes au panneau des couches, où elles sont soixante et
     * n'ont jamais été le geste principal ; les faire toutes grandir
     * transformerait cette liste-là en escalier sans que personne ne l'ait
     * demandé. Ici, filtrer EST ce qu'on vient faire.
     */
    .app__panel--charging .app__chip,
    .app__panel--charging .app__close {
        min-height: 2.75rem;
    }

    .app__panel--charging .app__close {
        min-width: 2.75rem;
    }

    /*
     * Les liens du pied aussi : « Retour au portail Maps » est le seul chemin
     * de sortie, et un chemin de sortie qu'on rate au pouce est un cul-de-sac.
     */
    .app__panel--charging .app__charging-clear .app__link,
    .app__panel--charging .app__panel-foot .app__link {
        display: inline-flex;
        align-items: center;
        min-height: 2.75rem;
    }
}

/*
 * ── LE MARQUEUR DE GROUPE ─────────────────────────────────────────────────
 *
 * Il est un `<button>` posé par MapLibre, et non un rond peint dans le canevas.
 * La raison est écrite dans `drawClusters()` : les glyphes d'un fond raster
 * n'existent pas, et un rond peint n'est atteignable ni au clavier ni par une
 * technologie d'assistance.
 *
 * Le diamètre arrive par `--app-cluster-size`, écrit par le navigateur d'après
 * le compte. Le reste — couleur, contraste, anneau de focus — vient des jetons,
 * comme partout ailleurs.
 */
.app__cluster {
    --app-cluster-size: 30px;
    width: var(--app-cluster-size);
    height: var(--app-cluster-size);
    display: grid;
    place-items: center;
    padding: 0;
    border: 2px solid var(--tds-surface-default);
    border-radius: 50%;
    /*
     * La couleur du groupe arrive par `--app-cluster-colour` quand le domaine
     * en a une à dire — famille dominante (mobilité), concept dominant
     * (trafic). La mobilité l'écrivait depuis la 0.20.0 sans qu'aucune règle
     * ne la lise : tous ses groupes étaient de la même couleur (relevé le
     * 2026-09-16). La recharge n'en pose pas, et garde la couleur par défaut.
     */
    background: var(--app-cluster-colour, var(--tds-data-2));
    color: var(--tds-surface-default);
    font: inherit;
    font-size: var(--tds-font-size-caption);
    font-weight: var(--tds-font-weight-semibold);
    font-variant-numeric: tabular-nums;
    line-height: 1;
    cursor: pointer;
    box-shadow: var(--tds-elevation-low);
}

/*
 * Une station d'observation (0.24.0). Météo : la température dans une pastille.
 * Air : un repère — quatre polluants ne se lisent pas dans un disque, et en
 * choisir un serait une hiérarchie inventée. Le détail est dans la fiche.
 */
.app__station {
    display: grid;
    place-items: center;
    padding: 0 var(--tds-space-1);
    min-width: 1.6rem;
    height: 1.6rem;
    border: 2px solid var(--tds-surface-default);
    border-radius: var(--tds-radius-full);
    background: var(--tds-data-6);
    color: var(--tds-surface-default);
    font: inherit;
    font-size: var(--tds-font-size-caption);
    font-weight: var(--tds-font-weight-semibold);
    font-variant-numeric: tabular-nums;
    line-height: 1;
    cursor: pointer;
    box-shadow: var(--tds-elevation-low);
}

.app__station--air {
    min-width: 0.9rem;
    width: 0.9rem;
    height: 0.9rem;
    padding: 0;
    background: var(--tds-data-5);
}

.app__station:focus-visible {
    outline: var(--tds-focus-width) solid var(--tds-border-focus);
    outline-offset: var(--tds-focus-offset);
}

/*
 * ── LA CIBLE TACTILE D'UN MARQUEUR (0.28.0) ───────────────────────────────
 *
 * Mesuré sur la production 0.27.0 : 72 à 134 cibles de moins de 44 px par
 * vue de recharge ou de transport — les grappes (30 px) et les stations
 * (26 px, 14 px pour l'air). Sur un écran TACTILE, la zone qui reçoit le doigt
 * s'étend à 44 px par un pseudo-élément invisible : le dessin ne change pas,
 * la carte ne se charge pas davantage. Les grappes sont espacées d'au moins
 * 56 px par le serveur (`MapScale::CELL_PIXELS`) : deux zones ne se
 * recouvrent pas. Règle `touch-target-not-hover` du Design System.
 */
@media (pointer: coarse) {
    .app__cluster::after,
    .app__station::after {
        content: "";
        position: absolute;
        inset-block-start: 50%;
        inset-inline-start: 50%;
        width: max(100%, var(--tds-touch-target-web));
        height: max(100%, var(--tds-touch-target-web));
        border-radius: 50%;
        transform: translate(-50%, -50%);
    }
}

.app__cluster:hover {
    filter: brightness(1.08);
}

.app__cluster:focus-visible {
    outline: var(--tds-focus-width) solid var(--tds-border-focus);
    outline-offset: var(--tds-focus-offset);
}

.app__card-summary {
    margin: 0 0 var(--tds-space-3);
    font-weight: var(--tds-font-weight-semibold);
}

/*
 * ══════════════════════════════════════════════════════════════════════════
 * L'EXPLORATION — 0.23.0
 * ══════════════════════════════════════════════════════════════════════════
 *
 * La colonne de gauche d'une application cartographique : recherche, thèmes,
 * panneau du thème, fiche d'objet. Tout y est construit en jetons du Design
 * System ; les primitives — colonne flottante, feuille inférieure, liste de
 * choix — sont celles du gabarit candidat « map-workspace », et sont proposées
 * au Design System (voir docs/produit.md, « Ce qui remonte au Design System »).
 */

/* ── LA COLONNE D'EXPLORATION ────────────────────────────────────────────── */

.app__explore {
    z-index: 5;
    justify-self: start;
    align-self: stretch;
    width: min(26rem, calc(100vw - 2 * var(--tds-space-3)));
    min-height: 0;
    margin: var(--tds-space-3);
    margin-block-start: calc(env(safe-area-inset-top) + var(--app-header-h) + var(--tds-space-2));
    /* Au-dessus de l'attribution mesurée : la colonne ne la recouvre jamais. */
    margin-block-end: calc(env(safe-area-inset-bottom) + var(--app-attribution-h, 2.5rem) + var(--tds-space-2));
    display: flex;
    flex-direction: column;
    gap: var(--tds-space-2);
    /*
     * La colonne elle-même ne capte AUCUN geste : entre deux panneaux, sous un
     * panneau court, c'est la carte qu'on touche. Seuls ses enfants répondent.
     */
    pointer-events: none;
}

.app__explore > * {
    pointer-events: auto;
}

.app__explore > [hidden] {
    display: none;
}

/* ── LES THÈMES ──────────────────────────────────────────────────────────── */

/*
 * Sur grand écran, la bande peut dépasser la colonne : sept puces tiennent sur
 * une ligne à 1 280 px, et en trois lignes dans 26 rem. Elle s'arrête avant le
 * rail des commandes.
 */
.app__themes {
    width: max-content;
    max-width: calc(100vw - 2 * var(--tds-space-3) - 4rem);
}

.app__themes-list {
    display: flex;
    flex-wrap: wrap;
    gap: var(--tds-space-2);
    margin: 0;
    padding: 0;
    list-style: none;
}

/*
 * Le composant `chip` du Design System, variante « sélectionnable ». L'état
 * choisi se lit SANS la couleur : aplat, contour appuyé et graisse — et il est
 * exposé par `aria-current`, pas seulement peint.
 */
.app__theme {
    display: inline-flex;
    align-items: center;
    gap: var(--tds-space-1);
    min-height: var(--tds-touch-target-web);
    padding: 0 var(--tds-space-3);
    border: var(--tds-border-width-default) solid var(--tds-border-default);
    border-radius: var(--tds-radius-role-pill);
    background: var(--tds-surface-default);
    color: var(--tds-text-secondary);
    box-shadow: var(--tds-elevation-low);
    font-size: var(--tds-font-size-body-small);
    font-weight: var(--tds-font-weight-medium);
    text-decoration: none;
    white-space: nowrap;
    transition: background-color 120ms ease, color 120ms ease;
}

.app__theme:hover {
    background: var(--tds-action-ghost-hover);
    color: var(--tds-text-primary);
}

.app__theme:focus-visible {
    outline: var(--tds-focus-width) solid var(--tds-border-focus);
    outline-offset: var(--tds-focus-offset);
}

.app__theme.is-active,
.app__theme[aria-current="true"] {
    background: var(--tds-brand-subtle);
    border-color: var(--tds-brand-primary);
    border-width: var(--tds-border-width-accent);
    color: var(--tds-text-primary);
    font-weight: var(--tds-font-weight-semibold);
}

.app__theme-icon {
    flex: none;
    color: var(--tds-brand-primary);
}

/* ── LE PANNEAU DU THÈME ─────────────────────────────────────────────────── */

.app__theme-panel,
.app__card {
    background: var(--tds-surface-default);
    border: var(--tds-border-width-default) solid var(--tds-border-default);
    border-radius: var(--tds-radius-role-surface);
    box-shadow: var(--tds-elevation-medium);
}

.app__theme-panel {
    flex: 0 1 auto;
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: var(--tds-space-3) var(--tds-space-4);
}

/* Une fiche ouverte a la colonne pour elle : le thème revient à sa fermeture. */
html[data-app-fiche] .app__theme-panel {
    display: none;
}

.app__theme-head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--tds-space-2);
}

.app__theme-kicker,
.app__object-type {
    margin: 0;
    color: var(--tds-text-muted);
    font-size: var(--tds-font-size-caption);
    letter-spacing: var(--tds-letter-spacing-overline);
    text-transform: uppercase;
}

.app__theme-title {
    margin: 0;
    font-size: var(--tds-font-size-heading4);
}

.app__theme-summary {
    min-height: var(--tds-touch-target-web);
    display: flex;
    align-items: center;
    cursor: pointer;
    color: var(--tds-text-secondary);
    font-size: var(--tds-font-size-body-small);
}

.app__theme-desc {
    margin: 0 0 var(--tds-space-3);
    color: var(--tds-text-secondary);
    font-size: var(--tds-font-size-body-small);
}

.app__theme-category + .app__theme-category {
    margin-block-start: var(--tds-space-3);
}

.app__theme-category-title {
    margin: 0 0 var(--tds-space-1);
    color: var(--tds-text-muted);
    font-size: var(--tds-font-size-label);
    font-weight: var(--tds-font-weight-medium);
}

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

/*
 * Une ligne de couche : l'interrupteur prend la place, la fiche ⓘ se pose à
 * côté (0.28.0). Deux cibles distinctes, chacune de 44 px : allumer une couche
 * et lire d'où elle vient ne sont pas le même geste.
 */
.app__theme-layer-row {
    display: flex;
    align-items: center;
    gap: var(--tds-space-1);
}

.app__theme-layer-info {
    flex: none;
    display: inline-grid;
    place-items: center;
    width: var(--tds-touch-target-web);
    height: var(--tds-touch-target-web);
    border: 0;
    border-radius: var(--tds-radius-role-control);
    background: none;
    color: var(--tds-text-muted);
    font: inherit;
    cursor: pointer;
}

.app__theme-layer-info:hover {
    background: var(--tds-action-ghost-hover);
    color: var(--tds-text-primary);
}

.app__theme-layer-info:focus-visible {
    outline: var(--tds-focus-width) solid var(--tds-border-focus);
    outline-offset: calc(-1 * var(--tds-focus-width));
}

.app__layers-summary {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--tds-space-2);
    margin: 0 0 var(--tds-space-3);
    padding: var(--tds-space-2) var(--tds-space-3);
    border-radius: var(--tds-radius-role-control);
    background: var(--tds-surface-sunken);
    font-size: var(--tds-font-size-body-small);
}

.app__layers-summary[hidden],
[data-app-layers-extra][hidden] {
    display: none;
}

[data-app-layers-extra] {
    margin-block-start: var(--tds-space-2);
}

/*
 * Un INTERRUPTEUR, et son état se voit sans la couleur : la pastille se remplit
 * et se décale. `aria-checked` le dit aux technologies d'assistance.
 */
.app__theme-layer {
    width: 100%;
    min-height: var(--tds-touch-target-web);
    display: flex;
    align-items: center;
    gap: var(--tds-space-2);
    padding: 0 var(--tds-space-1);
    border: 0;
    border-radius: var(--tds-radius-role-control);
    background: none;
    color: var(--tds-text-primary);
    font: inherit;
    font-size: var(--tds-font-size-body-small);
    text-align: start;
    cursor: pointer;
}

.app__theme-layer::before {
    content: "";
    flex: none;
    width: 2rem;
    height: 1.125rem;
    border: var(--tds-border-width-accent) solid var(--tds-border-strong);
    border-radius: var(--tds-radius-full);
    background:
        radial-gradient(circle at 0.5rem 50%, var(--tds-border-strong) 0.3rem, transparent 0.32rem);
}

.app__theme-layer[aria-checked="true"]::before {
    border-color: var(--tds-brand-primary);
    background:
        radial-gradient(circle at 1.4rem 50%, var(--tds-brand-primary) 0.3rem, transparent 0.32rem),
        var(--tds-brand-subtle);
}

.app__theme-layer:hover {
    background: var(--tds-action-ghost-hover);
}

.app__theme-layer:focus-visible {
    outline: var(--tds-focus-width) solid var(--tds-border-focus);
    outline-offset: calc(-1 * var(--tds-focus-width));
}

.app__theme-layer:disabled {
    color: var(--tds-text-muted);
    cursor: not-allowed;
}

.app__theme-layer-name {
    flex: 1 1 auto;
}

.app__theme-layer-state {
    flex: none;
    color: var(--tds-text-muted);
    font-size: var(--tds-font-size-caption);
}

.app__theme-links {
    display: flex;
    flex-wrap: wrap;
    gap: var(--tds-space-2) var(--tds-space-4);
    margin: var(--tds-space-3) 0 0;
}

/* ── LES SUGGESTIONS, RANGÉES PAR NATURE ─────────────────────────────────── */

.app__suggestion-group + .app__suggestion-group {
    border-top: var(--tds-border-width-default) solid var(--tds-border-default);
    margin-top: var(--tds-space-1);
    padding-top: var(--tds-space-1);
}

.app__suggestion-heading {
    padding: var(--tds-space-2) var(--tds-space-3) var(--tds-space-1);
    color: var(--tds-text-muted);
    font-size: var(--tds-font-size-caption);
    font-weight: var(--tds-font-weight-medium);
    letter-spacing: var(--tds-letter-spacing-overline);
    text-transform: uppercase;
}

/* ── LA FICHE D'OBJET ────────────────────────────────────────────────────── */

.app__object-head {
    position: relative;
    padding-inline-end: var(--tds-space-8);
}

.app__object-back {
    display: inline-flex;
    align-items: center;
    min-height: var(--tds-touch-target-web);
    margin-block-end: var(--tds-space-1);
}

.app__card-title:focus-visible {
    outline: var(--tds-focus-width) solid var(--tds-border-focus);
    outline-offset: var(--tds-focus-offset);
    border-radius: var(--tds-radius-sm);
}

.app__card-title:focus:not(:focus-visible) {
    outline: none;
}

.app__card-close {
    inset-block-start: 0;
    inset-inline-end: calc(-1 * var(--tds-space-2));
}

.app__object-actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--tds-space-2);
    margin: var(--tds-space-3) 0;
}

/*
 * Des boutons SECONDAIRES : la fiche n'a pas d'action principale — elle
 * informe. La règle `single-primary-action` du Design System l'interdirait
 * d'ailleurs à trois boutons de même poids.
 */
.app__action {
    min-height: var(--tds-touch-target-web);
    padding: 0 var(--tds-space-3);
    border: var(--tds-border-width-default) solid var(--tds-border-default);
    border-radius: var(--tds-radius-role-control);
    background: var(--tds-action-secondary);
    color: var(--tds-text-primary);
    font: inherit;
    font-size: var(--tds-font-size-body-small);
    cursor: pointer;
}

.app__action:hover {
    background: var(--tds-action-secondary-hover);
}

.app__action:focus-visible {
    outline: var(--tds-focus-width) solid var(--tds-border-focus);
    outline-offset: var(--tds-focus-offset);
}

.app__object-source {
    margin-block-start: var(--tds-space-4);
    padding: var(--tds-space-3);
    border: var(--tds-border-width-default) solid var(--tds-border-default);
    border-radius: var(--tds-radius-role-surface);
    background: var(--tds-brand-subtle);
    color: var(--tds-text-primary);
}

.app__object-source-title {
    margin: 0 0 var(--tds-space-1);
    color: var(--tds-text-primary);
    font-size: var(--tds-font-size-caption);
    letter-spacing: var(--tds-letter-spacing-overline);
    text-transform: uppercase;
}

.app__object-source-line {
    margin: 0 0 var(--tds-space-1);
    color: var(--tds-text-primary);
    font-size: var(--tds-font-size-caption);
}

/* Le composant `key-value-row` : une propriété, sa valeur. */
.app__kv {
    margin: 0;
}

/*
 * Les faits d'une fiche de référentiel — mobilité, trafic, observations —
 * dans le même dessin `key-value-row` que ceux d'une couche du catalogue
 * (0.28.0). La classe n'avait AUCUNE règle : ces fiches héritaient du style
 * par défaut du navigateur, la valeur décalée sous sa clé.
 */
.app__card-facts {
    display: grid;
    grid-template-columns: minmax(7rem, 40%) 1fr;
    column-gap: var(--tds-space-3);
    margin: var(--tds-space-2) 0;
    font-size: var(--tds-font-size-body-small);
}

.app__card-facts dt,
.app__card-facts dd {
    padding: var(--tds-space-2) 0;
    border-bottom: var(--tds-border-width-default) solid var(--tds-border-default);
}

.app__card-facts dt {
    color: var(--tds-text-muted);
}

.app__card-facts dd {
    margin: 0;
    font-variant-numeric: tabular-nums;
    overflow-wrap: anywhere;
}

.app__kv-row {
    display: grid;
    grid-template-columns: minmax(7rem, 40%) 1fr;
    gap: var(--tds-space-3);
    padding: var(--tds-space-2) 0;
    border-bottom: var(--tds-border-width-default) solid var(--tds-border-default);
    font-size: var(--tds-font-size-body-small);
}

.app__kv-row dt {
    color: var(--tds-text-muted);
}

.app__kv-row dd {
    margin: 0;
    font-variant-numeric: tabular-nums;
    overflow-wrap: anywhere;
}

.app__kv-row--mono dd {
    font-family: var(--tds-font-family-mono);
    font-size: var(--tds-font-size-caption);
}

.app__choices {
    display: flex;
    flex-direction: column;
    gap: var(--tds-space-2);
    margin: var(--tds-space-3) 0 0;
    padding: 0;
    list-style: none;
}

/* ── SUR TÉLÉPHONE ───────────────────────────────────────────────────────── */

@media (max-width: 47.99rem) {
    .app__explore {
        margin-block-end: 0;
    }

    /*
     * Les thèmes tiennent sur UNE ligne qui défile, et c'est une exception
     * DÉCLARÉE au Design System (design-system.json) : sa règle de chip veut
     * qu'une rangée passe à la ligne. Sur une carte de téléphone, sept puces
     * sur trois lignes couvriraient 150 px de territoire sous le pouce. Le
     * bord qui s'estompe dit qu'il en reste ; aucune puce n'est inatteignable.
     */
    .app__themes {
        width: auto;
        max-width: none;
        margin-inline: calc(-1 * var(--tds-space-3));
    }

    .app__themes-list {
        flex-wrap: nowrap;
        overflow-x: auto;
        padding: var(--tds-space-1) var(--tds-space-3);
        scroll-padding-inline: var(--tds-space-3);
        scrollbar-width: none;
        mask-image: linear-gradient(to right, transparent 0, currentColor var(--tds-space-3), currentColor calc(100% - var(--tds-space-6)), transparent 100%);
    }

    .app__themes-list::-webkit-scrollbar {
        display: none;
    }

    .app__theme-panel {
        max-height: 38dvh;
        padding-block: var(--tds-space-1);
    }

    .app__card {
        overflow-y: auto;
    }

    /* Une fiche ouverte en bas : les commandes remontent au-dessus d'elle. */
    html[data-app-fiche] .app__rail,
    html[data-app-fiche] .app .maplibregl-ctrl-top-right {
        visibility: hidden;
    }
}

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

/*
 * ── UN TÉLÉPHONE EN PAYSAGE ─────────────────────────────────────────────────
 *
 * 844 × 390 : assez LARGE pour la mise en page d'ordinateur, trop BAS pour
 * elle. Mesuré le 2026-09-13 : en-tête, recherche et deux lignes de thèmes
 * laissaient 120 px à la fiche. Sous 32 rem de haut, les thèmes tiennent sur une
 * ligne qui défile, et une fiche ouverte les remplace — la colonne entière est
 * alors à elle.
 */
@media (max-height: 32rem) and (min-width: 48rem) {
    .app__explore {
        margin-block-start: calc(env(safe-area-inset-top) + var(--app-header-h) + var(--tds-space-1));
        gap: var(--tds-space-1);
    }

    .app__themes {
        width: auto;
        max-width: none;
    }

    .app__themes-list {
        flex-wrap: nowrap;
        overflow-x: auto;
        scrollbar-width: none;
    }

    html[data-app-fiche] .app__themes {
        display: none;
    }
}

/*
 * ══════════════════════════════════════════════════════════════════════════
 * LE PANNEAU DE CONTEXTE — 0.25.0
 * ══════════════════════════════════════════════════════════════════════════
 *
 * Un seul conteneur pour les résultats, la liste de choix, la fiche, les
 * couches et le thème — une vue à la fois (public/js/lib/panneau.mjs). Il
 * reprend l'habit des cartes de la colonne : les vues qu'il porte perdent le
 * leur, pour qu'on ne lise pas une carte dans une carte.
 *
 * Grand écran : la colonne sous la recherche, qui s'arrête au-dessus de
 * l'attribution. Téléphone : une feuille inférieure à trois crans, dont la
 * hauteur est posée par le runtime (`poserFeuille()`) et suivie par le rail.
 * Les primitives restent celles du gabarit candidat « map-workspace » du Design
 * System ; la feuille à crans y est proposée (docs/audit-ux-0.25.md, dettes).
 */

.app__context {
    position: relative;
    flex: 0 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    background: var(--tds-surface-default);
    border: var(--tds-border-width-default) solid var(--tds-border-default);
    border-radius: var(--tds-radius-role-surface);
    box-shadow: var(--tds-elevation-medium);
}

.app__context[hidden] {
    display: none;
}

.app__context-views {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
}

.app__context .app__theme-panel,
.app__context .app__card {
    border: 0;
    border-radius: 0;
    box-shadow: none;
    background: transparent;
    overflow: visible;
}

.app__context .app__card {
    position: relative;
}

.app__results,
.app__layers-view {
    padding: var(--tds-space-3) var(--tds-space-4) var(--tds-space-4);
}

.app__results-head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--tds-space-2);
    margin-block-end: var(--tds-space-2);
}

/* Même hiérarchie dans les résultats, les couches et les thèmes. */
.app__results-head h2 {
    margin: 0;
    font-size: var(--tds-font-size-heading4);
    line-height: var(--tds-line-height-heading);
    overflow-wrap: anywhere;
}

.app__results-head h2:focus {
    outline: none;
}

.app__results-head h2:focus-visible {
    outline: var(--tds-focus-width) solid var(--tds-border-focus);
    outline-offset: var(--tds-focus-offset);
}

.app__results-group + .app__results-group {
    margin-block-start: var(--tds-space-3);
}

.app__results-zone {
    width: 100%;
    margin-block-end: var(--tds-space-3);
}

.app__results-zone[hidden] {
    display: none;
}

.app__result.is-current {
    border-color: var(--tds-brand-primary);
}

/*
 * ── LE PIED, DANS LE PANNEAU ───────────────────────────────────────────────
 *
 * Le bloc est `tds-footer`, celui de toutes les pages. Ce qui est écrit ici
 * n'est que sa PLACE : collé au bas de la vue « Couches », visible sans faire
 * défiler les couches, sur toute la largeur du panneau. Il ne coûte rien à la
 * carte — il n'existe que panneau ouvert.
 */
.app__foot {
    position: sticky;
    inset-block-end: 0;
    margin: var(--tds-space-4) calc(-1 * var(--tds-space-4)) calc(-1 * var(--tds-space-4));
    background: var(--tds-surface-default);
}

.app__foot .tds-footer__inner {
    padding-inline: var(--tds-space-4);
}

.app__layers-base {
    margin-block-end: var(--tds-space-4);
}

.app__layers-base-choices {
    display: flex;
    flex-wrap: wrap;
    gap: var(--tds-space-2);
    margin-block: var(--tds-space-1) var(--tds-space-2);
}

.app__base--compact {
    flex: 1 1 8rem;
    min-height: var(--tds-touch-target-web);
}

.app__object-explore {
    display: flex;
    flex-wrap: wrap;
    gap: var(--tds-space-2);
}

/* La poignée n'a rien à dire sur grand écran : rien ne se tire. */
.app__sheet-grip {
    display: none;
}

/* Le bouton « Couches » ouvert se lit sans la couleur : contour appuyé. */
.app__tool.is-active {
    border-color: var(--tds-brand-primary);
    border-width: var(--tds-border-width-accent);
    color: var(--tds-text-primary);
}

/* Une station choisie : un anneau épais ET un grossissement — pas une teinte. */
.app__station.is-selected {
    outline: 3px solid var(--tds-border-focus);
    outline-offset: 2px;
    transform: scale(1.15);
    z-index: 2;
}

/* Le panneau de mobilité se ferme vraiment (0.24.0 : la classe n'avait aucune règle). */
.app__panel.app__panel--closed {
    display: none;
}

@media (max-width: 47.99rem) {
    /*
     * La FEUILLE. Elle quitte la colonne pour la géométrie (`fixed`) et y reste
     * pour l'ordre de lecture et du clavier. Sa hauteur vient du runtime ; la
     * transition la rend lisible, et `prefers-reduced-motion` la retire.
     */
    .app__context {
        position: fixed;
        inset-inline: 0;
        inset-block-end: 0;
        z-index: 8;
        height: 50dvh;
        max-height: calc(100dvh - var(--app-header-h, 3.5rem));
        margin: 0;
        border-radius: 0;
        border-inline: 0;
        border-block-end: 0;
        border-start-start-radius: var(--tds-radius-xl, 1rem);
        border-start-end-radius: var(--tds-radius-xl, 1rem);
        box-shadow: var(--tds-elevation-high);
        transition: height 180ms ease;
    }

    .app__context.is-dragging {
        transition: none;
    }

    .app__context-views {
        padding-block-end: env(safe-area-inset-bottom);
    }

    /* Réduite, la feuille ne montre que l'en-tête de sa vue : pas de défilement caché. */
    .app__context[data-cran="reduit"] .app__context-views {
        overflow: hidden;
    }

    .app__sheet-grip {
        display: grid;
        place-items: center;
        flex: 0 0 auto;
        width: 100%;
        min-height: var(--tds-touch-target-web);
        margin: 0;
        padding: 0;
        border: 0;
        background: transparent;
        cursor: grab;
        touch-action: none;
    }

    .app__sheet-grip:focus-visible {
        outline: var(--tds-focus-width) solid var(--tds-border-focus);
        outline-offset: calc(-1 * var(--tds-focus-width));
    }

    .app__sheet-grip-bar {
        width: 2.5rem;
        height: 0.25rem;
        border-radius: var(--tds-radius-full);
        background: var(--tds-border-strong);
    }

    .app__context .app__card {
        position: relative;
        inset: auto;
        z-index: auto;
        max-height: none;
        padding-block-start: 0;
        padding-block-end: var(--tds-space-4);
    }

    .app__context .app__theme-panel {
        max-height: none;
        padding-block-start: 0;
    }

    .app__results,
    .app__layers-view {
        padding-block-start: 0;
    }

    /*
     * Le rail et le zoom ne DISPARAISSENT plus sous une fiche (0.24.0 : cachés) :
     * ils montent au-dessus de la feuille, quelle que soit sa hauteur, tant
     * qu'elle laisse de la place ; en plein cran, ils se retirent.
     */
    html[data-app-fiche] .app__rail,
    html[data-app-fiche] .app .maplibregl-ctrl-top-right {
        visibility: visible;
    }

    /*
     * Tout ce qui est posé en bas de la carte se pose AU-DESSUS de la feuille :
     * l'attribution d'abord — une mention ne se cache jamais sous un panneau,
     * règle du gabarit —, puis l'échelle, le zoom et le rail. `--app-sheet-h`
     * vaut 0 sans feuille ; la zone de sécurité du bas prend alors le relais.
     */
    .app__attribution {
        inset-block-end: var(--app-sheet-h, 0px);
    }

    .app .maplibregl-ctrl-bottom-left {
        inset-block-end: calc(max(env(safe-area-inset-bottom), var(--app-sheet-h, 0px)) + var(--app-attribution-h, 2.25rem));
    }

    .app__rail {
        margin-block-end: calc(
            max(env(safe-area-inset-bottom), var(--app-sheet-h, 0px)) + var(--app-attribution-h, 2.75rem)
            + var(--tds-space-2) + 5.5rem + var(--tds-space-3)
        );
    }

    .app .maplibregl-ctrl-top-right {
        inset-block-end: calc(max(env(safe-area-inset-bottom), var(--app-sheet-h, 0px)) + var(--app-attribution-h, 2.75rem) + var(--tds-space-2));
    }

    html:has(.app__context[data-cran="plein"]:not([hidden])) .app__rail,
    html:has(.app__context[data-cran="plein"]:not([hidden])) .app .maplibregl-ctrl-top-right,
    html:has(.app__context[data-cran="plein"]:not([hidden])) .app__legend {
        visibility: hidden;
    }

    /* La légende : au-dessus de l'attribution et de la feuille, repliée par défaut, jamais sur le rail. */
    .app__legend {
        inset-inline-end: auto;
        inset-inline-start: var(--tds-space-3);
        max-width: calc(100% - 2 * var(--tds-space-3) - 3.5rem);
        inset-block-end: calc(var(--app-sheet-h, 0px) + var(--app-attribution-block, var(--tds-space-6)) + var(--tds-space-2));
    }
}

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

    .app__station.is-selected {
        transform: none;
    }
}

/* La liste de suggestions passe au-dessus du panneau et de la feuille qu'elle chevauche. */
.app__search {
    z-index: 9;
}

/* « ← Résultats » : la flèche et le mot, séparés. */
.app__object-back {
    display: inline-flex;
    align-items: center;
    gap: var(--tds-space-1);
    min-height: var(--tds-touch-target-web);
}

/* Les puces d'une fiche (« Explorer autour ») : une cible de doigt sur écran tactile. */
@media (pointer: coarse) {
    .app__object-explore .app__chip {
        min-height: var(--tds-touch-target-web);
    }
}

@media (max-width: 47.99rem) {
    /*
     * Une fiche, une liste de résultats ou les couches ouvertes en feuille :
     * les puces de thème se retirent (≈ 50 px de carte rendus) ; elles
     * reviennent à la fermeture. La recherche, elle, reste.
     */
    html:has(.app__context:not([hidden]):is([data-vue="fiche"], [data-vue="choix"], [data-vue="resultats"], [data-vue="couches"])) .app__themes {
        display: none;
    }
}

/* L'échelle ne passe pas sous le panneau de contexte ouvert (grand écran). */
@media (min-width: 48rem) {
    html:has(.app__context:not([hidden])) .app .maplibregl-ctrl-bottom-left {
        inset-inline-start: calc(min(26rem, 100vw - 2 * var(--tds-space-3)) + 2 * var(--tds-space-3));
    }
}

/* La consultation Transit laisse la carte et ses commandes accessibles. */
.app > .app__transit {
    position: absolute;
    z-index: 7;
    inset-block-start: calc(var(--app-header-h) + var(--tds-space-3));
    inset-inline-end: var(--tds-space-3);
    width: min(22rem, calc(100% - 2 * var(--tds-space-3)));
    max-height: calc(100% - var(--app-header-h) - 4rem);
    overflow: visible;
    align-self: start;
    justify-self: end;
    background: var(--tds-surface-default);
    border-radius: var(--tds-radius-lg);
    box-shadow: var(--tds-elevation-medium);
    padding: var(--tds-space-3);
}
.app__transit-scroll {
    max-height: calc(100dvh - var(--app-header-h) - 4rem - 2 * var(--tds-space-3));
    overflow: auto;
    overscroll-behavior: contain;
}
.app__transit [data-app-transit-filter] {
    display: block;
    width: 100%;
    margin-block-end: var(--tds-space-2);
}
@media (max-width: 600px) {
    .app > .app__transit {
        inset-block-start: auto;
        inset-block-end: calc(var(--app-attribution-block, 2rem) + var(--tds-space-2));
        inset-inline: var(--tds-space-2);
        width: auto;
        max-height: 42dvh;
    }
    .app__transit-scroll {
        max-height: calc(42dvh - 2 * var(--tds-space-3));
    }
}

/* Composition métier : identité compacte, choix du point, heures, catalogue.
   Les boutons, champs et disclosures sont ceux du DS vendorisé. */
.app__transit-scroll { display: flex; flex-direction: column; }
.app__transit-close { align-self: start; }
.app__transit [data-app-transit-card-body] { order: 0; }
.app__transit [data-app-transit-geometry] { order: 1; }
.app__transit [data-app-transit-status] { order: 2; margin-block: var(--tds-space-3); color: var(--tds-text-secondary); font-size: var(--tds-font-size-body-small); }
.app__transit [data-app-transit-status]:empty { display: none; }
.app__transit [data-app-transit-filters] { order: 3; }
.app__transit [data-app-transit-sources] { order: 4; }
.app__transit .app__card-title { margin: 0 0 var(--tds-space-1); font-size: var(--tds-font-size-heading4); line-height: 1.2; overflow-wrap: anywhere; }
.app__transit [data-app-transit-card-body] > h3,
.app__transit-board > h3,
.app__transit-catalogue > h3 { margin: 0 0 var(--tds-space-2); font-size: var(--tds-font-size-body-large); font-weight: var(--tds-font-weight-semibold); }
.app__transit-board { margin-block: var(--tds-space-3); }
.app__transit-catalogue { margin-block: var(--tds-space-4); border-block-start: var(--tds-border-width-default) solid var(--tds-border-default); padding-block-start: var(--tds-space-3); }
.app__transit-mode { margin: var(--tds-space-2) 0 var(--tds-space-1); font-size: var(--tds-font-size-body-small); font-weight: var(--tds-font-weight-semibold); color: var(--tds-text-secondary); }
.app__transit-service,
.app__transit-line { padding-block: var(--tds-space-2); border-block-start: var(--tds-border-width-default) solid var(--tds-border-default); overflow-wrap: anywhere; }
.app__transit-service-heading { display: flex; gap: var(--tds-space-2); align-items: start; margin-block-end: var(--tds-space-1); }
.app__transit-service-heading > div { min-width: 0; }
.app__transit-sign { flex: 0 0 auto; justify-content: center; min-width: 2.5rem; min-height: 2rem; font-variant-numeric: tabular-nums; }
.app__transit-passage { display: grid; grid-template-columns: 4rem minmax(0, 1fr); gap: var(--tds-space-2); padding-block: var(--tds-space-2); }
.app__transit-passage + .app__transit-passage { border-block-start: var(--tds-border-width-default) solid var(--tds-border-default); }
.app__transit-time { font-size: var(--tds-font-size-heading4); font-weight: var(--tds-font-weight-bold); line-height: 1.2; font-variant-numeric: tabular-nums; }
.app__transit-quality { display: block; font-weight: var(--tds-font-weight-semibold); }
.app__transit-note { display: block; color: var(--tds-text-secondary); font-size: var(--tds-font-size-body-small); line-height: 1.4; margin-block: var(--tds-space-1); }
.app__transit-action { margin-block: var(--tds-space-1); max-width: 100%; white-space: normal; overflow-wrap: anywhere; text-align: start; }
.app__transit-search { margin-block: var(--tds-space-2); }
.app__transit .tds-disclosure { margin-block-start: var(--tds-space-2); }
.app__transit .tds-field + .tds-field { margin-block-start: var(--tds-space-2); }
.app__transit [hidden] { display: none !important; }
@media (min-width: 601px) { .app > .app__transit { width: min(26rem, calc(100% - 2 * var(--tds-space-3))); } }
@media (max-width: 600px) {
    .app > .app__transit { max-height: 52dvh; }
    .app__transit-scroll { max-height: calc(52dvh - 2 * var(--tds-space-3)); }
}
.app__transit-point--selected { outline: var(--tds-focus-width) solid var(--tds-border-focus); outline-offset: var(--tds-focus-offset); font-weight: var(--tds-font-weight-bold); }

.app__transit-navigation { display: flex; flex-wrap: wrap; align-items: center; gap: 0 var(--tds-space-2); margin-block: 0 var(--tds-space-1); }
.app__transit-navigation .app__link { display: inline-flex; align-items: center; min-height: var(--tds-touch-target-web); }

.app__transit-members { display: flex; flex-direction: column; align-items: flex-start; gap: var(--tds-space-2); margin-block: var(--tds-space-2); }
.app__transit-members > .app__link { min-height: 44px; text-align: start; }

.app__transit-passage .app__link { display: inline-flex; align-items: center; min-height: var(--tds-touch-target-web); }

.app__transit-points [data-app-transit-select-point] { display: flex; flex-direction: column; align-items: flex-start; gap: var(--tds-space-1); width: 100%; }
.app__transit-point-reference { font-size: var(--tds-font-size-caption); font-weight: var(--tds-font-weight-regular); overflow-wrap: anywhere; }

/* L’identité et Fermer réservent leurs largeurs réelles pendant toute la lecture.
   La peinture du bandeau est bornée, avec un espace pour le contour de focus DS. */
.app__transit-identity-header {
    display: grid;
    grid-template-columns: minmax(0, 1fr) max-content;
    align-items: start;
    gap: var(--tds-space-2);
    flex: 0 0 auto;
    position: sticky;
    inset-block-start: 0;
    z-index: 2;
    min-height: var(--tds-touch-target-web);
    background: var(--tds-surface-default);
    contain: paint;
    overflow-clip-margin: calc(var(--tds-focus-width) + var(--tds-focus-offset));
    padding: calc(var(--tds-focus-width) + var(--tds-focus-offset));
}
.app__transit-identity-content { min-width: 0; overflow-wrap: anywhere; }


/* Filtre d'enseigne, commun aux magasins dessinés et à la recherche. */
.app__shops { min-width: 0; color: var(--tds-text-primary); padding-block: var(--tds-space-2); }
.app__shops[hidden] { display: none; }
.app__shops label { display: block; margin-block-end: var(--tds-space-3); }
.app__shops select { display: block; width: 100%; min-height: 44px; font: inherit; font-size: max(1rem, 16px); color: inherit; background: var(--tds-surface-default); padding: 8px; }
.app__shops p { font-size: 0.85rem; margin-block-end: 0; }

.app__shop-hours table { width: 100%; margin-block: .75rem; border-collapse: collapse; }
.app__shop-hours th, .app__shop-hours td { padding: .3rem .4rem; text-align: start; vertical-align: top; }
.app__shop-hours th { font-weight: 500; }
.app__shop-hours label { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; }
.app__shop-hours input { width: auto; max-width: 100%; }

.app__shops-legend { font-size: .8rem; display: flex; flex-wrap: wrap; gap: .4rem .7rem; }
.app__shops-legend span { display: inline-flex; gap: .3rem; align-items: center; }
.app__shop-swatch { width: .75rem; height: .75rem; border-radius: 50%; background: var(--tds-data-3); border: 1px solid var(--tds-text-primary); }
.app__shops summary { cursor: pointer; min-height: 44px; padding-block: .75rem; font-size: .9rem; }
.app__shops-provenance a, .app__shops-references a { display: inline-flex; align-items: center; min-height: 44px; }

/* La recherche passe devant les commandes, y compris hors de la colonne. */
.app__explore:has([data-app-search][aria-expanded="true"]) { z-index: 10; }
.app__suggestions { max-height: min(60dvh, calc(100dvh - var(--app-header-h) - 5rem)); overscroll-behavior: contain; }

/* Les sorties et actions secondaires ont la même cible que les interrupteurs. */
.app__context .app__close { flex: 0 0 auto; min-width: 44px; min-height: 44px; }
.app__context .app__link,
.app__context .app__theme-layer-info { display: inline-flex; align-items: center; justify-content: center; min-height: 44px; min-width: 44px; }

@media (max-width: 47.99rem) {
    /* Conserver les couches si une seule commande tient ; réduire la feuille
     * rend les autres commandes. Les gestes de carte restent disponibles. */
    html[data-app-controls="compact"] .app__rail {
        margin-block-end: calc(var(--app-sheet-h, 0px) + var(--app-attribution-h, 2.75rem) + var(--tds-space-2));
    }
    html[data-app-controls="compact"] [data-app-locate] { display: none; }
    html[data-app-controls="compact"] .app .maplibregl-ctrl-top-right,
    html[data-app-controls="hidden"] .app .maplibregl-ctrl-top-right,
    html[data-app-controls="hidden"] .app__rail { visibility: hidden; }
    .app:has([data-app-search][aria-expanded="true"]) .app__rail,
    .app:has([data-app-search][aria-expanded="true"]) .maplibregl-ctrl-top-right { visibility: hidden; }
}

.app__shop-logo { margin: 0 0 1rem; }
.app__shop-logo img { width: 96px; height: 64px; object-fit: contain; }
.app__shop-logo [hidden] { display: none; }
.app__shop-logo figcaption { font-size: .75rem; overflow-wrap: anywhere; }


/* Libellés et séparation : indépendants des polices du fond cartographique. */
.app__point-names, .app__point-fan { position: absolute; inset: 0; pointer-events: none; z-index: 2; overflow: hidden; }
.app__point-names [hidden] { display: none; }
.app__point-name { position: absolute; height: 24px; padding: 0 4px; border: 0; background: none; color: var(--tds-text-primary); font: 500 12px/24px system-ui; text-align: start; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; text-shadow: -1px -1px var(--tds-surface-default), 1px -1px var(--tds-surface-default), -1px 1px var(--tds-surface-default), 1px 1px var(--tds-surface-default); pointer-events: auto; cursor: pointer; }
.app__point-name:focus-visible { outline: var(--tds-focus-width) solid var(--tds-border-focus); background: var(--tds-surface-default); }
.app__point-links { position: absolute; width: 100%; height: 100%; overflow: visible; }
.app__point-links line { stroke: var(--tds-text-secondary); stroke-width: 1.5; }
.app__point-separated { position: absolute; display: flex; align-items: center; gap: 8px; height: 48px; padding: 2px 8px 2px 2px; border: 1px solid var(--tds-border-default); border-radius: var(--tds-radius-lg); background: var(--tds-surface-default); color: var(--tds-text-primary); pointer-events: auto; cursor: pointer; text-align: start; font: 500 13px/1.3 system-ui; }
.app__point-separated > span:last-child { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; overflow-wrap: anywhere; }
.app__point-badge { flex: 0 0 42px; height: 42px; display: grid; place-items: center; border-radius: 50%; background: var(--tds-surface-sunken); }
.app__point-badge svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 2; }
.app__point-separated:focus-visible, .app__point-pager button:focus-visible { outline: var(--tds-focus-width) solid var(--tds-border-focus); outline-offset: var(--tds-focus-offset); }
.app__point-pager { position: absolute; display: flex; align-items: center; gap: 4px; min-height: 44px; pointer-events: auto; border-radius: var(--tds-radius-md); background: var(--tds-surface-default); color: var(--tds-text-primary); font: 12px/1.2 system-ui; }
.app__point-pager button { min-width: 44px; min-height: 44px; border: 0; background: none; color: inherit; cursor: pointer; }
@media (pointer: coarse) { .app__point-name { pointer-events: none; } }
