/* ============================================================================
   Entreprise Atlas — socle du design system
   Réf. : docs/specs/spec-design.md

   Source unique des couleurs, tailles et espacements du site. Les autres
   feuilles (site.css, entreprise.css) ne définissent plus aucun token : elles
   consomment ceux-ci via var().

   ORDRE DE CHARGEMENT — ce fichier est chargé EN DERNIER (base.html, après
   {% block extra_head %}). Ce n'est pas un détail :
   le preflight de Tailwind pose `a { color: inherit; text-decoration: inherit }`,
   et chaque gabarit charge tailwind.css dans extra_head. Un socle chargé en
   premier se ferait écraser sa règle de lien sur toutes les pages Tailwind.

   Les var() se résolvent au calcul, pas à l'analyse : définir les tokens ici
   alors que site.css les utilise plus haut fonctionne sans réserve.
   ========================================================================== */

:root {
  /* ── Palette ────────────────────────────────────────────────────────────
     Douze couleurs. Toute couleur absente d'ici est un bug (spec §2.1). */

  /* Neutres */
  --ca-noir: #000000;              /* fond hero, footer */
  --ca-charbon: #0a0a0a;           /* texte principal, titres */
  --ca-gris-fort: #4a4a4a;         /* texte secondaire, libellés de colonne */
  --ca-gris: #767676;              /* 4.54:1 sur BLANC PUR — aucune marge dès que la
                                      surface est teintée. Pour du texte posé sur un bloc,
                                      utiliser --ca-gris-fort. */
  --ca-filet: rgba(0, 0, 0, 0.12); /* bordures, séparations */
  --ca-surface: #ffffff;           /* fond de carte */
  --ca-surface-2: #f5f5f5;         /* fond de bloc, alternance de ligne */

  /* Accents. Les contrastes indiqués sont vérifiés, ne pas les éclaircir. */
  --ca-jaune: #faff69;   /* Comme TEXTE : sur fond sombre uniquement (1.1:1 sur blanc).
                            Comme APLAT sous du charbon ou comme FILET : sur toute
                            surface (19:1 pour du noir sur jaune) — décision B1 du
                            2026-09-23, spec-design §8.1 : le survol de .ca-action, le
                            repère « aujourd'hui », le bouton primaire d'un formulaire. */
  --ca-jaune-surlignage: rgba(250, 255, 105, 0.45); /* surlignage sur clair */
  --ca-lien: #6e6500;    /* liens sur clair — 5.96:1 blanc, 5.25:1 crème */
  --ca-vert: #087f3f;    /* positif, acquisition — 5.10:1 blanc, 4.68:1 sur #f5f5f5 */
  --ca-rouge: #e00000;   /* négatif, cession — 5.04:1 blanc, 4.62:1 sur #f5f5f5 */

  /* Ces deux valeurs sont les plus VIVES qui tiennent encore 4.5:1 en texte,
     sur blanc comme sur #f5f5f5 — mesuré, pas estimé. Les éclaircir davantage
     casse la lisibilité des chiffres. Le vert plafonne plus bas que le rouge :
     sa luminance perceptuelle pèse 0.7152 contre 0.2126 au rouge, donc il
     devient « trop clair » beaucoup plus tôt à saturation égale.

     Variantes vives — REMPLISSAGES SEULEMENT (barres, pastilles, heatmaps,
     points de carte), où le seuil tombe à 3:1. Jamais pour du texte : #12a150
     n'est qu'à 3.37:1 sur blanc. C'est ce qui permet aux aplats de claquer
     sans rendre les chiffres pâles. */
  --ca-vert-vif: #12a150;
  --ca-rouge-vif: #f03e3e;

  /* ── Typographie — 5 crans, aucune autre taille (spec §2.2) ──────────── */
  --font-mono: "IBM Plex Mono", ui-monospace, monospace;
  --font-sans: "IBM Plex Sans", system-ui, sans-serif;

  --fs-xs: 11px;   /* mono strict : libellé de colonne, unité, source. Plancher. */
  --fs-s: 13px;    /* métadonnées, notes */
  --fs-m: 15px;    /* corps de texte */
  --fs-l: 20px;    /* titre de bloc, valeur mise en avant */
  --fs-xl: 32px;   /* titre de page hors hero */
  --fs-hero: clamp(2.5rem, 5vw, 4rem);   /* plafonné à --fs-xl sous le palier compact, plus bas */

  /* ── Espacement — échelle de 4 px ────────────────────────────────────── */
  --sp-1: 4px;
  --sp-2: 8px;
  --sp-3: 12px;
  --sp-4: 16px;
  --sp-6: 24px;
  --sp-8: 32px;
  --sp-12: 48px;
  --sp-16: 64px;

  --max-width: 72rem;

  /* ── Densité — the vertical rhythm of a page, one number per gap ────────────────────────
     User, 2026-10-02: « a lot of scrolling is required to go through all the content ».
     Measured that day at 1440 px on the plate of 301984563: 5 330 px, 5.9 screens; the frame
     (card padding, gaps between cards, section heads) was 13 % of it, the rows and the stacked
     blocks the rest. Every gap that repeats down a page reads ONE token here, so the density is
     tuned in this block and nowhere else (the atlas pages are built to be adjusted in one
     place, user rule of 2026-09-29).
     The values on `:root` are the base set; the page sets the tighter one in the
     `body:has(.ca-header--atlas)` block below, which every page now takes. */
  --densite-page: 3rem;            /* the frame: rail → first card */
  --densite-gouttiere: 1.25rem;    /* the frame's side padding */
  --densite-carte: 1.25rem;        /* a card's padding, above and below */
  --densite-carte-cote: 1.35rem;   /* a card's padding, left and right */
  --densite-entre-cartes: 1.25rem; /* between two cards */
  --densite-bloc: var(--sp-4);     /* between two blocks of one card: head, band, table */
  --densite-groupe: var(--sp-6);   /* above a sub-title, between two charts */
  --densite-ligne: var(--sp-3);    /* a data line's padding, above and below */
  --densite-cellule: var(--sp-2);  /* a table cell's padding, above and below */
  --densite-repere: 12rem;         /* the narrowest a tile of the repères band may be */

  /* The one number a sticky element under the header needs (spec-design §8.1 decision, B5-4,
     2026-09-29): before this, .planche-rail hardcoded `top: 0`, landing at the exact same
     offset as .ca-header (also `top: 0`) and disappearing under it once both engaged their
     sticky behaviour (z-index 40 under 100) — the review's critical B5 defect. Measured on
     .ca-header's own border-box at the `compact` and `large` paliers (getBoundingClientRect,
     /design/, 2026-09-29): 61px there. A rail once carried an estimate
     (`top: 3.25rem`); this is the real number, as a token so it never drifts out of sync.
     Decision 10 (B3, 2026-09-29): ONE number at every width. The atlas header was 69 px between
     768 and 1023 (the ☰'s 44 px target inside the roomy 12 px padding of the large tier); the
     atlas header now takes the compact padding on the whole folded band (« Header atlas » below),
     so 61 px holds from 360 to 1600 and this token no longer has a tablet value. */
  --header-height: 3.8125rem;   /* 61px */

  /* ── Couche de compatibilité ────────────────────────────────────────────
     site.css et entreprise.css référencent encore ces noms hérités. Ce sont des
     ALIAS, pas des couleurs : ils pointent vers la palette ci-dessus.

     À SUPPRIMER au fur et à mesure — quand plus aucun var(--ca-moutarde) ne
     subsiste, retirer la ligne. Ne jamais y remettre une valeur littérale :
     c'est exactement comme ça que le site s'est retrouvé avec trois jaunes
     concurrents (#FAFF69, #FFD600, #D4A02A).

     Les tokens *-rgb existent pour composer une opacité :
     `rgb(var(--ca-vert-rgb) / 0.1)`. Ils doivent rester synchronisés avec la
     couleur du même nom — d'où les triplets alignés sur la palette. */
  --ca-moutarde: var(--ca-jaune);
  /* Décision B2 du 2026-09-23 (spec-design §8.1) : plus aucun alias littéral. Les trois
     derniers (#ffffb0, #fafafa, #1a1a1a) étaient indiscernables du jeton voisin sur une
     nuance côte à côte ; le dégradé SVG du hero et les survols de bouton prennent le jaune. */
  --ca-moutarde-vif: var(--ca-jaune);
  --ca-moutarde-dim: var(--ca-jaune-surlignage);
  --ca-moutarde-glow: rgba(250, 255, 105, 0.5);
  --ca-moutarde-fonce: var(--ca-lien);
  --ca-moutarde-fonce-2: var(--ca-lien);
  --ca-moutarde-tres-fonce: var(--ca-lien);
  --ca-accent-ink: var(--ca-jaune);

  --ca-blanc: var(--ca-surface);
  --ca-creme: var(--ca-surface);
  --ca-card: var(--ca-surface);
  --ca-card-2: var(--ca-surface);
  --ca-bg-alt: var(--ca-surface-2);
  --ca-hairline: var(--ca-filet);
  --ca-charbon-soft: var(--ca-charbon);

  /* Texte sur fond sombre (cartouche, footer) : la surface, et pour le texte secondaire une
     TEINTE de la surface (blanc à 62 %), pas un jeton de plus. --ca-gris ne tenait que sur le
     noir pur (4.6:1) : sur la bande des repères (blanc à 6 % sur noir, rgb 15 15 15) il tombe
     à 4.21:1, sur l'ancien hero teinté (rgb 20 20 8) à 4.07:1. Le blanc à 62 % tient ≥ 7:1 sur
     ces trois surfaces (mesuré ; l'ancien littéral #9a9a94 tenait 7.5:1). Décision B1 du
     2026-09-23, revue le même jour à B7 (spec-design §8.1). */
  --ca-text-on-dark: var(--ca-surface);
  --ca-text-muted-dark: rgb(var(--ca-blanc-rgb) / 0.62);
  --ca-text-muted: var(--ca-gris-fort);
  --ca-text-muted-light: var(--ca-gris);

  --ca-vert-fonce: var(--ca-vert);
  --ca-rouge-fonce: var(--ca-rouge);
  --ca-rouge-dim: rgba(224, 0, 0, 0.18);

  /* Bleu : plus aucune valeur de la palette. Ces trois alias ne survivent que
     pour les graphes vis-network, réécrits à l'étape 3 (spec §3.7). */
  --ca-bleu: #082577;
  --ca-bleu-vif: #2b52c0;
  --ca-bleu-clair: #8aa4e0;

  --ca-grid-line: rgba(250, 255, 105, 0.1);   /* grille du hero */
  --ca-scanline: rgba(0, 0, 0, 0.02);
  --ca-surface-dark: rgba(250, 255, 105, 0.14);

  --ca-noir-rgb: 0 0 0;
  --ca-blanc-rgb: 255 255 255;
  --ca-moutarde-rgb: 250 255 105;
  --ca-moutarde-fonce-rgb: 110 101 0;
  --ca-lien-rgb: 110 101 0;        /* = --ca-lien : les nuances d'un graphique (B14) */
  --ca-vert-rgb: 18 161 80;      /* = --ca-vert-vif : ces triplets ne servent
                                    qu'à des aplats en opacité (heatmaps) */
  --ca-rouge-rgb: 240 62 62;     /* = --ca-rouge-vif, même raison */
  --ca-bleu-rgb: 8 37 119;
  --ca-bleu-vif-rgb: 43 82 192;
  --ca-text-muted-rgb: 74 74 74;
  --ca-text-muted-light-rgb: 118 118 118;
}

