/* @grammaire v2
   ══════════════════════════════════════════════════════════════
   ANNUAIRE — le hub des trois annuaires

   Maquette « Annuaire hub ANCESU », tour 1. Le reproche central : la page se
   DECRIVAIT au lieu d'orienter. Six écrans de prose, de chiffres et de cartes
   d'aiguillage avant le premier nom de centre, et quatre fois la même promesse
   reformulée.

   Ce que la feuille habille désormais : la recherche posée DANS la carte de
   tête (elle vivait dans un bloc à part, sur un fond teinté qui n'appartenait à
   aucune surface de la grammaire), les trois sections qui montrent ce qu'elles
   contiennent, et la colonne d'appui où la carte descend au même rang que sur
   l'annuaire des CESU.

   Ce qui n'est PAS ici, et c'est le sens de la refonte : les cartes
   d'aiguillage sont des `_rail_card`, les en-têtes de section des
   `_section_header`, les jetons de portée un `_pill_group`, les surfaces des
   `ui-card`, les filets et pastilles des macros `ui.*`. Sont mortes avec leur
   balisage la bande de quatre grands chiffres, la grille « trois façons de s'y
   retrouver » et la bande d'appel marine de pied de page.

   UNE DEPENDANCE A CONNAITRE AVANT DE RENOMMER QUOI QUE CE SOIT ICI :
   `.directory-index__finder-item*` est construit par `createNearestCesuSearch`
   dans `assets/app.js` — c'est du JavaScript qui BATIT ces nœuds, pas une
   feuille qui les habille. Les renommer casserait l'autocomplétion sans
   qu'aucun lint ne le signale.
   ══════════════════════════════════════════════════════════════ */

/* ══ LA RECHERCHE, DANS LA CARTE DE TETE ═════════════════════════ */

/* LE CHAMP EST LA BRIQUE PARTAGEE (`_search_field`) : hauteur, loupe, bouton,
   anneau de focus et croix d'effacement viennent de la, et rien n'en est
   redeclare ici. Ce qui suit ne fait que le POSER dans le rang — sa borne, la
   place du bouton voisin, et la liste de propositions qu'il accueille dans sa
   fente.

   Un champ ecrit a la main avait recree deux defauts que la brique corrige avec
   leur docblock : l'anneau de focus autour de la seule saisie, dans le cadre,
   et trois hauteurs calculees a trois endroits. */
.directory-hub__seek {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-ms);
    margin-top: var(--spacing-lg);
}

.directory-hub__seek-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--spacing-sm);
}

/* LE CHAMP EST BORNE. `search-field` prend `width: 100%` : sans borne il occupe
   toute la carte, et une ligne de saisie de mille pixels pour trois mots
   annonce un formulaire plutot qu'une recherche. */
.directory-hub__field {
    flex: 1 1 18rem;
    max-width: 30rem;
    min-width: 0;
}

.directory-hub__geo {
    flex: none;
    gap: var(--spacing-xs);
}

/* ── LA LISTE DE PROPOSITIONS ──
   Elle est POSITIONNEE ici et PEUPLEE par le script : son contenu depend d'une
   requete et de la frappe, le serveur ne peut pas le connaitre.

   Sa reference est `search-field__group`, le CADRE du champ, parce que la
   brique l'accueille dans sa fente `autocomplete_html`. Posee en soeur du
   formulaire, elle prenait le rang entier pour reference : mille cent pixels de
   large sous un champ de trois cents. */
.directory-hub__suggestions {
    position: absolute;
    left: 0;
    right: 0;
    top: calc(100% + var(--spacing-xs));
    margin: 0;
    list-style: none;
    padding-block: var(--spacing-2xs);
    background: var(--surface-2);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-md);
    z-index: var(--z-dropdown, 20);
    max-height: 18rem;
    overflow-y: auto;
}

.directory-index__finder-item {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--spacing-md);
    padding: var(--spacing-xs) var(--spacing-md);
    cursor: pointer;
    transition: background 0.1s;
}

.directory-index__finder-item--active,
.directory-index__finder-item:hover {
    background: var(--color-section-cesu-light);
}

.directory-index__finder-item-label {
    font-size: var(--font-size-sm);
    font-weight: 600;
    color: var(--color-text);
}

/* Le code postal est une VALEUR, pas de la prose : chasse fixe, comme les
   matricules de centre et les comptes de la page. */
.directory-index__finder-item-meta {
    flex: none;
    font-family: var(--font-data);
    font-size: var(--font-size-xs);
    color: var(--color-text-light);
}