/* The atlas's density (see « Densité » above). `body:has(.ca-header--atlas)` is the atlas's one
   hook (base.html sets the class), the same as the native controls' below.
   What each step buys, measured at 1440 px on 301984563 (2026-10-02):
     · a line 8 px above and below instead of 12: a one-line row 37 px (45), a two-line row
       57 px (65);
     · a table cell 4 px instead of 8: a row 29 px (37), the 20 postes of « Comptes déposés »
       in 580 px (740);
     · a card 16 px inside and 12 px from the next (20 and 20); the frame 16 px under the rail
       (48).
   The 44 px floor of a finger is untouched: it is carried by the links' own min-height and
   by the padding / negative-margin pairs of the touch tier, not by these gaps. */
body:has(.ca-header--atlas) {
  /* ONE row width for the atlas: the header's 86 rem (« Header atlas » below), which the
     indexes took at E0 #15. The plates and the footer were still on the 72 rem of a reading
     page: at 1440 px the header ran 1 376 px wide, the index 1 336 and the plate 1 112, three
     left edges on one site, and 164 px of grey on either side of a plate whose tables wrapped
     (an établissement row was 102 px tall, three lines in « Localisation » and « Activité »).
     A plate is a page of data, not of prose: its sentences keep their own measure
     (`.methode-ligne`, `.definition`, `.cartouche-lead`). The endpapers keep their reading
     column (`.colonne-lecture`). */
  --max-width: 86rem;
  --densite-page: var(--sp-4);
  --densite-carte: var(--sp-4);
  --densite-entre-cartes: var(--sp-3);
  --densite-bloc: var(--sp-3);
  --densite-groupe: var(--sp-4);
  --densite-ligne: var(--sp-2);
  --densite-cellule: var(--sp-1);
  /* 10rem: seven tiles on one row of the 86 rem card (« Synthèse financière » has seven and
     printed them 4 + 3 at 12rem on the 72 rem card, 5 + 2 on this one), six from 1280 px. The
     longest value, « non publié » at --fs-l, is 120 px. */
  --densite-repere: 10rem;
}

/* On a phone the frame and the card took 83 px of a 390 px screen (20 + 21.6 on each side):
   the text column was 305 px and wrapped a label, an address or a ratio's name onto a second
   line in most rows. 12 + 12 px leave 340 px (+11 %); the cartouche's text, which reads the
   same gutter, keeps 12 px from the edge of the screen. Width: tailwind/viewport.json. */
@media (max-width: 767.98px) {
  body:has(.ca-header--atlas) {
    --densite-gouttiere: var(--sp-3);
    --densite-carte-cote: var(--sp-3);
  }
}

/* ============================================================================
   LIENS (spec §2.3)

   Le site n'a que DEUX rôles de lien réellement utilisés :
     1. navigation — mène à une autre entité. C'est le cas par défaut.
     2. action     — bouton. `.ca-action`, plus trois alias historiques.

   La spec prévoit un troisième rôle, « lien secondaire » (pointillé gris pour
   une métadonnée cliquable). La classe `.lien-secondaire` est prête ci-dessous
   mais rien ne l'utilise encore : `.datum-meta`, `.identity-url` et
   `.person-acte-link` sont des <span> et des <p>, pas des liens.

   Ce qu'il ne faut pas refaire : avant, chaque composant réintroduisait un
   soulignement AU SURVOL SEULEMENT. Un lien au repos était typographiquement
   identique au texte courant. Il y avait trois resets `text-decoration: none`
   sur `a` répartis dans deux fichiers.
   ========================================================================== */

/* 1. Navigation — le défaut.
   NB : ne pas ajouter `.mode-lecture a` à cette liste. Dans une liste de
   sélecteurs chacun garde SA spécificité : (0,1,1) écraserait les exclusions
   en (0,1,0) plus bas, comme `.ca-logo`. Le `a` nu suffit. */
a {
  color: var(--ca-lien);
  text-decoration: underline;
  text-decoration-color: var(--ca-lien);
  text-decoration-thickness: 1px;
  text-underline-offset: 0.18em;
  transition: text-decoration-thickness 0.15s ease, background 0.15s ease,
    color 0.15s ease, border-color 0.15s ease;
}

a:hover {
  text-decoration-thickness: 2px;
  background: var(--ca-jaune-surlignage);
}

/* Sur fond sombre. `.mode-terminal` désigne le MODE TYPOGRAPHIQUE et NON un
   fond sombre — sur la home il habille aussi #explorer, #veille et le footer,
   qui sont blancs. Les deux seules surfaces sombres du site sont celles-ci. */
.hero a,
.societe-identity a {
  color: var(--ca-jaune);
  text-decoration-color: rgba(250, 255, 105, 0.5);
  background: none;
}

.hero a:hover,
.societe-identity a:hover {
  text-decoration-color: var(--ca-jaune);
  background: none;
}

/* 3. Lien secondaire — disponible, pas encore employé (voir en-tête de bloc). */
.lien-secondaire {
  color: var(--ca-gris-fort);
  text-decoration-style: dotted;
  text-decoration-color: currentColor;
}

.lien-secondaire:hover {
  color: var(--ca-lien);
  text-decoration-style: solid;
}

/* Native controls: charbon, never the browser's blue (spec-design §2, « no blue anywhere »;
   decision 10, B10 and B16). Measured 2026-09-29: radios and checkboxes carried
   `accent-color: auto` on every atlas index and account form, and only fonds.css set charbon
   for its own slider. One rule for the pages (`.ca-header--atlas` is its hook, base.html) and
   for the forms of /compte/. */
body:has(.ca-header--atlas) input:is([type="checkbox"], [type="radio"], [type="range"]),
.formulaire input:is([type="checkbox"], [type="radio"]) {
  accent-color: var(--ca-charbon);
}

/* Les liens de navigation ne se signalent pas par un soulignement : leur
   repérage vient de leur position. Déclaré après le bloc « fond sombre » pour
   l'emporter à spécificité égale.
   `.planche-rail a` ajouté le 2026-09-29 (revue de design, défaut B5 mineur) : la règle
   d'exclusion existait déjà pour .ca-nav et .societe-nav, deux autres barres de navigation
   par position, mais personne n'avait ajouté le rail du composant §3.3 quand il est né — ses
   17 entrées portaient donc le soulignement `a` de base, plus chargé que l'ancien
   .societe-nav et gênant la lecture du trait de l'entrée courante (Q1 ci-dessous). */
.ca-nav a,
.societe-nav a,
.planche-rail a,
.ca-logo {
  color: var(--ca-gris-fort);
  text-decoration: none;
  background: none;
}

.ca-nav a:hover,
.societe-nav a:hover,
.planche-rail a:hover {
  color: var(--ca-charbon);
  text-decoration: underline;
  text-decoration-color: var(--ca-jaune);
  text-decoration-thickness: 2px;
}

.ca-logo {
  color: var(--ca-charbon);
}

/* 2. Action — bouton. Déclaré en dernier des règles de lien : un bouton reste
   un bouton, y compris posé sur le hero noir.
   `.cta-link`, `.section-link`, `.module-link`, `.fold-toggle`, `.fs-jump` et
   `.fs-more > summary` sont les noms historiques ; `.ca-action` est le nom
   canonique. Le site portait cinq habillages différents pour la même chose :
   pastille jaune arrondie, bouton jaune plein à halo, bouton blanc à filet
   gris… Ils sont ici, une fois. Ne pas en redéclarer un sixième ailleurs. */
.ca-action,
.cta-link,
.section-link,
.module-link,
.fold-toggle,
.fs-jump,
.fs-more > summary {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  line-height: 1.4;
  padding: var(--sp-1) var(--sp-2);
  border: 1px solid var(--ca-lien);
  color: var(--ca-charbon);
  background: transparent;
  text-decoration: none;
  cursor: pointer;
}

.ca-action:hover,
.cta-link:hover,
.section-link:hover,
.module-link:hover,
.fold-toggle:hover,
.fs-jump:hover,
.fs-more > summary:hover {
  background: var(--ca-jaune);
  border-color: var(--ca-jaune);
  color: var(--ca-noir);
  text-decoration: none;
}

/* The hit area of an action inside a section or an index panel (decision 11): the fold
   button, « la pièce › », « l'acte › », « Réinitialiser » measured 25 px tall (spec-design
   §2.4 sets the floor at 44 px on compact). The SURFACE grows, not the type, and only on
   compact and on a tablet with a finger (B17 Q49: `pointer: coarse` under 1024 px); on large
   the visible size is unchanged. Scoped to `.planche-section`: the other `.ca-action`s of the site keep their size. */
@media (max-width: 767.98px), (max-width: 1023.98px) and (pointer: coarse) {
  .planche-section .ca-action,
  .planche-section .fold-toggle {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
  }
}

/* The « suivantes » bar of an index (decision 11, Q5): the width of the list, 44 px tall,
   in the same outlined style as any action; it ends the list and is one large target on a
   phone (the chip it replaces was 193 x 25 px at the foot of a 7 000 px scroll). The
   template draws it only when more rows exist. */
.ca-action.ca-action--barre {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: 44px;
  margin-top: var(--sp-3);
}

/* Sur fond sombre le bouton s'inverse. `text-decoration: none` est nécessaire
   ici : `.hero a` (0,1,1) l'emporterait sinon sur `.ca-action` (0,1,0). */
.hero .ca-action,
.hero .cta-link,
.societe-identity .ca-action,
.societe-identity .cta-link {
  border-color: var(--ca-jaune);
  color: var(--ca-jaune);
  text-decoration: none;
}

/* .module-card est un conteneur flex-column : sans align-self, le bouton
   s'étirerait sur toute la largeur au lieu de rester à droite. */
.module-link {
  align-self: flex-end;
  margin-top: auto;
}

.section-link {
  margin-top: var(--sp-4);
}

/* ============================================================================
   FOCUS (spec §2.4)
   Avant : 1 règle :focus et 3 :focus-visible pour tout le site, face à
   1 800+ éléments focusables sur une seule page de recherche.
   ========================================================================== */

:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--ca-lien);
  outline-offset: 2px;
}

.hero :where(a, button, input, summary):focus-visible,
.societe-identity :where(a, button, input, summary):focus-visible {
  outline-color: var(--ca-jaune);
}

/* Quand un encadré signale déjà le focus par :focus-within, le champ qu'il
   contient ne doit PAS dessiner un second anneau : on obtenait sinon trois
   traits jaunes concentriques (bordure de l'encart + box-shadow + outline).
   C'est l'encadré qui porte l'état, sur toute la zone cliquable. */
.terminal-encart input:focus-visible,
.ca-header-search-field input:focus-visible {
  outline: none;
}

/* ============================================================================
   HEADER (spec §3.1)
   La recherche prend toute la largeur disponible. Avant, un
   `max-width: 18rem` combiné à `justify-content: space-between` faisait glisser
   la barre horizontalement d'une page à l'autre : sa position dépendait de la
   largeur de la nav, qui changeait à chaque page (il existait six variantes).
   ========================================================================== */

/* Le `flex-wrap: wrap` ne sert plus qu'à une chose : laisser la nav DÉPLIÉE
   descendre sur sa propre rangée sous 1024. Au-delà, il est explicitement
   annulé (`nowrap`, plus bas) — c'est lui qui, combiné au `flex-basis: 22rem`
   de la recherche, mettait la nav à la ligne sur TOUS les écrans de bureau. */
.ca-header-inner {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--sp-2) var(--sp-4);
}

.ca-logo {
  flex: 0 0 auto;
}

/* Le glyphe et le nom sont collés dans le HTML (pas d'espace entre les balises,
   sinon il resterait une chasse au téléphone où le nom est masqué). L'espace se
   pose donc ici, et disparaît de lui-même quand `.ca-logo-texte` est en
   `display: none`. */
.ca-logo-texte {
  margin-left: 0.35em;
}

.ca-header-search {
  flex: 1 1 22rem;
  min-width: 0;
  /* Conteneur de requête pour le préfixe ci-dessous (viewport.css §7). Le champ
     porte déjà `position: relative` pour son panneau de suggestions : il était
     donc déjà bloc contenant, `container-type` ne déplace rien. */
  container-type: inline-size;
}

/* À 1024 px la rangée unique ne laisse que ~150 px à la recherche, et le
   préfixe « rechercher › » en mange 85 — il ne resterait pas de quoi lire
   « nom ou SIREN ». Le préfixe s'efface donc quand le CHAMP est étroit.

   C'est une requête de CONTENEUR, pas un treizième palier : elle réagit à la
   largeur réellement obtenue par le champ, pas à celle de l'écran. Un palier de
   plus serait refusé par `web/checks/check_viewport_coherence.py`, et à juste titre —
   la question posée ici n'est pas « quel écran ? » mais « quelle place reste-t-il
   dans ce champ ? ». Le placeholder porte alors seul l'affordance. */
@container (max-width: 17rem) {
  .ca-header-search-prompt {
    display: none;
  }
}

.ca-header-search-field {
  height: 2.25rem;
  padding: 0 var(--sp-3);
}

.ca-header-search-prompt,
.ca-header-search-input {
  font-size: var(--fs-s);
}

.ca-nav {
  flex: 0 0 auto;
  margin-left: auto;
  font-size: var(--fs-s);
  column-gap: var(--sp-4);
  row-gap: var(--sp-2);
}

/* Bouton de menu — n'existe qu'au palier compact (cf. plus bas). */
.ca-nav-bascule {
  display: none;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  width: 44px;
  height: 44px;
  margin-left: var(--sp-2);
  border: 1px solid var(--ca-filet);
  background: transparent;
  color: var(--ca-charbon);
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
}