/* ══ LE CORPS : DEUX COLONNES ════════════════════════════════════ */

/* L'ECART APPARTIENT A CE QUI SUIT, JAMAIS A CE QUI PRECEDE — regle posee avec
   `--rhythm-*` dans `theme.css`, et c'est elle qui vide le rembourrage HAUT :
   `.content-header` paie deja sa gouttiere basse (`--card-gap`), et les deux
   s'AJOUTAIENT. Mesure avant correction : 32 px de trop entre la carte de tete
   et la premiere section.

   En bas, RIEN non plus, et pour la meme raison : `.subscriptions`, le bandeau
   qui suit, declare `padding-block: var(--rhythm-block) 0` avec un commentaire
   qui dit pourquoi — « le bandeau porte desormais tout l'ecart ». Les 48 px
   qu'on posait ici s'y AJOUTAIENT : 96 px entre la derniere section et le
   bandeau, mesures, pour un ecart de bloc qui en vaut 48.

   Une page qui ne paie NI en haut NI en bas n'est pas une page sans rythme :
   c'est une page dont les deux voisins ont declare le leur. */
.directory-hub {
    padding-block: 0;
}

.directory-hub__body {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--spacing-xl);
    align-items: start;
}

/* `--rhythm-section` : deux sections d'un meme bloc. `--spacing-2xl` valait la
   meme chose qu'un ecart de BLOC, donc les trois sections se lisaient comme
   trois pages posees l'une sous l'autre. */
.directory-hub__main {
    display: flex;
    flex-direction: column;
    gap: var(--rhythm-section);
    min-width: 0;
}

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

/* DEUX ECARTS S'AJOUTAIENT sous chaque titre de section : les 24 px de marge
   basse de `_section_header` et les 16 px de gouttiere de la colonne, soit 40
   entre un titre et ce qu'il annonce. La brique garde sa marge pour ses autres
   appelants ; ici c'est la colonne qui rythme, donc la marge tombe. Meme regle
   que `--rhythm-*` : un seul des deux voisins paie l'ecart. */
.directory-hub__section > .section-header {
    margin-bottom: 0;
}

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

/* La colonne d'appui ne devient une COLONNE qu'à partir du palier où elle a la
   place de l'être. En dessous, elle suit le corps — et elle le suit APRES, ce
   qui est l'ordre du source : la carte et les rebonds accompagnent, ils
   n'introduisent pas. */
@media (width >= 62em) {
    .directory-hub__body {
        grid-template-columns: minmax(0, 1fr) 21rem;
    }

    .directory-hub__rail {
        position: sticky;
        top: var(--spacing-lg);
    }
}

/* ══ LES CESU ════════════════════════════════════════════════════ */

/* L'ETAT DE REPOS. Il ne s'excuse pas d'être vide : il demande la seule chose
   qui permette de montrer un centre plutôt qu'un autre. Le voile de niveau 3 le
   distingue des fiches, qui sont des cartes pleines. */
.directory-hub__prompt {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--spacing-md);
    padding: var(--spacing-lg);
    background: var(--surface-3);
    border-radius: var(--radius-lg);
}

.directory-hub__prompt-text {
    flex: 1 1 20rem;
    margin: 0;
    font-size: var(--font-size-sm);
    line-height: var(--line-height-base);
    color: var(--color-text);
}

.directory-hub__located {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-sm);
}

.directory-hub__note {
    margin: 0;
    font-size: var(--font-size-sm);
    color: var(--color-text-light);
}

.directory-hub__cesu-list {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-sm);
}

/* ── UNE FICHE DE CENTRE ──
   Construite par le script, à partir du magasin de localisation : cette page
   est mémorisée entière par le cache pleine page, donc le serveur ne peut pas
   écrire le centre d'un visiteur sans le montrer à tous les suivants. */
.directory-hub__cesu {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    gap: var(--spacing-sm) var(--spacing-lg);
    align-items: center;
    padding: var(--spacing-md) var(--spacing-lg);
    background: var(--surface-2);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
}

.directory-hub__cesu-main {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-xs);
    min-width: 0;
}

.directory-hub__cesu-head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--spacing-2xs) var(--spacing-sm);
}

/* Le matricule IDENTIFIE, il ne nomme pas : chasse fixe, au-dessus de la ville,
   comme sur les fiches de l'annuaire des CESU. */
.directory-hub__cesu-code {
    font-family: var(--font-data);
    font-size: var(--font-size-xs);
    color: var(--color-text-light);
}