/* ── Palier `large` : marque + recherche + nav sur UNE rangée ───────────────
   La nav est ici toujours visible. `.ca-nav.hidden` (0,2,0) l'emporte sur le
   `.hidden` de Tailwind (0,1,0), donc la classe posée dans le gabarit devient
   inerte.

   LE BUDGET DE LARGEUR — c'est lui qui tient la rangée, pas une astuce CSS.
   Mesuré au navigateur, à 1024 px (le cas le plus serré : 984 px utiles une
   fois les 2 × 20 px de padding retirés) :

       marque 167 + nav 633 + 2 gouttières 32  →  152 px pour la recherche

   et à partir de 1152 px, où le conteneur plafonne à `--max-width`, 279 px.
   Toute entrée ajoutée à la nav, ou tout libellé rallongé, se paie sur ces
   152 px — c'est pour ça que le lien est libellé « Liquidations » et non
   « Liquidations judiciaires ». Si une septième entrée devient nécessaire, ce
   n'est pas le budget qu'il faut forcer : c'est le repli qu'il faut remonter
   au-dessus de 1024, ou une entrée qu'il faut sortir.

   `nowrap` sur la rangée + `flex-basis: 0` sur la recherche : la recherche
   absorbe toute la compression, donc rien ne peut plus passer à la ligne. Avec
   `flex-basis: 22rem` (352 px, l'ancienne valeur) c'est l'inverse qui se
   produisait — le navigateur renvoie à la ligne AVANT de rétrécir une base,
   donc la nav partait sur une deuxième rangée dès 1440 px. */
@media (min-width: 1024px) {
  .ca-header-inner {
    flex-wrap: nowrap;
  }

  .ca-header-search {
    flex: 1 1 0;
  }

  .ca-nav {
    flex-wrap: nowrap;
    white-space: nowrap;
  }

  .ca-nav.hidden {
    display: flex;
  }

  /* `:not(.ca-header--atlas)`: the atlas header folds up to 1280 px (« Header atlas » below). */
  .ca-header:not(.ca-header--atlas) .ca-nav-bascule {
    display: none !important;
  }
}

/* ── Paliers `compact` et `medium` : la nav est rangée derrière le bouton ───
   Elle mesure ~570 px à elle seule ; sous 1024 il ne reste pas de quoi la poser
   à côté d'une recherche utilisable. Plutôt que de la laisser passer à la ligne
   (la rangée en trop, qui rendait aussi la hauteur du header variable donc son
   `position: sticky` inopérant), elle se replie : `repli-large` dans le
   gabarit, viewport.css §8. Dépliée, elle s'ouvre en colonne SOUS la rangée,
   comme un menu — pas comme une deuxième barre. */
@media (max-width: 1023.98px) {
  .ca-nav-bascule {
    display: inline-flex;
  }

  .ca-nav {
    order: 4;
    width: 100%;
    margin-left: 0;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    padding-top: var(--sp-2);
    border-top: 1px solid var(--ca-filet);
  }

  /* Cible tactile (spec §2.4). La règle des 44 px existait depuis toujours ;
     rien ne l'appliquait, et l'audit du 2026-08-21 a relevé 20 px sur ces
     liens, 27 px sur le CTA, 34 px sur le champ de recherche.
     On agit sur la SURFACE (min-height + centrage), jamais sur la taille du
     texte : le cran typographique est déjà le bon. Vaut aussi sur tablette :
     `medium` est un palier tactile, pas un petit bureau. */
  .ca-nav a {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    width: 100%;
    justify-content: flex-start;
  }

  .ca-nav .cta-link {
    justify-content: center;
    margin-top: var(--sp-2);
  }
}

/* B17 Q49 : l'en-tête atlas sur une tablette au doigt (768–1023 px, `pointer: coarse`) — le
   logo mesurait 23 px et le champ de recherche 34 px sur les 40 pages mesurées. Le champ garde
   sa largeur ; seule la hauteur change, et la rangée (61 px) la contient. Limité à
   `.ca-header--atlas`. */
@media (min-width: 768px) and (max-width: 1023.98px) and (pointer: coarse) {
  .ca-header--atlas .ca-header-search-field,
  [data-recherche] .ca-header-search-field { height: 44px; }
  .ca-header--atlas .ca-logo { display: inline-flex; align-items: center; min-height: 44px; }
}

/* ── Palier `compact` : ce qui n'est vrai QUE sur téléphone ────────────────── */
@media (max-width: 767.98px) {
  .ca-header-search-field {
    height: 44px;
  }

  /* Le logo est aussi un lien de retour : même traitement. */
  .ca-logo {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    flex: 0 0 auto;
  }

  /* La marque seule au téléphone : « ◉ entreprise atlas » fait ~215 px (estimé au prorata des
     230 px mesurés pour l'ancienne marque « convergence atlas », un caractère de plus), il ne
     resterait pas de place pour la recherche sur la même rangée. Le nom complet
     revient dès 768 px. Le lien garde son aria-label, donc rien ne se perd pour
     un lecteur d'écran. */
  .ca-logo-texte {
    display: none;
  }

  /* Réduit au seul glyphe, le lien ne mesurait plus que 11 px de large : la
     hauteur de 44 px ne suffit pas, une cible tactile a DEUX dimensions. */
  .ca-logo-marque {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 44px;
    font-size: 1.15rem;
    line-height: 1;
  }

  /* La recherche partage la PREMIÈRE rangée avec la marque et le menu. Son
     `flex-basis: 22rem` (352 px, posé plus haut hors media query) forçait à lui
     seul le retour à la ligne sur un écran de 390 : marque + 352 + bouton = 405.
     `flex: 1 1 0` la laisse prendre exactement ce qui reste. */
  .ca-header-search {
    order: 0;
    flex: 1 1 0;
    min-width: 0;
  }

  /* La gouttière de 16 px du socle coûtait 32 px sur une rangée de 390. */
  .ca-header-inner {
    gap: 0 var(--sp-2);
    padding: var(--sp-2) var(--sp-3);
  }
}

/* ── Header atlas (B3, spec-design §8.1 decision 10, 2026-09-29) ──────────────────────────
   Everything the header changes from its base rules above, behind ONE hook,
   `.ca-header--atlas` (base.html). Measured before, on
   /entreprises/ (2026-09-29):
     · the search field was 34 px wide at 1024, 110 at 1100, 162 from 1200 to 1600 (the row was
       capped at 72 rem = 1152 px), its placeholder cut to « entreprise, SIREN »;
     · the header was 61 px, 69 px from 768 to 1023 (the ☰'s 44 px target in the roomy padding);
     · the open ☰ menu was 430 px on a 390 screen (eight 44 px rows in one column).
   Decisions: the row is 80 rem = 1280 px wide; the nav folds under ☰ below 1280 px (the only
   seuil beyond the three paliers, tailwind/viewport.json `seuils_atlas`); the folded band takes
   the compact padding so the height is 61 px at every width; the open menu is a grid, two
   columns on a phone (about 250 px for the header) and four from 768.
   E0 #3 (2026-09-30): the row is 86 rem = 1376 px. « Fonds » became « Fonds de commerce »
   (+96 px) and, at the 80 rem cap, the search paid for all of it: 239 → 143 px logged out
   (« Créer un compte » + « Se connecter »), its placeholder cut to « entreprise, SIREN ». The
   96 px go back to the row, not to a new seuil: from 1376 px up the field is 239 px again;
   between 1280 and 1376 the row is the screen and the field grows with it. */
.ca-header--atlas .ca-header-inner {
  max-width: 86rem;
}

/* The account action: the flat olive chip of `.ca-action` (tokens above), the header's one.
   `.ca-nav a` (0,1,1) would grey its text and underline its hover; this is the same pair
   redeclared one class higher, and the text size joins the nav's own (the chip's 11 px next to
   13 px links read as a footnote). */
.ca-header--atlas .ca-nav a.ca-action {
  color: var(--ca-charbon);
  font-size: var(--fs-s);
}

.ca-header--atlas .ca-nav a.ca-action:hover {
  color: var(--ca-noir);
  text-decoration: none;
}

/* « Ma veille » (logged in), framed as the Secteurs filter field (index.css `.arbre-filtre`,
   user 2026-10-14: « the same kind of look »): the bright yellow frame and the nav CTA's halo
   on hover and focus. 2 px, not the field's 3: the user found 3 px heavy on a button of this
   size (« slightly finer », same day); 1 px of `--ca-jaune` (1.1:1 on white) would vanish. The
   padding gives back the 1 px the frame adds, so the header row keeps its height.
   A rule, not a fill, at rest (§6.2, §6.3): the hover fill is the one of every `.ca-action`. */
.ca-header--atlas .ca-nav a.ca-action--veille {
  border: 2px solid var(--ca-jaune);
  padding: calc(var(--sp-1) - 1px) calc(var(--sp-2) - 1px);
}

.ca-header--atlas .ca-nav a.ca-action--veille:hover,
.ca-header--atlas .ca-nav a.ca-action--veille:focus-visible {
  box-shadow: 0 0 12px var(--ca-moutarde-glow);
}

/* The current index: the yellow rule of the rail's current entry (site.css .planche-rail
   a.est-courant, decision 9 (e)), `aria-current` being the hook a screen reader reads too. */
.ca-header--atlas .ca-nav a[aria-current="page"] {
  color: var(--ca-charbon);
  box-shadow: inset 0 -2px 0 var(--ca-jaune);
}

/* Folded, below 1280 px: what the base header does below 1024 (above), one seuil higher. */
@media (max-width: 1279.98px) {
  .ca-header--atlas .ca-header-inner {
    flex-wrap: wrap;
    gap: 0 var(--sp-2);
  }

  .ca-header--atlas .ca-nav-bascule {
    display: inline-flex;
  }

  .ca-header--atlas .ca-nav {
    order: 4;
    width: 100%;
    margin-left: 0;
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0 var(--sp-2);
    padding-top: var(--sp-2);
    border-top: 1px solid var(--ca-filet);
  }

  /* The 44 px target (spec-design §2.4) on the SURFACE, never the type. */
  .ca-header--atlas .ca-nav a {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
  }

  .ca-header--atlas .ca-nav a.ca-action {
    justify-content: center;
  }
}

/* From 768 the grid has room for four columns: the six entries and the two account links in
   two rows. The padding is the compact one (8 px above and below the 44 px ☰: 61 px in all),
   the sides keep the tablet's 20 px. */