.directory-hub__cesu-city {
    margin: 0;
    font-size: var(--font-size-lg);
    font-weight: 700;
    line-height: var(--line-height-tight);
    color: var(--color-primary-dark);
}

.directory-hub__cesu-actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--spacing-2xs);
    justify-content: flex-end;
}

@media (width < 36em) {
    .directory-hub__cesu {
        grid-template-columns: minmax(0, 1fr);
    }

    .directory-hub__cesu-actions {
        justify-content: flex-start;
    }
}

/* ── LE LIEN DE PIED DE SECTION EST `section-header__link` ──

   Il en avait recopie tout le dessin : meme `inline-flex`, meme gouttiere, meme
   graisse, meme fleche. Trois declarations pour un seul objet — la brique, ce
   lien-ci, et celui de la carte — dont deux dans une feuille de zone.

   Il porte donc la classe de la brique, et il ne reste ici que ce qui releve de
   sa PLACE : un pied de section est dans une colonne flex, qui l'etirerait sans
   `align-self`. Le seuil de cible tactile part avec le reste : la brique rend
   25 px, mesures sur l'accueil, la ou ces liens en rendaient 18.

   Le libelle vit dans un `<span>` parce que le script le REECRIT
   (`data-hub-more`) : ecrire dans le lien entier emporterait le pictogramme. */
.directory-hub__more,
.directory-hub__map-link {
    align-self: flex-start;
}

.directory-hub__more svg,
.directory-hub__map-link svg {
    flex: none;
    transition: transform 0.15s;
}

.directory-hub__more:hover svg,
.directory-hub__map-link:hover svg {
    transform: translateX(2px);
}

@media (prefers-reduced-motion: reduce) {
    .directory-hub__more svg,
    .directory-hub__map-link svg {
        transition: none;
    }

    .directory-hub__more:hover svg,
    .directory-hub__map-link:hover svg {
        transform: none;
    }
}

/* ══ LES RESU ════════════════════════════════════════════════════ */

.directory-hub__network {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-xs);
}

.directory-hub__network-head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--spacing-sm);
    margin: 0;
}

.directory-hub__network-count {
    font-family: var(--font-data);
    font-size: var(--font-size-xs);
    color: var(--color-text-light);
}

.directory-hub__network-title {
    margin: 0;
    font-size: var(--font-size-xl);
    font-weight: 700;
    line-height: var(--line-height-tight);
    color: var(--color-primary-dark);
}

.directory-hub__network-actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--spacing-sm);
    margin: var(--spacing-2xs) 0 0;
}

/* ══ LES PARTENAIRES ═════════════════════════════════════════════ */

/* LA GRILLE EST CELLE DE L'ANNUAIRE DES PARTENAIRES (`directory.css`), et rien
   n'est redéclaré ici : la fiche y est la même, elle n'a donc pas à se poser
   autrement. Ses paliers portent sur la FENETRE et non sur la colonne, ce qui
   tient tant que la colonne d'appui ne s'ouvre qu'au-delà. */
.directory-hub__families {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: var(--spacing-sm) var(--spacing-lg);
    margin: 0;
}


/* ══ LA CARTE, DANS LA COLONNE D'APPUI ═══════════════════════════ */

.directory-hub__map-card {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-xs);
}

.directory-hub__map-wrap {
    position: relative;
    margin-top: var(--spacing-2xs);
}

/* ── PAS D'OVERRIDE DE LA GAMME, ET C'EST LA CORRECTION ──

   La feuille forcait `--geo-fond: var(--geo-region)`, soit le CYAN PLEIN, sur
   tous les departements. La regle venait de la carte des REGIONS qu'elle
   remplace : un seul aplat y etait rempli, il fallait qu'il se voie. Sur la
   couche departement, ou 103 aplats sur 103 sont remplis, le meme choix peint
   un bloc cyan uni — plus une carte, une tache.

   `geo-map.css` le dit d'ailleurs en toutes lettres : `--geo-region` est un
   degre de SURVOL, et le cyan plein « n'etait pas fait pour porter une
   echelle ». Le fond de la gamme (24 % sur blanc) est le degre « ce
   departement a un centre » — celui que l'annuaire des CESU emploie, ou il se
   lit. Il n'y avait rien a regler ici, seulement un override a retirer. */

.directory-hub__map-note {
    margin: 0;
    font-size: var(--font-size-xs);
    line-height: var(--line-height-base);
    color: var(--color-text-light);
}