@media (min-width: 768px) and (max-width: 1279.98px) {
  .ca-header--atlas .ca-header-inner {
    padding: var(--sp-2) 1.25rem;
  }

  .ca-header--atlas .ca-nav {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

/* E0 #4 (2026-09-30): the ☰ is the search field's height and speaks the site's one button
   dialect (spec-experience §6.1, the `.ca-action` pair above): olive rule and glyph at rest,
   yellow fill on hover and while the menu is open (§6.2's hover meaning; the open state is the
   hover held). Before, a grey rule and a black glyph at 44 px beside a 36 px field, 8 px taller
   than the field from 768 to 1279 on a mouse. The 44 px it keeps where a finger needs it
   (spec-design §2.4) are exactly where the field is 44 too: a phone, and a tablet under 1024
   in `pointer: coarse` (B17 Q49 above). */
.ca-header--atlas .ca-nav-bascule {
  width: 2.25rem;
  height: 2.25rem;
  border-color: var(--ca-lien);
  color: var(--ca-lien);
}

.ca-header--atlas .ca-nav-bascule:hover,
.ca-header--atlas .ca-nav-bascule[aria-expanded="true"] {
  background: var(--ca-jaune);
  border-color: var(--ca-jaune);
  color: var(--ca-noir);
}

/* With a 36 px ☰ the folded row takes the large tier's 12 px above and below, so the header
   stays 61 px (`--header-height`, which the sticky rails read): 12 + 36 + 12 + the 1 px rule. */
@media (min-width: 768px) and (max-width: 1279.98px) {
  .ca-header--atlas .ca-header-inner {
    padding-top: var(--sp-3);
    padding-bottom: var(--sp-3);
  }
}

@media (max-width: 767.98px) {
  .ca-header--atlas .ca-nav-bascule {
    width: 44px;
    height: 44px;
  }
}

@media (min-width: 768px) and (max-width: 1023.98px) and (pointer: coarse) {
  .ca-header--atlas .ca-nav-bascule {
    width: 44px;
    height: 44px;
  }

  .ca-header--atlas .ca-header-inner {
    padding-top: var(--sp-2);
    padding-bottom: var(--sp-2);
  }
}

/* ============================================================================
   SOUS-NAVIGATION D'ANCRES (spec §3.2)
   Avant : `overflow: visible` sans repli. Sur /secteur/, trois entrées
   débordaient à 1 395–1 540 px et étaient invisibles ET non cliquables sur un
   écran de 1 440.
   ========================================================================== */

/* Le défilement, l'accrochage et l'affordance viennent de `.rail`
   (viewport.css §2) : le gabarit écrit `class="societe-nav-inner rail mono"`.
   Il ne reste ici que ce qui est propre à la sous-navigation.

   Avant, cette barre portait sa propre mécanique : `overflow-x: auto` +
   `scrollbar-width: none` + un `::after` en dégradé FIXE. Le dégradé étant
   permanent et toujours à droite, il ne disait rien — ni « il reste du contenu
   à droite », ni « vous en avez dépassé à gauche ». Sur /secteur/, 1 026 px
   d'ancres (73 % du total) étaient hors champ sans le moindre signal exploitable
   (audit du 2026-08-21, constat 02). `.rail` pose `data-debord` selon la
   position réelle et masque du bon côté. */

.societe-nav-inner > a {
  flex: 0 0 auto;
  white-space: nowrap;
}

/* ============================================================================
   DÉBORDEMENT HORIZONTAL

   Cause mesurée sur /operations/ à 390 px : un blowout `min-width: auto`.
   Le libellé le plus long de l'arbre de facettes (« Commerce ; réparation
   d'automobiles et de motocycles », indenté de cinq niveaux) impose sa largeur
   de contenu minimale à toute la grille — la carte faisait 1 029 px dans un
   parent de 358.

   facets.css applique déjà min-width:0 sur .ds-tree et sa
   descendance, mais s'arrêtait un niveau trop bas : la carte qui les contient
   est un élément de grille resté en min-width:auto. C'est elle qui gonflait.
   ========================================================================== */

.ds-tree-facet,
.ds-tree-facet > *,
#ds-panel,
#ds-panel > *,
main > *,
main .grid > *,
main .flex > * {
  min-width: 0;
}

/* Filet de sécurité : aucune page ne défile latéralement. */
html,
body {
  overflow-x: clip;
}

/* Le corps est au cran --fs-m, pas aux 16 px du navigateur : il n'y a que cinq crans, et le
   texte qui hérite du corps sans taille propre en était un sixième silencieux (décision B1 du
   2026-09-23, spec-design §8.1). Les rem restent calés sur html, donc rien d'autre ne bouge. */
body {
  font-size: var(--fs-m);
}

/* Sous le palier compact, le h1 d'une planche descend au cran --fs-xl : à 40 px de mono sur
   390 px, « BOULANGERIE DUPONT ET FILS » tenait sur trois lignes de quatorze signes
   (mesuré sur /design/, décision B1 du 2026-09-23). Largeur : tailwind/viewport.json. */
@media (max-width: 767.98px) {
  :root {
    --fs-hero: var(--fs-xl);
  }
}

/* ============================================================================
   MOUVEMENT
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* ============================================================================
   COMPOSANTS

   Ces classes sont la bibliothèque partagée : Transactions, Actes, Commande
   publique, Comparables et les résultats de recherche s'en servent toutes.
   Un composant réutilisé est un composant, pas un copier-coller (spec §4.5).
   ========================================================================== */

/* ── Ligne de donnée (spec §3.4) ─────────────────────────────────────────────
   Remplace les « cartes » Tailwind. Une ligne, pas une boîte : filet vertical
   porteur du sens à gauche, fond transparent, séparation par un filet.

   Ce qu'on ne refait pas : les anciennes cartes étaient écrites
   `rounded-xl bg-white border-l-4 border-l-emerald-400` puis à moitié annulées
   par la couche .societe-embed. Rendu réel : coins droits, fond gris, filet
   gauche de 1px. La carte blanche à colonne vertébrale colorée n'existait
   qu'en intention.                                                          */

.ligne-donnee {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: var(--sp-1) var(--sp-4);
  padding: var(--densite-ligne) 0 var(--densite-ligne) var(--sp-3);
  /* 2 px : le seul trait gauche de l'atlas, le même que celui du repère et de
     l'avertissement (décision B2 du 2026-09-23, spec-design §8.1 ; la ligne avait 3 px et le
     repère 2 px pour le même sens). */
  border-left: 2px solid var(--ca-filet);
  border-bottom: 1px solid var(--ca-filet);
}

.ligne-donnee:last-child {
  border-bottom: none;
}

/* Le filet porte la direction de l'opération. C'est le seul endroit où la
   couleur code une valeur dans ce composant. */
.ligne-donnee--gain { border-left-color: var(--ca-vert); }
.ligne-donnee--perte { border-left-color: var(--ca-rouge); }

/* ── One line per fact (`.ligne-donnee--une`; spec-design §8.1 decision 18, 2026-10-02) ────
   The user, on the drawings of artifacts/densite-propositions.html: « yes » to one line per
   fact, the rest on demand, and of « Actes » as it stood: « still not dense enough ». An acte
   with two signals was 96 px, its type, its sentences and its date on three rows; it is 29 px.

     date │ what                 │ what else, cut with « … » ▸        │ amount or door
     mono │ `.ligne-une-titre`   │ `.ligne-suite` (a <details>)       │ `.ligne-cote`

   The columns are the same from row to row, so a list reads down as a table does, and the long
   text (the sentences read in an acte, the object of a marché) opens under its row, in the
   third column. A row with nothing more to say has no third cell.
   IN A NARROW LIST the third cell goes under the first two, on a line of its own: a list is its
   own container (`.liste-donnees--une`), so the rule follows the width the list really has (a
   cell of five columns of the grid, a phone) and not the screen's; under 36 rem, so that a
   cell of six columns (about 40 rem at 1440 px) keeps the one line. A row is then two lines at
   most, one when it has nothing more to say.
   The row's vertical padding is a table cell's (`--densite-cellule`): it is one. */
.liste-donnees--une { container-type: inline-size; }

.ligne-donnee--une {
  /* `--ligne-titre`: the width of the second column, which a list sets when its « what » is
     longer than a type of acte (a chronology's « CHANGEMENT DE CONTRÔLE · FUSION-ABSORPTION »). */
  grid-template-columns: 4.75rem minmax(0, var(--ligne-titre, 17rem)) minmax(0, 1fr) auto;
  align-items: baseline;
  gap: 0 var(--sp-4);
  padding-block: var(--densite-cellule);
  font-size: var(--fs-s);
}

.ligne-donnee--une > .date {
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  font-variant-numeric: tabular-nums;
  color: var(--ca-gris-fort);
  white-space: nowrap;
}

.ligne-une-titre {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.ligne-donnee--une > .ligne-cote {
  grid-column: 4;
  grid-row: 1;
  font-size: var(--fs-xs);
  color: var(--ca-gris-fort);
}

.ligne-donnee--une > .ligne-cote .montant { display: inline; }

.ligne-suite { grid-column: 3; grid-row: 1; min-width: 0; color: var(--ca-gris-fort); }

/* `--pleine`: the line that opens sits under the row it belongs to, across its whole width, and
   not in the third column of a `--une` row (the company plate's « Établissements »: the
   exploitants a lieu has had, graph/entreprise/exploitants.html). Its body is a list of lines
   of its own, under the summary. */
.ligne-suite--pleine { grid-column: 1 / -1; grid-row: auto; }
.ligne-suite--pleine > .liste-donnees { margin: var(--sp-1) 0 var(--sp-2); }

/* The third cell when it does not open (a journal line: the company, its address): the same
   place, cut the same way. In the two cells the words are grey when they qualify the row
   (Actes, Marchés publics) and ink when they ARE the row's subject (`--nom`: the company of a
   chronology line, whose second column is the kind of event). */
.ligne-une-reste {
  grid-column: 3;
  grid-row: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.ligne-suite-resume--nom { color: var(--ca-charbon); }

/* A row with no date (the cibles of an opération): the same line without its first column. */
.ligne-donnee--sans-date { grid-template-columns: minmax(0, var(--ligne-titre, 17rem)) minmax(0, 1fr) auto; }
.ligne-donnee--sans-date > :is(.ligne-suite, .ligne-une-reste) { grid-column: 2; }
.ligne-donnee--sans-date > .ligne-cote { grid-column: 3; }

/* A row whose second column is a kind of event in mono capitals (a chronology, a journal):
   « CHANGEMENT DE CONTRÔLE · FUSION-ABSORPTION » is 300 px, a type of acte 200. */
.ligne-donnee--une:has(> .ligne-une-titre.ligne-tete) { --ligne-titre: 21rem; }
/* And it wraps instead of being cut: the kind of an event is printed nowhere else on the row
   (an annonce's « AUTRE ACHAT, APPORT, ATTRIBUTION (IMMATRIC… » lost its end, walk of
   2026-10-02), where a cut type of acte is one click from its plate. */
.ligne-une-titre.ligne-tete { white-space: normal; overflow: visible; }

.ligne-suite > summary {
  display: flex;
  gap: var(--sp-1);
  cursor: pointer;
  list-style: none;
}

.ligne-suite > summary::-webkit-details-marker { display: none; }

/* The words are cut, the sign is not: it is what says the line opens (§6.4). */
.ligne-suite-resume { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ligne-suite > summary::after { content: "▸"; flex: 0 0 auto; color: var(--ca-lien); }
.ligne-suite[open] > summary::after { content: "▾"; }
.ligne-suite > summary:hover .ligne-suite-resume { color: var(--ca-charbon); }

.ligne-suite-corps { margin: var(--sp-1) 0 var(--sp-2); }
.ligne-suite-corps > p { margin: 0 0 var(--sp-1); }

/* `.ligne-donnee.ligne-donnee--une`, two classes: the compact rule of the plain line, further
   down (« la colonne de droite passe sous le corps »), would otherwise put this row in one
   column on a phone. */
@container (max-width: 36rem) {
  .ligne-donnee.ligne-donnee--une { grid-template-columns: 4.75rem minmax(0, 1fr) auto; }
  .ligne-donnee--une > .ligne-cote { grid-column: 3; grid-row: 1; text-align: right; }
  .ligne-suite, .ligne-une-reste { grid-column: 2 / -1; grid-row: 2; }
  .ligne-une-reste { white-space: normal; }
  .ligne-donnee.ligne-donnee--sans-date { grid-template-columns: minmax(0, 1fr) auto; }
  .ligne-donnee--sans-date > :is(.ligne-suite, .ligne-une-reste) { grid-column: 1 / -1; }
  .ligne-donnee--sans-date > .ligne-cote { grid-column: 2; }
}

/* The touch tier: a line that opens is a 44 px target, its row grows to hold it; the state
   word beside a door (« pièce lisible · ») goes, the door says it (« la pièce › » is a pièce
   one can read, « l'acte › » is not). */
@media (max-width: 767.98px), (max-width: 1023.98px) and (pointer: coarse) {
  .ligne-suite > summary { min-height: 44px; align-items: center; }
  /* A link that is the row's name (the acheteur of a marché): the floor comes from its own
     padding, which the row grows to hold. No negative margin as on the plain line: the name's
     box cuts what overflows it, and a hit area outside it would be cut too. */
  .ligne-une-titre > a,
  .ligne-une-reste > a { display: inline-block; padding: 13px 0; }
  .ligne-donnee--une > .ligne-cote .etat { display: none; }
}

/* Ligne d'en-tête : nature de l'opération puis qualificatifs, en mono. Les
   pastilles arrondies pastel ont disparu — quatre teintes (emerald, indigo,
   amber, violet) pour de l'information secondaire, c'était trois de trop. */
.ligne-tete {
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ca-gris-fort);
}

.ligne-tete .nature { font-weight: 500; }
.ligne-tete .nature--gain { color: var(--ca-vert); }
.ligne-tete .nature--perte { color: var(--ca-rouge); }

/* Séparateur « · » posé en CSS : le gabarit n'a pas à gérer forloop.last. */
.ligne-tete .qual::before {
  content: " · ";
  color: var(--ca-filet);
}

.ligne-corps {
  font-size: var(--fs-s);
  color: var(--ca-charbon);
  min-width: 0;
}

.ligne-corps .role {
  color: var(--ca-gris-fort);
}

/* Colonne de droite : date au-dessus, montant en dessous, chiffres alignés. */
.ligne-cote {
  grid-column: 2;
  grid-row: 1 / span 2;
  text-align: right;
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.ligne-cote .date {
  font-size: var(--fs-xs);
  color: var(--ca-gris-fort);
}

.ligne-cote .montant {
  display: block;
  font-size: var(--fs-s);
  font-weight: 500;
  color: var(--ca-charbon);
}

.ligne-cote .montant--absent {
  color: var(--ca-gris-fort);
  font-style: italic;
  font-weight: 400;
}

/* La précision sous le montant (unité, libellé de procédure…) peut être longue :
   elle s'enroule dans une largeur bornée au lieu d'étirer la colonne. Le reste
   de .ligne-cote garde `nowrap` pour que dates et montants ne se coupent pas. */
.ligne-cote .unite {
  display: block;
  max-width: 14rem;
  margin-left: auto;
  font-size: var(--fs-xs);
  color: var(--ca-gris-fort);
  white-space: normal;
}

/* Pied : « Détails » repliable à gauche, action à droite. */
.ligne-pied {
  grid-column: 1 / -1;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-2);
  margin-top: var(--sp-1);
}

.ligne-pied > details {
  min-width: 0;
  flex: 1 1 auto;
}

.ligne-pied summary {
  cursor: pointer;
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  color: var(--ca-gris-fort);
  list-style: none;
}

.ligne-pied summary::-webkit-details-marker { display: none; }

.ligne-pied summary::before {
  content: "› ";
  color: var(--ca-lien);
  display: inline-block;
  transition: transform 0.15s ease;
}

.ligne-pied details[open] > summary::before {
  transform: rotate(90deg);
}

.ligne-detail {
  margin-top: var(--sp-2);
  font-size: var(--fs-s);
  color: var(--ca-gris-fort);
}

/* Sous-liste d'une opération multi-cibles : chaque cible avec SA valeur. Les
   valeurs ne sont jamais additionnées (spec G0 / spec-ma-pipeline.md). */
.ligne-sous-liste {
  margin: var(--sp-2) 0 0;
  padding: 0;
  list-style: none;
  border-top: 1px solid var(--ca-filet);
}

.ligne-sous-liste li {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-2);
  padding: var(--sp-1) 0;
  border-bottom: 1px solid var(--ca-filet);
  font-size: var(--fs-s);
}

.ligne-sous-liste .valeur {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  color: var(--ca-charbon);
}

.ligne-sous-liste .valeur--absente {
  color: var(--ca-gris-fort);
  font-style: italic;
}

@media (max-width: 767.98px) {
  /* Sur mobile la colonne de droite passe sous le corps plutôt que de
     comprimer les noms d'entreprise. */
  .ligne-donnee { grid-template-columns: 1fr; }
  .ligne-cote { grid-column: 1; grid-row: auto; text-align: left; }
}

/* B17 (decision 13). On compact the right column sits under the body, but it kept `nowrap`:
   « Changements de contrôle » on Danone printed date + « BODACC, annonces de vente et de
   cession · INSEE, Sirene » on one 273 px line that ended 19 px past the screen at 390 and 49
   at 360, cut silently by the page's `overflow-x: clip` (the recette read scrollWidth, which
   that clip makes 0). Only the date and the amount must not break. Scoped to `.planche-section`. */
@media (max-width: 767.98px) {
  .planche .planche-section .ligne-cote { white-space: normal; }
  .planche .planche-section .ligne-cote .date,
  .planche .planche-section .ligne-cote .montant { white-space: nowrap; }
  /* The precision under the date keeps the left edge of the column it now sits in: its
     `margin-left: auto` (the right alignment of the wide tier) indented it 66 px from the date
     above it (« Actes », 2026-10-01). */
  .planche .planche-section .ligne-cote .unite { margin-left: 0; max-width: none; }
}

/* B17 Q41 / Q49: the link of a row (a name, « › ») reaches 44 px on the touch tier. Padding on
   the inline link and an equal negative margin: the hit area grows, the row does not (the same
   trick as the chronology's, site.css, decision 11; a row is already ~44 px between its rules).
   17 px measured, 81 links on 9 plates. Sentence links keep their size. */
@media (max-width: 767.98px), (max-width: 1023.98px) and (pointer: coarse) {
  .planche .planche-section .ligne-donnee .ligne-corps > a,
  .planche .planche-section .ligne-donnee .ligne-cote a {
    display: inline-block;
    padding: 13px 0;
    margin: -13px 0;
  }
  .planche .planche-section .ligne-donnee .ligne-texte > summary {
    padding: 14px 0;
    margin: -14px 0;
  }
}

/* ── Étiquette (spec §3.5, §6.12; decision 11 of 2026-09-29, B15) ───────────────────────
   For the few statuses worth isolating, the closed list of §6.12. Never a pastel fill, never
   a rounded corner. LOWERCASE (§6.6: « lowercase for statuses and units »): the code set
   `text-transform: uppercase` and a .06em tracking, so a « SIÈGE » in a row read like the
   column head beside it; capitals stay for titles, kickers and heads. One --sp-1 keeps it
   off the word it qualifies, on either side (the specimen printed them touching, « ACTIF établissement »).
   Never a link, never a tap target. A badge alone in its cell has no word beside it, so no
   offset. */

.etiquette {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  padding: 2px 6px;
  margin: 0 var(--sp-1);
  border: 1px solid var(--ca-filet);
  color: var(--ca-gris-fort);
  white-space: nowrap;
}

td > .etiquette:only-child { margin: 0; }

/* ── Marque du jour (decision 12 of 2026-09-29, B12 Q36) ────────────────────────────────────
   « aujourd'hui », written once for two components: the frise's rule and the chronology list's
   marker. A yellow FILL under charbon text, never yellow text (spec-design decision 3: #faff69
   is 1,07:1 on white, so the word is set in ink on the yellow, and the rule beside it keeps
   the yellow the reader is taught to look for). Never a link. */
.marque-aujourdhui {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  line-height: 1.4;
  padding: 1px var(--sp-2);
  background: var(--ca-jaune);
  color: var(--ca-charbon);
  white-space: nowrap;
}

.etiquette--gain { border-color: var(--ca-vert); color: var(--ca-vert); }
.etiquette--perte { border-color: var(--ca-rouge); color: var(--ca-rouge); }

/* ── Liste de lignes ─────────────────────────────────────────────────────── */

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

/* Note de bas de bloc : provenance de la donnée. */
.bloc-source {
  margin: var(--sp-3) 0 0;
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  color: var(--ca-gris-fort);
}

/* ── Tableau de données (spec §3.6) ──────────────────────────────────────────
   En-tête mono en capitales, chiffres tabulaires alignés à droite, filets
   plutôt que zébrage. Sur mobile le tableau défile DANS son conteneur : c'est
   la page qui ne doit jamais défiler latéralement.                          */

.table-donnees-conteneur {
  overflow-x: auto;
  min-width: 0;
}

.table-donnees {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--fs-s);
}

.table-donnees th {
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--ca-surface);
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ca-gris-fort);
  text-align: left;
  padding: var(--sp-2) var(--sp-3) var(--sp-2) 0;
  border-bottom: 1px solid var(--ca-charbon);
  white-space: nowrap;
}

.table-donnees td {
  padding: var(--densite-cellule) var(--sp-3) var(--densite-cellule) 0;
  border-bottom: 1px solid var(--ca-filet);
  vertical-align: baseline;
}

/* A paragraph in a cell (an établissement's « Succession », one <p> per link) is a line of the
   cell, not a paragraph of prose: the browser's 1em above and below made every row with a
   succession 26 px taller than its text (74 px for two lines, measured 2026-10-02 on the
   77 rows of 301984563). Scoped to the plate (`.planche`), like the rules around it. */
.planche .table-donnees td p { margin: 0; }

/* The year under an amount (« 816,1 M€ » over « 2025 ») follows it on its line where the row
   is a table row: it made every row of a cell's « La liste » two lines for one cell (walk of
   2026-10-02). On a phone the row is a card and has its own rule (viewport.css). */
@media (min-width: 768px) {
  .planche .table-donnees td.num > br { display: none; }
  .planche .table-donnees td.num > .discret { margin-left: var(--sp-1); font-size: var(--fs-xs); }
}

.table-donnees tbody tr:hover {
  background: var(--ca-surface-2);
}

/* Colonnes de chiffres : mono, tabulaire, alignées à droite. */
.table-donnees .num,
.table-donnees th.num {
  text-align: right;
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* ── Rôles de texte ──────────────────────────────────────────────────────────
   `.discret` est LE gris de métadonnée du site : compteur, unité, mention
   secondaire, « prix non divulgué ». Il remplace `text-slate-400`, qui n'est
   pas dans la palette (spec §2.1) et ne donne que 2,5:1 — sous le seuil AA.

   Il vaut `--ca-gris-fort` (#4a4a4a) et NON `--ca-gris` (#767676).
   Ce n'est pas un excès de prudence, c'est une mesure : #767676 tient 4,54:1
   sur BLANC PUR et sur rien d'autre. Posé sur les fonds à peine teintés que le
   site emploie partout (#fcfdfe d'une ligne alternée, #fafbfd d'un en-tête de
   colonne), il retombe à 4,39-4,46:1 — sous le seuil, de peu, donc invisible à
   l'œil et attrapé seulement par check_design.py. Première tentative de cette
   conversion : 258 échecs de ce type exactement.

   `--ca-gris` reste réservé aux aplats et aux fonds strictement blancs, où on
   sait ce qu'on fait.                                                        */

.discret {
  color: var(--ca-gris-fort);
}

/* ── Repères (la bande de chiffres clés) ─────────────────────────────────────
   Décision B7 du 2026-09-23 (spec-design §8.1) : la tuile n'est plus une boîte. La rangée
   pose sur une bande --ca-surface-2 (le seul sens de ce jeton : « une bande »), chaque
   repère porte le trait gauche de 2 px de .ligne-donnee — charbon, vert ou rouge quand la
   valeur a un sens (§6.7) — et rien ne l'entoure : ni bord, ni fond de cellule, ni grille
   de filets. L'ancienne grille à `gap: 1px` sur fond filet laissait un aplat gris derrière
   un repère orphelin (6 repères sur 5 colonnes) et se lisait comme un tableur collé sur la
   cartouche noire. La valeur garde le cran --fs-l (« they were large enough »).
   `auto-fill` + `minmax` : pas de nombre de colonnes fixe, donc pas de demi-ligne morte.
   Le balisage est <div> ou <ul>, d'où la remise à zéro de la liste.                     */

/* ── Section : une carte (décision du 2026-09-23, spec-design §8.1 décision 7) ─────────
   Chaque section d'une planche est une carte blanche sur le fond gris de la page : filet de
   1 px, l'ombre légère de la page entreprise (.societe-block), son retrait, rayon 0. Dessinée
   à côté de la version en filets (page blanche, filet du titre, ligne de source, --sp-12
   entre les sections) : « I like A boxes better ». C'est le renversement de la décision B2 (a)
   du même jour (la planche sur --ca-surface) et de « lines not boxes » : la page pose sur
   --ca-surface-2, la section sur --ca-surface, la bande des repères reste --ca-surface-2 dans
   la carte. L'ombre est la seule de l'atlas.                                             */
.planche-section {
  border: 1px solid var(--ca-filet);
  background: var(--ca-surface);
  box-shadow: 0 4px 16px rgb(var(--ca-noir-rgb) / 0.06);
  padding: var(--densite-carte) var(--densite-carte-cote);
  margin: 0 0 var(--densite-entre-cartes);
  /* L'ancre du rail atterrit SOUS la barre collante, sinon le titre visé passe dessous. */
  scroll-margin-top: 4rem;
}

/* Un seul filet entre deux éléments (B2) : un titre dont le filet tomberait directement sur
   une bande ou sur la tête d'un tableau perd le sien, le bord de la bande ou le filet de la
   tête fait office. `:has()` pour que le gabarit n'ait rien à savoir ; un navigateur sans
   :has() (Firefox < 121) montre deux filets, rien de cassé.                                */
:is(h2, h3, h4):has(+ .reperes, + .table-donnees-conteneur, + .table-donnees) {
  border-bottom: 0;
  padding-bottom: 0;
  margin-bottom: var(--sp-2);
}

.reperes {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(var(--densite-repere), 1fr));
  gap: var(--densite-bloc) var(--sp-6);
  margin: 0 0 var(--densite-bloc);
  padding: var(--densite-bloc) var(--sp-4) var(--densite-bloc) var(--sp-2);
  background: var(--ca-surface-2);
  list-style: none;
}

.repere {
  padding: var(--sp-1) 0 var(--sp-1) var(--sp-3);
  border-left: 2px solid var(--ca-charbon);
}

/* La paire profonde, la même que celle de .ligne-donnee et de la valeur elle-même (B2) ;
   la paire vive (3,37:1 sur blanc) ne sert plus que sur la surface sombre. */
.repere--gain { border-left-color: var(--ca-vert); }
.repere--perte { border-left-color: var(--ca-rouge); }

.repere .valeur {
  display: block;
  font-family: var(--font-mono);
  font-size: var(--fs-l);
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  color: var(--ca-charbon);
  line-height: 1.2;
}

.repere--gain .valeur { color: var(--ca-vert); }
.repere--perte .valeur { color: var(--ca-rouge); }

/* Une valeur absente (« non publié », « — », §7.4) ne crie pas : gris fort, graisse 400. */
.repere--absent .valeur {
  font-weight: 400;
  color: var(--ca-gris-fort);
}

.repere .libelle {
  display: block;
  margin-top: var(--sp-2);
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ca-charbon);
}

/* B17 Q48: a precision (« depuis 2008 », « 2024 · + 6 % sur un an ») is a number and its unit,
   so it takes the mono face its 11 px belongs to (spec-design §2.2: 11 px is mono only, the
   sans floor is 13). It was sans 11 px on every plate with repères. */
.repere .precision {
  display: block;
  margin-top: 2px;
  font-size: var(--fs-xs);
  color: var(--ca-gris-fort);
}

/* The mono face is scoped to the plates (`main.planche`). */
.planche .repere .precision { font-family: var(--font-mono); }

/* Sur la surface sombre (la cartouche est un .hero) : la bande est un blanc à 6 %, le trait
   et la valeur sont la surface, le libellé aussi ; la précision et la valeur absente en gris
   sombre. Le trait de sens garde ses couleurs vives (aplats, ≥ 3:1 sur noir). */
.hero .reperes { background: rgba(255, 255, 255, 0.06); }
/* Sur le noir, la paire vive : la nuance du trait sur sombre, comme le texte y prend la
   surface (B1) ; #087f3f à 2 px sur noir ne se lit pas. */
.hero .repere { border-left-color: var(--ca-surface); }
.hero .repere--gain { border-left-color: var(--ca-vert-vif); }
.hero .repere--perte { border-left-color: var(--ca-rouge-vif); }
.hero .repere .valeur,
.hero .repere .libelle { color: var(--ca-text-on-dark); }
.hero .repere .precision,
.hero .repere--absent .valeur { color: var(--ca-text-muted-dark); }

/* Palier compact : deux colonnes, cinq repères tiennent sur trois rangs (largeur :
   tailwind/viewport.json). */
@media (max-width: 767.98px) {
  .reperes {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--densite-bloc) var(--sp-4);
  }
}

/* ── « La preuve » (spec-experience §5.4) ──────────────────────────────────────────────
   Le nombre surligné d'une phrase : le surlignage jaune, le seul sens de ce jeton avec le
   survol d'un lien (§6.2). */

.preuve {
  display: inline-block;
  margin: var(--sp-4) 0 0;
  font-family: var(--font-mono);
  font-size: var(--fs-m);
}

.preuve .valeur {
  background: var(--ca-jaune-surlignage);
  padding: 0 var(--sp-1);
  font-weight: 500;
}

/* ── Avertissement ───────────────────────────────────────────────────────────
   Pour les mises en garde de lecture (un total partiel, une source
   incomplète). Un filet jaune à gauche et rien d'autre : ni fond ambre, ni
   fond gris — le fond --ca-surface-2 que la règle posait disparaissait sur la
   page .mode-lecture (même gris) et faisait une boîte sur la page blanche.
   Le jaune peut être un filet sur toute surface (B1) ; c'est, avec la ligne
   de source, l'un des deux usages nommés d'un filet à côté de la ligne de
   donnée (décision B2 du 2026-09-23, spec-design §8.1).                    */

.avertissement {
  margin: var(--sp-3) 0;
  padding: var(--sp-2) var(--sp-3);
  border-left: 2px solid var(--ca-jaune);
  font-size: var(--fs-s);
  color: var(--ca-charbon);
}

/* Django's `messages` framework carries a `success`/`error` tag on top of the plain
   avertissement (D9b, the account's own first real caller: a saved profile, a deleted list).
   Same shape, the rule recoloured to the site's one green/red pair (§6.7) — never a new hue,
   never a filled background. */
.avertissement--succes { border-left-color: var(--ca-vert); }
.avertissement--erreur { border-left-color: var(--ca-rouge); }

/* ── Sous-titre de groupe dans un bloc ───────────────────────────────────── */

.groupe-titre {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-2);
  margin: var(--densite-groupe) 0 var(--sp-2);
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ca-gris-fort);
  border-bottom: 1px solid var(--ca-filet);
  padding-bottom: var(--sp-1);
}

.groupe-titre:first-child { margin-top: 0; }
