/* Tokens : voir tokens.css — source unique. Ce fichier n'en définit aucun.
   (Il en portait 46, dont onze redéfinis à l'identique dans tokens.css et
   trois noms différents pour le même #ffffff.) */

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  scroll-behavior: smooth;
}

body {
  margin: 0;
  font-family: var(--font-sans);
  color: var(--ca-charbon);
  background: var(--ca-creme);
  line-height: 1.5;
}

/* Les liens sont définis une seule fois, dans tokens.css (spec §2.3).
   `a { color: inherit; text-decoration: none }` vivait ici : c'est la règle qui
   rendait un lien au repos typographiquement identique au texte courant. */

.mode-lecture .section-title::before,
.mode-terminal .section-title::before {
  color: var(--ca-moutarde);
}

.mono,
.stat,
.terminal-input,
.chip,
.logo,
h1,
.module-title {
  font-family: var(--font-mono);
}

/* ── Header ─────────────────────────────────────────────────────────────────
   Ici : l'habillage (fond, flou, filet, curseur clignotant).
   La mise en page (flex, largeurs, tailles) et le style des liens vivent dans
   tokens.css — ne pas les redéclarer ici.

   Ce bloc portait avant quatre définitions de .cta-link, trois de .ca-nav et
   trois règles `.ca-header.mode-lecture` que rien ne déclenchait : le header
   est toujours rendu en mode-terminal (base.html).                          */

.ca-header {
  position: sticky;
  top: 0;
  z-index: 100;
}

.ca-header.mode-terminal {
  background: rgba(255, 255, 255, 0.92);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--ca-hairline);
}

.ca-header-inner {
  max-width: var(--max-width);
  margin: 0 auto;
  padding: 0.75rem 1.25rem;
}

.ca-logo {
  font-size: 0.95rem;
  letter-spacing: -0.02em;
  line-height: 1.5;
}

/* Le carré jaune qui suit le nom : curseur de terminal. */
.ca-logo .cursor {
  display: inline-block;
  width: 0.55em;
  height: 0.85em;
  background: var(--ca-moutarde);
  margin-left: 0.15em;
  vertical-align: -0.1em;
  box-shadow: 0 0 8px var(--ca-moutarde-glow);
}

.ca-nav {
  display: flex;
  align-items: center;
  gap: 1.25rem;
  font-family: var(--font-mono);
  line-height: 1.5;
}

/* Le CTA est le seul bouton jaune plein du site : il l'est au repos, pas
   seulement au survol. Le halo au survol est le rappel de marque. */
.ca-nav .cta-link {
  padding: 0.3rem 0.7rem;
  border-color: var(--ca-moutarde);
  background: var(--ca-moutarde);
  color: #000;
}

.ca-nav .cta-link:hover {
  box-shadow: 0 0 16px var(--ca-moutarde-glow);
}

/* ── Champ de recherche du header ── */
.ca-header-search {
  position: relative;
  margin: 0;
}

.ca-header-search-field {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  border: 1px solid var(--ca-hairline);
  background: var(--ca-blanc);
  cursor: text;
  margin: 0;
}

/* Le champ n'a pas d'outline propre (voir .ca-header-search-input) : c'est
   l'encadré qui porte l'état de focus, pour toute la zone cliquable. */
.ca-header-search-field:focus-within {
  border-color: var(--ca-moutarde);
  box-shadow: 0 0 0 1px var(--ca-moutarde);
}

.ca-header-search-prompt {
  color: var(--ca-text-muted);
  line-height: 1;
  white-space: nowrap;
}

.ca-header-search-input {
  flex: 1;
  min-width: 0;
  height: 100%;
  border: none;
  background: transparent;
  color: var(--ca-charbon);
  font-family: inherit;
  line-height: 1;
  padding: 0;
  margin: 0;
  outline: none;
  -webkit-appearance: none;
  appearance: none;
}

.ca-header-search-input::placeholder {
  color: var(--ca-text-muted-light);
}

.ca-header-search-input::-webkit-search-decoration,
.ca-header-search-input::-webkit-search-cancel-button {
  -webkit-appearance: none;
  appearance: none;
}

.ca-header-search .search-suggestions {
  min-width: 16rem;
}

@media (max-width: 767.98px) {
  /* Le header tient désormais sur UNE rangée (marque + recherche + menu), donc
     sa hauteur est de nouveau fixe, donc il peut rester collant.
     Avant : la recherche prenait toute une rangée (`flex: 1 1 100%`) et la nav
     une troisième — 154 px au total, et `position: static` faute de hauteur
     stable. Voir base.html et spec §10. */
  .ca-header {
    position: sticky;
    top: 0;
  }

  /* La règle de largeur de `.ca-header-search` au palier compact vit dans
     tokens.css, PAS ici. tokens.css est chargé en dernier (spec §5.1) et y
     redéclare `.ca-header-search { flex: 1 1 22rem }` hors media query : à
     spécificité égale (0,1,0), c'est lui qui gagne, et une surcharge écrite ici
     serait silencieusement morte. Elle l'a été — le header mesurait 173 px au
     lieu de 56 parce que la recherche gardait sa base de 352 px et forçait le
     retour à la ligne. */

  /* iOS zoome la page au focus de tout champ < 16px : plancher à 16px. */
  input[type="text"],
  input[type="search"],
  input[type="number"],
  input[type="email"],
  select,
  textarea {
    font-size: max(16px, 1em);
  }
}

/* ── Data sections (fond clair, texture grille) ── */
.mode-terminal {
  background: var(--ca-creme);
  color: var(--ca-charbon);
}

section.mode-terminal,
.ca-footer {
  position: relative;
  background-color: var(--ca-creme);
  background-image:
    linear-gradient(var(--ca-grid-line) 1px, transparent 1px),
    linear-gradient(90deg, var(--ca-grid-line) 1px, transparent 1px);
  background-size: 2.25rem 2.25rem;
}

section.mode-terminal::after,
.ca-footer::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    radial-gradient(ellipse 120% 90% at 50% 40%, transparent 60%, rgba(250, 255, 105, 0.04) 100%),
    repeating-linear-gradient(
      to bottom,
      var(--ca-scanline) 0,
      var(--ca-scanline) 1px,
      transparent 2px,
      transparent 4px
    );
  pointer-events: none;
  z-index: 0;
}

/* Hero ClickHouse — bandeau noir vibrant */
section.mode-terminal.hero {
  background-color: var(--ca-noir);
  background-image:
    linear-gradient(rgba(250, 255, 105, 0.06) 1px, transparent 1px),
    linear-gradient(90deg, rgba(250, 255, 105, 0.06) 1px, transparent 1px);
  color: var(--ca-text-on-dark);
}

.mode-terminal.hero {
  color: var(--ca-text-on-dark);
}

.mode-terminal.hero::after {
  background:
    radial-gradient(ellipse 80% 60% at 70% 30%, rgba(250, 255, 105, 0.12) 0%, transparent 55%),
    repeating-linear-gradient(
      to bottom,
      rgba(255, 255, 255, 0.015) 0,
      rgba(255, 255, 255, 0.015) 1px,
      transparent 2px,
      transparent 4px
    );
}

.mode-terminal.hero .hero-status {
  color: var(--ca-text-muted-dark);
}

.mode-terminal.hero h1 {
  color: var(--ca-text-on-dark);
}

.mode-terminal.hero .signature {
  color: var(--ca-text-muted-dark);
}

.mode-terminal.hero .terminal-encart {
  border-color: rgba(250, 255, 105, 0.35);
  background: rgba(12, 12, 12, 0.95);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.04),
    0 8px 32px rgba(0, 0, 0, 0.4);
}

.mode-terminal.hero .terminal-encart:focus-within {
  border-color: var(--ca-moutarde);
  box-shadow: 0 0 16px rgba(250, 255, 105, 0.3);
}

.mode-terminal.hero .terminal-input-wrap,
.mode-terminal.hero .terminal-input-wrap .prompt {
  color: var(--ca-moutarde);
}

.mode-terminal.hero .terminal-input {
  color: var(--ca-text-on-dark);
}

.mode-terminal.hero .terminal-input::placeholder {
  color: var(--ca-text-muted-dark);
}

.mode-terminal.hero .terminal-cursor {
  background: var(--ca-moutarde);
}

/* Sur le hero noir, le gris des sections claires (--ca-text-muted, #4a4a4a) tombe à 2,37:1.
   C'est --ca-text-muted-dark qui tient le contraste sur fond noir (cf. .hero-status). */
.mode-terminal.hero .chip,
.mode-terminal.hero .chips-label {
  border-color: rgba(250, 255, 105, 0.25);
  color: var(--ca-text-muted-dark);
}

.mode-terminal.hero .chip:hover {
  border-color: var(--ca-moutarde);
  color: var(--ca-moutarde);
}

/* The cover's two searches (accueil/page.html, 2026-10-16). Each opens on a title line: what it
   finds in the reader's colour, then what the page it opens holds, muted. The secteur box sits
   under the company box (the proof band closes the cover), set off by a rule of its own so it reads as a second, separate search
   rather than a continuation of the first; its button is outlined (`--secondaire` below). */
.page-home .hero-recherche-titre {
  margin: 0 0 0.6rem;
  font-size: var(--fs-s);
  color: var(--ca-text-on-dark);
  letter-spacing: 0.02em;
}

.page-home .hero-recherche-aide {
  color: var(--ca-text-muted-dark);
}

.page-home .hero-recherche-aide::before {
  content: "— ";
}

.page-home .hero-recherche--secteur {
  margin-top: 2.25rem;
  padding-top: 1.75rem;
  border-top: 1px dashed rgba(250, 255, 105, 0.25);
  max-width: 38rem;
}

/* Below the cover's company examples, which carry the `.chips` 2 rem bottom margin. */
/* The secteur examples are links (components/recherche.html `exemples`): no underline, so they
   read as the same chips as the company examples above. */
.page-home a.chip {
  text-decoration: none;
}

.page-home .hero-recherche--secteur .search-block,
.page-home .hero-recherche--secteur .chips {
  margin-bottom: 0;
}

@media (max-width: 767.98px) {
  .page-home .hero-recherche-aide {
    display: block;
    margin-top: 0.2rem;
  }

  .page-home .hero-recherche-aide::before {
    content: none;
  }
}

.mode-terminal.hero .proof-band {
  border-left-color: var(--ca-moutarde);
  background: rgba(250, 255, 105, 0.08);
  color: var(--ca-text-muted-dark);
}

/* Deux sections claires qui se suivent n'avaient aucune frontière : « Par où commencer ? » et
   « Créez votre veille. » flottaient sur le même fond, et rien ne disait où l'une finissait.
   Un filet, pas une alternance de fond — la spec §2.4 pose le filet comme séparation. */
/* Scopé à `.page-home` : `.mode-terminal` habille aussi les sections de /entreprise/,
   /personne/, /secteur/ et /liquidations/, qui ont déjà leurs propres séparations. */
.page-home section.mode-terminal + section.mode-terminal {
  border-top: 1px solid var(--ca-hairline);
}

.mode-terminal .section-inner {
  max-width: var(--max-width);
  margin: 0 auto;
  padding: 3rem 1.25rem;
  position: relative;
  z-index: 1;
}

/* ── Lecture section ── */
.mode-lecture {
  background: var(--ca-bg-alt);
  color: var(--ca-charbon);
}

.mode-lecture .section-inner {
  max-width: var(--max-width);
  margin: 0 auto;
  /* The frame's two numbers are density tokens (tokens.css « Densité »): 3rem / 1.25rem as the
     base, tighter under `body:has(.ca-header--atlas)`. */
  padding: var(--densite-page) var(--densite-gouttiere);
}

.section-title {
  font-family: var(--font-mono);
  font-size: clamp(1.35rem, 2.4vw, 1.75rem);
  font-weight: 500;
  line-height: 1.25;
  margin: 0 0 1rem;
}

.section-title::before {
  content: "› ";
  color: var(--ca-moutarde);
}

/* ── Hero ── */
.hero {
  padding-top: 4rem;
  padding-bottom: 3.5rem;
  position: relative;
  overflow: hidden;
}

/* The suggestions panel is a child of the hero, so the clip above cuts it off mid-list. Lift
   it only while the panel is open (class toggled by the autocomplete JS) so the decorative
   ::after overlay stays contained the rest of the time.
   The z-index is the second half of the fix: every `.mode-terminal .section-inner` sits at
   z-index 1, so the hero's panel and the following section tie and later DOM order wins --
   the sections below would paint straight through the open list. */
.hero.suggestions-open {
  /* Vertical only. A plain `overflow: visible` also unclips the horizontal axis, which exposes
     a pre-existing ~14px overflow of the h1 on narrow viewports and gives the page a sideways
     scrollbar. `overflow-x: clip` is what makes the one-axis pair legal -- with `hidden` the
     browser would compute the `visible` back to `auto`. */
  overflow-x: clip;
  overflow-y: visible;
  z-index: 60;
}

.hero-inner {
  display: grid;
  /* minmax(0, 1fr), not 1fr: the search input carries a 20-char intrinsic width that a plain
     `1fr` (= minmax(auto, 1fr)) refuses to shrink below, which pushed the whole hero ~14px past
     narrow viewports. */
  grid-template-columns: minmax(0, 1fr);
  gap: 1.5rem;
  align-items: center;
}

@media (min-width: 1024px) {
  .hero-inner {
    grid-template-columns: minmax(0, 1fr) auto;
    gap: 3rem;
  }
}

.hero-status {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.72rem;
  letter-spacing: 0.03em;
  color: var(--ca-text-muted);
  margin: 0 0 1.5rem;
  text-transform: lowercase;
}

.live-dot {
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 50%;
  background: var(--ca-moutarde);
  box-shadow: 0 0 0 0 var(--ca-moutarde-glow);
  animation: pulse 2s ease-out infinite;
}

@keyframes pulse {
  0% {
    box-shadow: 0 0 0 0 rgba(250, 255, 105, 0.55);
  }
  70% {
    box-shadow: 0 0 0 0.5rem rgba(250, 255, 105, 0);
  }
  100% {
    box-shadow: 0 0 0 0 rgba(250, 255, 105, 0);
  }
}

/* Le titre est borné en `ch`, pas en px : la mesure suit la chasse du mono, donc le nombre de
   lignes est stable d'un palier à l'autre. À 3.5rem il en faisait quatre sur bureau et poussait
   la barre de recherche sous la ligne de flottaison ; 2.4rem × 32ch en fait deux, sans retour
   codé en dur dans le gabarit. */
.hero h1 {
  font-size: clamp(1.5rem, 3.6vw, 2.4rem);
  font-weight: 500;
  line-height: 1.15;
  letter-spacing: -0.02em;
  max-width: 32ch;
  margin: 0 0 1rem;
  position: relative;
  color: var(--ca-charbon);
}

.hero .signature {
  font-family: var(--font-sans);
  font-size: clamp(1rem, 2.2vw, 1.2rem);
  margin: 0 0 2.25rem;
  position: relative;
  color: var(--ca-text-muted);
}

/* Boussole SVG — la « version extravagante » du logo (cf. charte). */
.hero-compass {
  display: none;
  width: clamp(180px, 20vw, 260px);
  height: auto;
  /* currentColor pilote les traits/remplissages moutarde de la boussole. */
  color: var(--ca-moutarde);
}

.ca-ring-rot {
  transform-origin: 120px 120px;
  animation: ring-rotate 40s linear infinite;
}

@keyframes ring-rotate {
  to {
    transform: rotate(360deg);
  }
}

@media (min-width: 1024px) {
  .hero-compass {
    display: block;
  }
}

.search-block {
  position: relative;
  margin-bottom: 1.25rem;
  max-width: 38rem;
}

.terminal-input-wrap {
  display: flex;
  align-items: center;
  padding: 1.05rem 1.15rem;
  font-family: var(--font-mono);
  font-size: 1rem;
  color: var(--ca-moutarde);
}

.terminal-encart {
  border: 1px solid rgba(250, 255, 105, 0.35);
  background: var(--ca-blanc);
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.06);
  transition: border-color 0.15s, box-shadow 0.15s;
}

/* Un seul signal de focus : la bordure passe au jaune, un halo discret la
   pose. Pas d'anneau `0 0 0 1px` en plus — il doublait la bordure au pixel
   près et donnait un trait épais et sale. */
.terminal-encart:focus-within {
  border-color: var(--ca-moutarde);
  box-shadow: 0 0 12px rgba(250, 255, 105, 0.25);
}

.terminal-input-wrap .prompt {
  color: var(--ca-charbon);
  margin-right: 0.5rem;
  white-space: nowrap;
}

.terminal-input {
  flex: 1;
  border: none;
  background: transparent;
  color: var(--ca-charbon);
  font: inherit;
  outline: none;
  /* Both are needed: min-width kills the flex floor, width kills the 20-char intrinsic basis
     the input would otherwise contribute to its container's min-content. */
  min-width: 0;
  width: 0;
}

/* Phones: give the typed text the row back -- the prompt drops to a bare "›" and the
   generous desktop padding halves. */
@media (max-width: 767.98px) {
  .page-home .terminal-input-wrap {
    padding: 0.4rem 0.75rem;
  }

  .terminal-input-wrap {
    padding: 0.85rem 0.75rem;
  }

  .prompt-label {
    display: none;
  }

  .terminal-input-wrap .prompt {
    margin-right: 0.4rem;
  }

  /* Le champ lui-même faisait 26 px de haut : la zone où poser le doigt sur le contrôle
     principal de la page était plus petite que le plancher de la spec §2.4. On le porte à
     44 px et on rend au bloc les marges internes qu'on lui prend. */
  .page-home .terminal-input {
    min-height: 2.75rem;
  }
}

.terminal-input::placeholder {
  color: var(--ca-text-muted-light);
}

/* `type="search"` affiche une croix d'effacement native — bleue sous Chromium,
   hors palette. Le champ du header la neutralisait déjà, pas celui du hero. */
.terminal-input::-webkit-search-decoration,
.terminal-input::-webkit-search-cancel-button {
  -webkit-appearance: none;
  appearance: none;
}

.search-suggestions {
  position: absolute;
  left: 0;
  right: 0;
  top: calc(100% + 0.35rem);
  z-index: 50;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  max-height: 18rem;
  overflow-y: auto;
  border: 1px solid var(--ca-hairline);
  background: var(--ca-blanc);
  box-shadow: 0 10px 28px rgba(43, 40, 38, 0.12);
  text-align: left;
}

.search-suggestions.hidden {
  display: none;
}

/* ── Hero dual-column suggestions (entreprises | personnes) ── */
/* Le bloc devient une rangée [champ | bouton]. Le panneau de suggestions reste en
   `position: absolute` — il sort donc du flux flex et continue de se caler sur toute la
   largeur du bloc, sous la rangée entière. */
.search-block--dual {
  display: flex;
  flex-wrap: wrap;
  align-items: stretch;
  gap: 0.5rem;
  max-width: 52rem;
}

.search-block--dual .terminal-encart {
  flex: 1 1 18rem;
  min-width: 0;
}

/* CTA primaire sur fond sombre : jaune plein, texte noir (charte §5, règle de proportion). */
.search-submit {
  flex: 0 0 auto;
  min-height: 3.25rem;
  padding: 0 1.5rem;
  border: 1px solid var(--ca-jaune);
  background: var(--ca-jaune);
  color: var(--ca-noir);
  font-family: var(--font-mono);
  font-size: var(--fs-m);
  line-height: 1.2;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s;
}

/* The second search of a page (the cover's secteur box): outlined, yellow on dark, so only one
   button of the page is the full yellow primary (spec-experience §6.3). */
.search-submit.search-submit--secondaire {
  background: transparent;
  color: var(--ca-jaune);
}

.search-submit.search-submit--secondaire:hover {
  background: rgba(250, 255, 105, 0.12);
  border-color: var(--ca-jaune);
}

.search-submit:hover {
  background: var(--ca-jaune-clair, #ffffb0);
  border-color: var(--ca-jaune-clair, #ffffb0);
}

/* Sur téléphone le bouton passe sous le champ et prend toute la largeur : côte à côte, il
   ne laissait au champ que ~11 caractères visibles. */
@media (max-width: 767.98px) {
  .search-submit {
    flex: 1 0 100%;
    min-height: 2.75rem;
  }
}

.search-suggestions--dual {
  flex-direction: row;
  align-items: stretch;
  max-height: none;
  overflow: visible;
}

.suggestion-column {
  display: flex;
  flex-direction: column;
  flex: 1 1 0;
  min-width: 0;
  border-right: 1px solid var(--ca-hairline);
}

.suggestion-column:last-child {
  border-right: none;
}

.suggestion-column-head {
  position: sticky;
  top: 0;
  z-index: 1;
  margin: 0;
  padding: 0.5rem 0.85rem;
  border-bottom: 1px solid var(--ca-hairline);
  background: var(--ca-moutarde-dim);
  color: var(--ca-charbon);
  font-family: var(--font-mono);
  font-size: 0.66rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

/* 40 rows per side will not fit on screen, so each column scrolls independently under its
   own sticky header rather than the panel scrolling as one block. */
.suggestion-column-list {
  max-height: 22rem;
  overflow-y: auto;
}

.suggestion-empty {
  margin: 0;
  padding: 0.65rem 0.85rem;
  color: var(--ca-text-muted-light);
  font-family: var(--font-mono);
  font-size: 0.72rem;
}

@media (max-width: 767.98px) {
  .search-suggestions--dual {
    flex-direction: column;
  }

  .suggestion-column {
    border-right: none;
    border-bottom: 1px solid var(--ca-hairline);
  }

  .suggestion-column:last-child {
    border-bottom: none;
  }

  .suggestion-column-list {
    max-height: 13rem;
  }
}

/* Composant recherche (D7a, plan-web-structure-d7-accueil-recherche.md). The ONE suggestions
   box of the atlas (components/recherche.html): the header, the home's cover and the error
   pages all render it, reusing the hero dual box's OWN classes (.search-suggestions,
   .suggestion-column…) in their STACKED (non `--dual`) shape rather than a second, narrower
   component kept in sync by hand (Q2 of the D7 note: one visual shape at every width). The
   dual box's own border-right between columns (built for its ROW layout) is a stray vertical
   line once the columns stack; this swaps it for the SAME rule the dual box already uses on
   its own mobile breakpoint above, applied here at every width instead of only under it. */
/* E0 #5 (2026-09-30): the terminal variant stacks field, button and chips in a plain block
   (the hero dual box's `--dual` flex row, with its 0.5 rem gap, is not used here), so the three
   touched: 0 px between them at 390 and 1440 on the home's cover, and between field and button
   on the error pages. The spacing is that row's own 8 px, and 12 px before the chips, which
   are a different thing (examples, not the search). The suggestions panel is absolute, so
   these margins never move it. */
.search-block[data-recherche] > .search-submit {
  margin-top: var(--sp-2);
}

.search-block[data-recherche] > .chips {
  margin-top: var(--sp-3);
}

/* E0 #5 (a): the panel's anchor (components/recherche.html): the field's own box, so the
   panel's `top: calc(100% + 0.35rem)` reads the field's height, not the whole form's. */
.recherche-champ {
  position: relative;
}

/* E0 #5 (b): the atlas cover's hero clipped the open panel at its bottom (the fourth row cut
   in half at 1440). The hero dual box lifts the clip with `.suggestions-open`, toggled by its own
   inline script; `js/recherche.js` toggles only the panel's `.hidden`, so the same lift is
   written on that state instead: the same declarations as `.hero.suggestions-open` above. */
.hero:has([data-recherche] .search-suggestions:not(.hidden)) {
  overflow-x: clip;
  overflow-y: visible;
  z-index: 60;
}

.search-suggestions:not(.search-suggestions--dual) .suggestion-column {
  border-right: none;
  border-bottom: 1px solid var(--ca-hairline);
}

.search-suggestions:not(.search-suggestions--dual) .suggestion-column:last-child {
  border-bottom: none;
}

.search-suggestion {
  display: block;
  width: 100%;
  padding: 0.65rem 0.85rem;
  border: none;
  border-bottom: 1px solid rgba(43, 40, 38, 0.08);
  background: transparent;
  color: var(--ca-charbon);
  font-family: var(--font-mono);
  font-size: 0.76rem;
  line-height: 1.45;
  text-align: left;
  cursor: pointer;
  margin: 0;
}

.search-suggestion:last-child {
  border-bottom: none;
}

/* B17 Q41 / Q49: a suggestion row is one target of the touch tier, 44 px (38 px measured, 22
   rows on /recherche/), in the header's dropdown and in the search block alike. Scoped
   to the component's own form (`data-recherche`) and to the results page's static rows (in the
   reading column).
   The row is a flex column so its label stays centred in the taller box. */
@media (max-width: 767.98px), (max-width: 1023.98px) and (pointer: coarse) {
  [data-recherche] .search-suggestion,
  .colonne-lecture .suggestion-column-list .search-suggestion {
    display: flex;
    flex-direction: column;
    justify-content: center;
    min-height: 44px;
  }

  /* The field is the wrapper's frame, but the finger lands on the INPUT, which measured 26 px
     inside a 53 px frame. The frame's vertical padding moves into the input so the whole
     frame answers the touch (3rem = 48 px: the frame stays about as tall as before). */
  [data-recherche] .terminal-input-wrap { padding-block: 0; }
  [data-recherche] .terminal-input { min-height: 3rem; }
}

.search-suggestion:hover,
.search-suggestion.is-active {
  background: var(--ca-moutarde-dim);
}

.search-suggestion.is-closed,
.search-suggestion.is-closed .search-suggestion-label {
  color: var(--ca-text-muted-light);
  text-decoration: line-through;
  text-decoration-color: rgba(192, 128, 128, 0.85);
}

.search-suggestion-label {
  display: block;
  width: 100%;
  text-align: left;
  white-space: normal;
  word-break: break-word;
}

/* Curseur décoratif « terminal prêt ». Le champ étant en `width: 0; flex: 1`,
   ce bloc vit à l'extrémité droite de la ligne, loin du texte saisi : dès que
   le vrai caret apparaît, les deux se contredisent. On l'efface donc au focus. */
.terminal-cursor {
  width: 0.5em;
  height: 1em;
  background: var(--ca-moutarde);
  animation: blink 1.1s step-end infinite;
  flex-shrink: 0;
}

.terminal-encart:focus-within .terminal-cursor {
  display: none;
}

@keyframes blink {
  50% {
    opacity: 0;
  }
}

.chips {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 2rem;
}

/* « Exemples : » était un `aria-label` : annoncé aux lecteurs d'écran, invisible à l'œil.
   Rien ne disait à quoi servaient trois noms d'entreprise posés sous un champ de recherche. */
.chips-label {
  font-size: var(--fs-s);
  color: var(--ca-text-muted);
}

.chip {
  font-size: 0.75rem;
  padding: 0.35rem 0.7rem;
  background: transparent;
  cursor: pointer;
  transition: border-color 0.15s, color 0.15s;
}

/* 2.75rem = 44 px, le plancher de cible tactile de la spec §2.4 : ces pastilles étaient à 26 px.
   Scopé à la home — `.chip` sert aussi de pastille de filtre actif sur /entreprises/ et
   /operations/, où une trentaine de pastilles à 44 px changerait la densité des pages. */
.page-home .chip {
  display: inline-flex;
  align-items: center;
  min-height: 2.75rem;
  font-size: var(--fs-s);
  padding: 0.35rem 0.85rem;
}

/* E0 #6 (2026-09-30, the user: « make the exemples smaller in height »): on the atlas cover
   the `.page-home` 44 px above held at EVERY width, taller than the 52 px « Rechercher » they
   sit under once their own padding is counted, for a pointer that does not need it. The 44 px
   floor is a touch rule (spec-design §2.4), and B17 already writes it for the touch tiers just
   below; with a mouse the chips go back to their own padding. The media rule below comes later
   at the same specificity, so a phone and a coarse tablet keep 44 px. */
[data-recherche] .chips .chip {
  min-height: 0;
  padding: 0.25rem 0.7rem;
}

/* B17 Q41 / Q49: the six chips of the error page are links alone on their line (31 px
   measured). Modifier added by components/erreur.html. */
@media (max-width: 767.98px), (max-width: 1023.98px) and (pointer: coarse) {
  .chips--atlas .chip,
  [data-recherche] .chips .chip { display: inline-flex; align-items: center; min-height: 44px; }
}

.mode-terminal .chip {
  border: 1px solid rgba(0, 0, 0, 0.12);
  color: var(--ca-text-muted);
}

.mode-lecture .chip {
  border: 1px solid rgba(0, 0, 0, 0.12);
  color: var(--ca-text-muted);
}

.chip:hover {
  border-color: var(--ca-moutarde);
  color: var(--ca-charbon);
  background: var(--ca-moutarde-dim);
}

/* Trois faits, chacun d'un bloc. En `flex-wrap` sur une seule ligne de texte, la coupure
   tombait au milieu d'un groupe et laissait des séparateurs « · » en début de ligne ; ce sont
   maintenant des `<li>`, séparés par la gouttière et non par un caractère. */
.proof-band {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.5rem 2rem;
  list-style: none;
  font-size: var(--fs-s);
  margin: 1.75rem 0 0;
  padding: 0.85rem 1.1rem;
  border-left: 3px solid var(--ca-moutarde);
  background: var(--ca-surface-dark);
}

@media (max-width: 767.98px) {
  .proof-band {
    flex-direction: column;
  }
}

.mode-terminal .proof-band,
.mode-lecture .proof-band {
  color: var(--ca-text-muted);
}

.proof-band .stat {
  color: var(--ca-charbon);
  background: var(--ca-moutarde);
  padding: 0.05em 0.3em;
  font-weight: 500;
  white-space: nowrap;
}

/* `white-space: nowrap` : « 340 000 » se coupait en « 340 » / « 000 » d'une ligne à l'autre,
   avec le surlignage jaune de part et d'autre — un chiffre de preuve devenait deux. */
.mode-terminal .module-body .stat,
.module-body.mono .stat {
  color: var(--ca-charbon);
  background: var(--ca-moutarde);
  padding: 0.05em 0.3em;
  font-weight: 500;
  white-space: nowrap;
}

/* ── Explorer grid ── */
/* Quatre cartes de même poids : aucune n'est mise en avant par la grille, chacune est une page.
   `align-items: stretch` (défaut) + `margin-top: auto` sur .module-link alignent tous les
   boutons sur la même ligne de base, quelle que soit la hauteur du corps. */
.section-lead {
  max-width: 52rem;
  margin: 0 0 1.75rem;
  font-size: var(--fs-m);
  line-height: 1.65;
  color: var(--ca-text-muted);
}

/* Deux colonnes au-delà de 768 px, et pas trois : à quatre cartes (avant D7), une grille en
   trois colonnes les rangeait 3 + 1 — un tiers de la page vide sous la première rangée, une
   carte orpheline sous la seconde. 2 × N remplit le conteneur aux deux paliers, et le tient
   toujours à six cartes (D7c : Secteurs · Entreprises · Fonds · Opérations · Liquidations ·
   Analyse), qui rangent proprement en 2 × 3 sans repenser la règle. Pas de troisième palier :
   l'échelle du site n'en a que deux (viewport.json). */
.explorer-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1rem;
}

@media (min-width: 768px) {
  .explorer-grid {
    grid-template-columns: repeat(2, 1fr);
    gap: 1.25rem;
  }
}

.module-card {
  position: relative;
  border: 1px solid var(--ca-hairline);
  background: var(--ca-blanc);
  box-shadow: 0 4px 16px rgba(43, 40, 38, 0.06);
  padding: 1.5rem;
  display: flex;
  flex-direction: column;
  min-height: 11rem;
  overflow: hidden;
  transition: border-color 0.18s, box-shadow 0.18s, transform 0.18s;
}

/* Liseré accent supérieur qui s'allume au survol. */
.module-card::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 3px;
  background: var(--ca-moutarde);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.25s ease;
}

.module-card:hover {
  border-color: rgba(250, 255, 105, 0.55);
  box-shadow:
    0 8px 28px rgba(0, 0, 0, 0.08),
    0 0 24px rgba(250, 255, 105, 0.15);
  transform: translateY(-3px);
}

.module-card:hover::before {
  transform: scaleX(1);
}

/* Le titre de carte était le texte le plus petit de la page (11,5 px, capitales, interlettrage
   ouvert) alors que c'est ce qu'on lit en premier. Il passe au cran « titre de bloc » de
   l'échelle (--fs-l) et perd les capitales, qui coûtent cher en vitesse de lecture. */
.module-title {
  font-size: var(--fs-l);
  line-height: 1.3;
  letter-spacing: 0;
  text-transform: none;
  color: var(--ca-charbon);
  margin: 0 0 0.85rem;
}

/* Le point cartographique du logo sert de puce (charte §5) : décoratif, donc masqué aux
   lecteurs d'écran côté gabarit, et détaché de la teinte du titre. */
.module-bullet {
  color: var(--ca-lien);
}

/* Colonne flex, et non un bloc : c'est ce qui permet à la ligne de chiffres finale de descendre
   en pied de carte (`margin-top: auto`) et donc de s'aligner d'une carte à l'autre, alors que
   les corps de texte au-dessus n'ont pas la même hauteur. */
.module-body {
  flex: 1;
  display: flex;
  flex-direction: column;
  font-size: var(--fs-m);
  color: var(--ca-charbon);
  line-height: 1.65;
}

.module-body > * + * {
  margin-top: 0.7rem;
}

/* Le bouton prend la largeur de la carte et 44 px de haut (spec §2.4) : il était en 12 px,
   aligné à droite, large d'une vingtaine de millimètres — la plus petite cible de la page pour
   l'action la plus importante. Le sélecteur descendant est nécessaire : `tokens.css` est chargé
   EN DERNIER, donc un `.module-link` écrit ici à spécificité égale serait mort (piège §5.1). */
.explorer-grid .module-link {
  align-self: stretch;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 2.75rem;
  margin-top: auto;
  padding: 0.6rem 1rem;
  font-family: var(--font-mono);
  font-size: var(--fs-s);
  color: var(--ca-charbon);
  text-align: center;
  transition: background 0.15s, border-color 0.15s, color 0.15s;
}

.explorer-grid .module-body {
  margin-bottom: 1.25rem;
}

/* Lien étiré : la carte entière devient la cible, pas seulement le bouton. C'est le gain
   principal au doigt, et il n'est licite que parce que chaque carte ne porte plus qu'UN lien —
   sinon le clic hors bouton désignerait une cible indécidable. Contrepartie assumée : le texte
   de la carte n'est plus sélectionnable à la souris. */
.explorer-grid .module-link::after {
  content: "";
  position: absolute;
  inset: 0;
}

/* Les exemples sont la seule chose de la carte qui échappe au lien étiré. `position` +
   `z-index` les font peindre APRÈS le calque `.module-link::after` (même contexte
   d'empilement, ordre du DOM) : le survol et le clic les atteignent, le reste de la carte
   reste le bouton. Sans ces deux lignes ils seraient visibles mais inertes. */
.module-examples {
  position: relative;
  z-index: 1;
  margin: 0.85rem 0 0;
  font-size: var(--fs-m);
  line-height: 1.9;
  color: var(--ca-text-muted);
}

.module-examples-label {
  margin-right: 0.35rem;
  font-size: var(--fs-s);
}

/* Au doigt, ces liens ne faisaient que 19 px de haut. On ne peut pas les porter à 44 px sans
   casser le fil du texte, mais on peut les épaissir : l'interlignage passe à 2,4 pour que les
   boîtes de deux lignes voisines ne se chevauchent pas, puis le rembourrage remplit le créneau
   ainsi libéré. Compact seulement — à la souris, 19 px suffisent et l'aération coûterait deux
   lignes de carte. */
@media (max-width: 767.98px) {
  .module-examples {
    line-height: 2.4;
  }

  .module-examples a {
    display: inline-block;
    padding: 0.45rem 0;
  }
}

/* Survoler la carte allume son bouton : une carte, un bouton, aucune ambiguïté. */
.module-card:hover .module-link {
  background: var(--ca-jaune);
  border-color: var(--ca-jaune);
  color: var(--ca-noir);
  text-decoration: none;
}

/* ── Veille ── */
#veille .cta-link {
  display: inline-flex;
  align-items: center;
  min-height: 2.75rem;
  padding: 0.6rem 1.25rem;
  font-size: var(--fs-s);
}

.veille-reassurance {
  margin-top: 1rem;
  font-size: 0.78rem;
  color: var(--ca-text-muted);
}

/* B17 Q48: 0.78 rem = 12.48 px is no step of the scale; a sentence takes --fs-s. Home only
   (`page-home--atlas`, accueil/page.html). */
.page-home--atlas .veille-reassurance { font-size: var(--fs-s); }

.messages {
  max-width: var(--max-width);
  margin: 0 auto;
  padding: 0.5rem 1.25rem;
}

.messages .error {
  color: var(--ca-rouge);
  font-size: 0.85rem;
}

/* ── Footer ── */
.ca-footer {
  border-top: 1px solid var(--ca-hairline);
  padding: 2.5rem 0 2rem;
}

.footer-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1.5rem 2rem;
  margin-bottom: 2rem;
}

@media (min-width: 768px) {
  .footer-grid {
    grid-template-columns: repeat(3, 1fr);
  }
}

.footer-col h4 {
  font-family: var(--font-mono);
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ca-charbon);
  margin: 0 0 0.75rem;
}

.footer-col ul {
  list-style: none;
  margin: 0;
  padding: 0;
  font-size: 0.8rem;
}

.footer-col li {
  margin-bottom: 0.4rem;
}

.footer-col a {
  color: var(--ca-text-muted);
}

/* Sur téléphone les entrées du pied de page font 15 px de haut, séparées de 6 px : deux
   liens voisins tiennent sous une pulpe de doigt. Elles passent au plancher de 44 px —
   le pied s'allonge, mais c'est le seul palier où on navigue au doigt. */
@media (max-width: 767.98px) {
  .footer-col a {
    display: flex;
    align-items: center;
    min-height: 2.75rem;
  }

  .footer-col li {
    margin-bottom: 0;
  }
}

/* ── Variante courte (pages de compte, pages d'erreur) ──────────────────────
   Pas de colonnes : une rangée de liens légaux, la signature, la ligne de
   transparence. Le pied reste reconnaissable sans occuper un tiers d'écran sur
   une page où l'on est venu saisir un mot de passe. */
.ca-footer--court {
  padding: 1.5rem 0 1.25rem;
}

/* `.mode-terminal .section-inner` pose 3 rem de padding vertical, qui s'ajoutent
   à celui du pied : la variante courte faisait 9 rem de haut pour trois lignes
   de texte. */
.ca-footer--court .section-inner {
  padding-top: 0;
  padding-bottom: 0;
}

.footer-court {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem 1.25rem;
  list-style: none;
  margin: 0 0 1.25rem;
  padding: 0;
  font-size: 0.8rem;
}

.footer-court a {
  color: var(--ca-text-muted);
}

/* Même plancher tactile que la version complète : sous 768 px, deux liens
   voisins doivent rester séparables au doigt. */
@media (max-width: 767.98px) {
  .footer-court a {
    display: flex;
    align-items: center;
    min-height: 2.75rem;
  }
}

.footer-signature {
  font-family: var(--font-mono);
  font-size: 0.85rem;
  color: var(--ca-charbon);
  margin-bottom: 0.75rem;
}

.footer-signature::first-letter {
  color: var(--ca-moutarde);
}

.footer-transparency {
  font-size: 0.8rem;
  color: var(--ca-text-muted);
  max-width: 36rem;
}

.footer-transparency a {
  color: var(--ca-charbon);
  text-decoration: underline;
  text-decoration-color: var(--ca-moutarde);
}

/* Ce lien est désormais la seule vérification possible de la phrase qui le
   précède (« Données publiques : … »), et il est présent sur tout le site : il
   passe le plancher tactile de 44 px comme les entrées des colonnes. `inline-flex`
   et non `min-height` seul — sur un élément inline, `min-height` ne fait rien. */
@media (max-width: 767.98px) {
  .footer-transparency a {
    display: inline-flex;
    align-items: center;
    min-height: 2.75rem;
  }
}

/* ── Composant pied de page, variante atlas (components/footer.html ; B3, spec-design §8.1
   decision 10, 2026-09-29) ─────────────────────────────────────────────────────────────────
   Le pied porte `.ca-footer--atlas`, qui corrige les règles ci-dessus. Deux corrections, mesurées :
     · quatre colonnes (spec-experience §5.3 : Explorer, Le projet, Légal, la signature et la
       ligne des sources) au lieu de trois plus une signature dessous ; deux colonnes sous 768.
     · le plancher tactile de 44 px monte jusqu'à 1023 px, le repli du header d'origine : les
       liens du pied mesuraient 17 px de haut à 820 px, un palier tactile qui gardait la densité
       du bureau. */
.ca-footer--atlas .footer-grid {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

@media (min-width: 768px) {
  .ca-footer--atlas .footer-grid {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

/* The atlas footer's height (2026-10-02, « a lot of scrolling »): 385 px at 1440 px for 185 px
   of content, because the frame's 3 rem (`.mode-terminal .section-inner`) stacked on the
   footer's own 2.5 rem / 2 rem and on the grid's 2 rem bottom margin, under which nothing is
   printed (the signature is the grid's fourth column). The short variant had already dropped
   the frame's padding for the same reason. One --sp-6 above and below. */
.ca-footer--atlas { padding: var(--sp-6) 0; }
.ca-footer--atlas .section-inner { padding-top: 0; padding-bottom: 0; }
.ca-footer--atlas .footer-grid { margin-bottom: 0; }

/* B17 (decision 13): the footer's text was 0.8 rem = 12.8 px on 40 pages at three tiers: not a
   step of the five-step scale (spec-design §2.2), and under the 13 px floor of a sentence. It
   takes --fs-s. */
.ca-footer--atlas .footer-col ul,
.ca-footer--atlas .footer-transparency { font-size: var(--fs-s); }

/* The signature sits in the fourth column: no second bottom margin under it. */
.footer-col--signature > :last-child {
  margin-bottom: 0;
}

@media (max-width: 1023.98px) {
  .ca-footer--atlas .footer-col a,
  .ca-footer--atlas .footer-court a {
    display: flex;
    align-items: center;
    min-height: 2.75rem;
  }

  .ca-footer--atlas .footer-col li {
    margin-bottom: 0;
  }

  .ca-footer--atlas .footer-transparency a {
    display: inline-flex;
    align-items: center;
    min-height: 2.75rem;
  }
}

/* Respect des préférences d'accessibilité : on coupe le mouvement. */
@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
}

/* ── Composant graphe (components/graphe.html ; spec-experience §6.10) ─────────────────
   Décision B13 du 2026-09-23 (spec-design §8.1) : l'encre du libellé suit le fond (blanc
   sur charbon, vert, olive ; charbon sur jaune et gris), réglée dans graphe.js. Ici la rangée
   de commandes, l'hôte du canevas (vis-network dessine dedans ; rien ne dimensionne le canvas
   qu'il produit, seulement la boîte qu'il remplit) et l'état plein écran —
   only the .graphe-cadre (controls + canvas) lifts out of flow, so the exit control stays
   reachable and the SSR list below keeps its scroll position while the canvas is fullscreen. */
.graphe-controles {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2) var(--sp-6);
  margin: 0 0 var(--sp-3);
  font-size: var(--fs-s);
}

.graphe-couches {
  display: inline-flex;
  flex-wrap: wrap;
  gap: var(--sp-3);
}

/* Checkboxes carry their label to the right, in sans (§6.11) — the one place this page's
   default mono runs against the rule, since a checkbox label is prose, not a code or a tag. */
.graphe-couche {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  font-family: sans-serif;
  font-size: var(--fs-s);
  color: var(--ca-charbon);
}

/* B17 Q41 / Q49: the layer filters are controls, each alone in its slot: the label around the
   13 px box is the target, 44 px on the touch tier (the box measured 13 x 13 in a 19 px label). */
@media (max-width: 767.98px), (max-width: 1023.98px) and (pointer: coarse) {
  .planche .graphe-couche { min-height: 44px; }
}

.graphe-cadre {
  position: relative;
}

.graphe-canevas {
  height: 22rem;
  border: 1px solid var(--ca-filet);
  background: var(--ca-surface);
}

/* Outside the full screen a finger on the canvas scrolls the page (user, 2026-10-02): Hammer,
   inside vis-network, writes `touch-action: none` inline on the <canvas> to keep every gesture
   for the graph, and a phone's reader could not get past the section. `!important` is what it
   takes against an inline style. `manipulation`, not `auto`: the double tap opens a node's
   plate (graphe.js), it must not zoom the page. graphe.js holds the other half (the moves
   never reach Hammer, so the graph stays still while the page goes). */
.graphe:not(.graphe--plein-ecran) .graphe-canevas,
.graphe:not(.graphe--plein-ecran) .graphe-canevas * {
  touch-action: manipulation !important;
}

/* The zoom buttons are on the section's canvas too since 2026-10-02 (user): the wheel
   scrolls the page there (graphe.js), so the buttons are the section's only zoom. They sat
   in the full screen alone from 2026-10-01, when the wheel still zoomed everywhere. The
   buttons sit together, closer than the row's own gap: one control, two ends. */
.graphe-zoom {
  display: inline-flex;
  gap: var(--sp-1);
}

/* On the touch tier a .ca-action of a section is 44 px tall (tokens.css, decision 11), but
   « + » and « − » are one glyph wide: 24 px measured, two targets side by side that a thumb
   cannot tell apart. The surface grows to the square, the glyph stays centred. */
@media (max-width: 767.98px), (max-width: 1023.98px) and (pointer: coarse) {
  .graphe-zoom .ca-action {
    min-width: 44px;
    justify-content: center;
  }
}

/* The line of help stays with the full screen (user, 2026-10-01): under the section's
   22rem canvas it would outweigh the graph. */
.graphe-aide {
  display: none;
}

/* « 24 liens dessinés sur 49 … » (graphe.js): under the canvas of a section, not in full screen,
   where every link is drawn. */
.graphe-note { margin: var(--sp-1) 0 0; }
.graphe--plein-ecran .graphe-note { display: none; }

/* A dense graph alone on its row (a phone has the same 22 rem: at 340 px wide the height is
   not what is missing). */
@media (min-width: 1024px) {
  .graphe--dense:not(.graphe--plein-ecran) .graphe-canevas { height: 26rem; }
}

.graphe--plein-ecran .graphe-aide {
  display: block;
  margin: 0;
}

.graphe--plein-ecran .graphe-cadre {
  position: fixed;
  inset: var(--sp-4);
  z-index: 100;
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  background: var(--ca-surface);
  border: 1px solid var(--ca-filet);
  padding: var(--sp-4);
}

/* min-height: 0 — sans lui l'enfant d'une colonne flex ne descend pas sous la hauteur de son
   contenu, et le canvas de vis-network (height: 100 % de son hôte) le faisait grandir au-delà du
   cadre : 1 014 px de canvas dans 868 px de cadre, mesurés le 2026-10-01. */
.graphe--plein-ecran .graphe-canevas {
  flex: 1 1 0;
  min-height: 0;
  height: auto;
}

/* ── Composant chart (components/chart.html ; spec-experience §6.9) ───────────────────
   Décision B14 du 2026-09-23 (spec-design §8.1) : le graphique de la page entreprise est
   gardé (valeur au-dessus de la barre, ligne de zéro et axe des années, trois graduations à
   gauche, point cerclé de blanc, dernière valeur écrite à côté du point, bande p25–p75 et
   médiane en tirets, légende à trois marques, phrase de position) et son bleu devient l'olive
   du site : --ca-lien est la teinte de la série, ses nuances celles du secteur (barres à
   55 %, bande à 12 %, médiane à 60 %). Gris et charbon (la série en encre) ont été dessinés
   et refusés.

   Deux couches (le même jour, « the fonts and sizes should match the rest of the page ») :
   le SVG ne porte que les formes et s'étire sur la colonne (preserveAspectRatio="none",
   traits non mis à l'échelle) ; chaque libellé et chaque point est un <span> posé en
   pourcentage sur le plan, au cran des jetons — dans le SVG, le libellé de 11 px se lisait
   19 px à 1 440 et 6 px à 390. Le SVG ne porte que des classes (chart-barre, chart-ligne,
   chart-bande, chart-mediane, chart-axe, chart-regle, chart-tick), jamais un fill ni un
   stroke (spec-design §1) ; le passage aux jetons se fait ici, par forme (.chart--<forme>),
   parce qu'une même classe s'encre autrement d'une forme à l'autre (.chart-mediane :
   polyligne horizontale en tirets dans ligne_bande, règle verticale pleine dans
   histogramme).                                                                          */
.chart {
  margin: 0;
}

/* Two planes of one section (the synthèse financière: the volume above the ratio). Without
   the gap the source line of the first read as the heading of the second. */
.chart + .chart {
  margin-top: var(--densite-groupe);
}

/* Two planes of one reading, side by side (« Synthèse financière »: the volume, then the ratio).
   Stacked on the full row they were 520 px of a 978 px section at 1440 px, each plane stretched
   to 1 066 px for nine bars (user, 2026-10-02: too much scrolling). From 1280 px, where the
   atlas row leaves each plane at least 590 px (a slot of 53 px for eleven years, the width of
   a « 163,1 M€ » label), they share the row; under it they stack as before. A pair with one
   plane keeps the full row. The seuil is the atlas header's own fold (tailwind/viewport.json
   `seuils_atlas`). */
.chart-paire {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--densite-groupe) var(--sp-8);
  align-items: start;
}

.chart-paire > .chart:only-child { grid-column: 1 / -1; }
.chart-paire > .chart + .chart { margin-top: 0; }

@media (max-width: 1279.98px) {
  .chart-paire { grid-template-columns: minmax(0, 1fr); }
}

/* Two to four charts of ONE section (the secteur plates: a section holds one chart per question).
   Two columns from 1280 px, one under it, the same fold as `.chart-paire`. The charts align on
   their PLANES, not on their titles: a figure spans three rows (tête, corps, pied) of the grid
   and takes them as a subgrid, so a title of two lines pushes the neighbour's plane down with
   it instead of leaving the two planes at two heights. The gap between two rows of charts is
   the figure's own bottom padding, since a subgrid row-gap would also open the tête-corps
   space. Without `subgrid` (old browsers) the figures simply stack and the planes sit where
   their titles put them: a degradation, not a break. */
.chart-grille {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  column-gap: var(--sp-8);
  row-gap: 0;
  align-items: start;
}
.chart-grille > .chart,
.chart-grille > .chart + .chart,
.chart-grille > .fourchette {
  display: grid;
  grid-template-rows: subgrid;
  grid-row: span 3;
  row-gap: 0;
  margin-top: 0;
  padding-bottom: var(--densite-groupe);
}
@media (min-width: 1280px) {
  .chart-grille { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

.chart-plan {
  position: relative;
  background: var(--ca-surface);
}

.chart-plan-interieur {
  position: relative;
  height: 100%;
}

/* La forme ligne_bande garde en rem ses deux marges : les trois graduations à gauche, la
   dernière valeur à droite du dernier point. En unités du viewBox elles rétrécissaient avec
   la colonne et coupaient « 13,2 % » à 390 px. */
.chart-plan--ligne_bande .chart-plan-interieur,
.chart-plan--lignes .chart-plan-interieur {
  margin: 0 3.5rem 0 3.25rem;
}

.chart-plan svg {
  display: block;
  width: 100%;
  height: 100%;
}

.chart-plan line,
.chart-plan polyline,
.chart-plan rect {
  vector-effect: non-scaling-stroke;
}

/* Bar charts of more than six years (B17 Q47, spec-design §8.1 decision 13). Two renderings of
   the same series share the figure: `.chart-complet` (every year) from 768 px, and
   `.chart-compact` (the last six, the older groups behind « Années précédentes ▾ ») under it.
   Eleven bars in a 305 px card were 28 px slots, the value labels wider than their bar. Only
   one of the two is ever displayed, and a figure with six years or fewer carries the complet
   alone (no `chart--replie`). The user chose this over staggering the labels (Q47 c): the
   older years are behind a fold, not gone. */
.chart-compact { display: none; }
@media (max-width: 767.98px) {
  .chart--replie .chart-complet { display: none; }
  .chart--replie .chart-compact { display: block; }
}
.chart-anterieurs { margin: 0 0 var(--sp-3); }
.chart-anterieurs > summary { list-style: none; gap: var(--sp-1); }
.chart-anterieurs > summary::-webkit-details-marker { display: none; }
.chart-anterieurs .chart-plan { margin-top: var(--sp-3); }
/* A column plane whose year labels run on two lines (« 2024 » over « (provisoire) »): the second
   line is 11 px of the label's own size, and the plane's height is fixed, so the room is left
   under it rather than taken from the bars. */
.chart-plan--qualifie { margin-bottom: var(--sp-4); }
/* Centred, or the year sits at the left of the box the wider « (provisoire) » makes and reads as
   the neighbour's. */
.chart-plan--qualifie .chart-etiquette--dessous { text-align: center; }
/* The same on a line form, where the one qualified year is a label of the axis
   (core/charts.py `_etiquettes_annees`): centred on its point, and the plane leaves the room
   of the second line under it. */
.chart-etiquette--qualifiee { text-align: center; }
.chart-plan:has(.chart-etiquette--qualifiee) { margin-bottom: var(--sp-4); }

.chart-titre {
  font-size: var(--fs-s);
  font-weight: 500;
  color: var(--ca-charbon);
  margin: 0 0 var(--sp-2);
}
/* The note under the question: the window and the n (« 2016 → 2025 · 6 827 ventes avec prix »). */
.chart-titre:has(+ .chart-note) { margin-bottom: var(--sp-1); }
.chart-note { margin: 0 0 var(--sp-2); font-size: var(--fs-xs); color: var(--ca-gris-fort); }
/* A chart with fewer than two points: the sentence, in the plane's place. */
.chart-vide { margin: 0; font-size: var(--fs-s); color: var(--ca-gris-fort); }

/* Un libellé du plan : mono au cran --fs-xs (le plancher de B1 vaut ici sans SVG pour le
   réduire), ancré par ses modificateurs — milieu / fin sur l'axe x, dessus / dessous /
   centre sur l'axe y, après = à droite d'une barre horizontale. */
.chart-etiquette {
  position: absolute;
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  line-height: 1;
  color: var(--ca-gris-fort);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.chart-etiquette--milieu { transform: translateX(-50%); }
.chart-etiquette--fin { transform: translateX(-100%); }
.chart-etiquette--dessus { margin-top: -4px; transform: translate(-50%, -100%); }
.chart-etiquette--dessous { margin-top: 6px; }
.chart-etiquette--centre { transform: translateY(-50%); }
.chart-etiquette--fin.chart-etiquette--centre { transform: translate(-100%, -50%); }
.chart-tick-libelle { left: 0; width: 2.75rem; text-align: right; color: var(--ca-gris); }
/* Anchored on a rule near an edge: the label grows inward instead of running out of the card
   (a median at 3 % of the axis, a last bound at 96 %). Same-specificity modifiers above would
   lose to `--dessus`, hence the compound selectors. */
.chart-etiquette--dessus.chart-etiquette--debut { transform: translateY(-100%); }
.chart-etiquette--dessus.chart-etiquette--fin { transform: translate(-100%, -100%); }
.chart-etiquette--gain { color: var(--ca-vert); }
.chart-etiquette--perte { color: var(--ca-rouge); }
.chart-etiquette--mediane { color: var(--ca-lien); font-weight: 500; }

/* A year label thinned by width (core/charts.py `_etiquettes_annees`): `data-rang` is the first
   tier at which it fits — 1 always, 2 from 768 px, 3 from 1024 px, 4 never (the point's card
   says the year). The tiers nest, so the axis only gains labels as it widens. */
.chart-etiquette[data-rang="4"] { display: none; }
@media (max-width: 767.98px) {
  .chart-etiquette[data-rang="2"],
  .chart-etiquette[data-rang="3"] { display: none; }
}
@media (max-width: 1023.98px) {
  .chart-etiquette[data-rang="3"] { display: none; }
}

/* Barres horizontales : des rangées HTML. Le libellé garde sa colonne en rem à tout palier ;
   sous compact il prend sa propre ligne au-dessus de la barre. */
/* The three columns belong to the CHART, not to each row: every row is a subgrid of
   .chart-rangees. When each row was its own grid, a short label or a short value gave its row a
   wider track, so the bars started at different places and their 100 % had different lengths:
   bars that are not on one baseline cannot be compared (user, 2026-10-10). */
.chart-rangees {
  display: grid;
  grid-template-columns: minmax(10rem, 18rem) 1fr auto;
  column-gap: var(--sp-3);
  row-gap: var(--sp-2);
}
.chart-rangee {
  display: grid;
  grid-column: 1 / -1;
  grid-template-columns: subgrid;
  align-items: center;
}
.chart-rangee-libelle,
.chart-rangee-valeur { font-size: var(--fs-xs); color: var(--ca-gris-fort); font-variant-numeric: tabular-nums; }
.chart-rangee-piste { display: block; height: 1.375rem; }
.chart-rangee-piste .chart-barre { display: block; height: 100%; background: rgb(var(--ca-lien-rgb) / 0.55); }
/* A row the sentence points at (§10.40: 60 ans et plus, the médiane's class) in the full ink; a
   row that is the absence of a value (« effectif inconnu », §7.4) in grey, label and bar. */
.chart-rangee-piste .chart-barre--accent { background: var(--ca-lien); }
.chart-rangee--discret .chart-rangee-libelle,
.chart-rangee--discret .chart-rangee-valeur { color: var(--ca-gris); }
.chart-rangee--discret .chart-barre { background: rgb(0 0 0 / 0.14); }
@media (max-width: 767.98px) {
  .chart-rangees { grid-template-columns: 1fr auto; }
  .chart-rangee { row-gap: var(--sp-1); }
  .chart-rangee-libelle { grid-column: 1 / -1; }
}

.chart-axe,
.chart-regle {
  stroke: var(--ca-filet);
  stroke-width: 1;
}

.chart--barres .chart-barre { fill: rgb(var(--ca-lien-rgb) / 0.55); }
/* Split bars (decided 2026-10-05, the CA of the company plate). First drawn as four tints of
   the olive (0.2 → 0.4 → 0.65 → 1): the user asked the same day for more contrast between the
   parts. Now the site's own families, as the frise of « Historique » does (§6.7): gris for the
   achats, light olive for the charges externes, full olive for the personnel, so that no two
   neighbours share a family and a weight; the EBE in the green of §6.7 (positive), whose
   opposite, a loss, is its red under the zero line. No blue (§6.7), no jaune (§6.2). A year
   with no split is an outline on the same plane, so it never reads as one of the parts. The
   EBE is drawn at the foot (charts._parts), so green meets the zero line and red hangs under it. */
.chart--parts .chart-barre { fill: rgb(var(--ca-lien-rgb) / 0.08); stroke: rgb(var(--ca-lien-rgb) / 0.55); stroke-width: 1; vector-effect: non-scaling-stroke; }
.chart-part--0 { fill: rgb(var(--ca-text-muted-rgb) / 0.45); }
.chart-part--1 { fill: rgb(var(--ca-lien-rgb) / 0.3); }
.chart-part--2 { fill: var(--ca-lien); }
.chart-part--3 { fill: var(--ca-vert-vif); }
/* The loss lies OVER the charges it leaves uncovered, which go on under the zero line: an
   opaque red hid them (the personnel of a loss year, at the foot since the order of
   2026-10-05, read as absent) and a 75 % red over the dark olive read as a brown band of its
   own. A light tint keeps the parts legible under it, the full red outline bounds the loss. */
.chart-perte { fill: rgb(var(--ca-rouge-rgb) / 0.3); stroke: var(--ca-rouge-vif); stroke-width: 1.5; vector-effect: non-scaling-stroke; }
/* The lines from a part's top to the same part the next year (charts._liaisons): thin and
   grey, under the weight of the bars, so they guide the eye without reading as a series. */
.chart-liaison { stroke: var(--ca-gris); stroke-width: 1; vector-effect: non-scaling-stroke; }
/* The top line follows the CA from one bar top to the next and met the value written over it
   (« 722,7 M€ » is wider than its bar at 390 px): the value takes the card's ground, the line
   passes behind it. */
.chart--parts .chart-etiquette--dessus { background: var(--ca-surface); padding: 0 2px; }
.chart-definitions { margin: var(--sp-2) 0 0; font-size: var(--fs-xs); color: var(--ca-gris-fort); }
.chart-definitions > summary { cursor: pointer; list-style: none; }
.chart-definitions > summary::-webkit-details-marker { display: none; }
/* The touch tier: the summary is a 44 px target (17 px measured at 390 under « Où vont 100 € »
   of the Secteur page, 2026-10-07). */
@media (max-width: 767.98px), (max-width: 1023.98px) and (pointer: coarse) {
  .chart-definitions > summary { display: inline-flex; align-items: center; min-height: 44px; }
}
.chart-definitions dl { margin: var(--sp-2) 0 0; }
.chart-definitions dt { font-weight: 500; color: var(--ca-charbon); }
.chart-definitions dd { margin: 0 0 var(--sp-1); }

.chart--ligne_bande .chart-ligne { fill: none; stroke: var(--ca-lien); stroke-width: 2.4; stroke-linejoin: round; }
.chart--ligne_bande .chart-bande { fill: rgb(var(--ca-lien-rgb) / 0.12); stroke: none; }
.chart--ligne_bande .chart-mediane { fill: none; stroke: rgb(var(--ca-lien-rgb) / 0.6); stroke-width: 1.4; stroke-dasharray: 4 3; }
/* Le point de la page entreprise : l'encre de la série, cerclée de blanc, pour rester un
   point sur la ligne. Un <span>, pas un <circle> : un cercle étiré est une ellipse. */
.chart-point {
  position: absolute;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--ca-lien);
  box-shadow: 0 0 0 1.4px var(--ca-surface);
  transform: translate(-50%, -50%);
}
.chart-dernier { color: var(--ca-lien); font-weight: 500; margin-left: 9px; }

.chart--histogramme .chart-barre { fill: rgb(var(--ca-lien-rgb) / 0.55); }
.chart--histogramme .chart-mediane { stroke: var(--ca-lien); stroke-width: 1.4; }
.chart--histogramme .chart-tick { stroke: var(--ca-gris-fort); stroke-width: 1; }

/* La phrase de position sous la légende (« sous la médiane du secteur »), signée. */
.chart-position { margin: var(--sp-2) 0 0; font-size: var(--fs-xs); font-weight: 500; }
/* The figure of a series of one exercice (components/chart.html): its year and its value. */
.chart-seul { margin: 0; font-size: var(--fs-s); color: var(--ca-gris-fort); }
.chart-seul strong { font-size: var(--fs-l); font-weight: 500; color: var(--ca-charbon); }
.chart-position--gain { color: var(--ca-vert); }
.chart-position--perte { color: var(--ca-rouge); }

.chart-legende {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-4);
  margin: var(--sp-2) 0 0;
  padding: 0;
  list-style: none;
  font-size: var(--fs-xs);
  color: var(--ca-gris-fort);
}

.chart-legende li {
  display: flex;
  align-items: center;
  gap: var(--sp-1);
}

.chart-legende-marque {
  display: inline-block;
  width: 1rem;
  height: 2px;
  background: var(--ca-lien);
}

.chart-legende-marque--bande {
  height: 0.6rem;
  background: rgb(var(--ca-lien-rgb) / 0.12);
  border: 1px solid rgb(var(--ca-lien-rgb) / 0.3);
}

.chart-legende-marque--mediane {
  height: 2px;
  background: repeating-linear-gradient(90deg, rgb(var(--ca-lien-rgb) / 0.6) 0 4px, transparent 4px 7px);
}
/* The swatches of a split bar (§10.33): a block, not a line, in the part's own tint. */
.chart-legende-marque--part { height: 0.6rem; }
.chart-legende-marque--part.chart-part--0 { background: rgb(var(--ca-text-muted-rgb) / 0.45); }
.chart-legende-marque--part.chart-part--1 { background: rgb(var(--ca-lien-rgb) / 0.3); }
.chart-legende-marque--part.chart-part--2 { background: var(--ca-lien); }
.chart-legende-marque--part.chart-part--3 { background: var(--ca-vert-vif); }
.chart-legende-marque--part.chart-perte { background: rgb(var(--ca-rouge-rgb) / 0.3); border: 1.5px solid var(--ca-rouge-vif); }
.chart-legende-marque--part.chart-barre { background: rgb(var(--ca-lien-rgb) / 0.08); border: 1px solid rgb(var(--ca-lien-rgb) / 0.55); }

/* ── Les formes ajoutées le 2026-10-02 pour les planches de secteur (plan-secteur-planches W2) ──
   Même règle que plus haut : le SVG ne porte que des classes, l'encre se décide ici par forme.
   Les séries se distinguent par l'encre DU SITE (olive, charbon, gris fort) ET par le style du
   trait ou du remplissage — jamais par la couleur seule (§6.7) ; le vert et le rouge ne disent
   que gain et perte. */

/* histogramme_classes : barres olive à 55 %, la classe ouverte plus claire (sa borne haute
   n'existe pas), le contour de la référence en charbon, sans remplissage. */
.chart--histogramme_classes .chart-barre { fill: rgb(var(--ca-lien-rgb) / 0.55); }
.chart--histogramme_classes .chart-barre--ouverte { fill: rgb(var(--ca-lien-rgb) / 0.3); }
.chart--histogramme_classes .chart-mediane { stroke: var(--ca-lien); stroke-width: 1.4; }
.chart--histogramme_classes .chart-tick { stroke: var(--ca-gris-fort); stroke-width: 1; }
.chart-reference { fill: none; stroke: var(--ca-charbon); stroke-width: 1.4; stroke-linejoin: miter; }
.chart-marqueur { stroke: var(--ca-charbon); stroke-width: 1.4; stroke-dasharray: 2 3; }
/* L'estimation du lecteur : écrite dans le tracé, sur un fond de surface pour rester lisible
   sur les barres, et ouverte du côté où il y a de la place (loin de l'étiquette de la médiane). */
.chart-marqueur-libelle {
  background: var(--ca-surface);
  padding: 1px 3px;
  color: var(--ca-charbon);
  font-weight: 500;
}
.chart-marqueur-libelle--d { margin-left: 3px; }
.chart-marqueur-libelle--g { margin-left: -3px; transform: translateX(-100%); }

/* lignes : trois encres, trois styles de trait. */
.chart--lignes .chart-ligne { fill: none; stroke-width: 2.4; stroke-linejoin: round; stroke-linecap: round; }
.chart--lignes .chart-ligne--s1 { stroke: var(--ca-lien); }
.chart--lignes .chart-ligne--s2 { stroke: var(--ca-charbon); stroke-dasharray: 6 4; }
.chart--lignes .chart-ligne--s3 { stroke: var(--ca-gris-fort); stroke-dasharray: 1 4.5; }
.chart-zero { stroke: var(--ca-gris-fort); stroke-width: 1; }
.chart-point--s2 { background: var(--ca-charbon); }
.chart-point--s3 { background: var(--ca-gris-fort); }
.chart-dernier--s2 { color: var(--ca-charbon); }
.chart-dernier--s3 { color: var(--ca-gris-fort); }
/* Un point est une cible de 7 px : la zone de survol déborde, sans changer ce qui se voit. */
.chart-point { cursor: default; }
.chart-point::before { content: ""; position: absolute; inset: -7px; }
.chart-point:focus-visible,
.chart-zone:focus-visible,
.fourchette-piste:focus-visible { outline: 2px solid var(--ca-charbon); outline-offset: 2px; }

/* Les formes en colonnes : la zone de survol couvre une année du plan, de haut en bas. */
.chart-zone { position: absolute; top: 0; bottom: 0; z-index: 1; }
.chart-zone:hover,
.chart-zone:focus-visible { background: rgb(var(--ca-lien-rgb) / 0.07); outline-offset: -2px; }

/* barres_empilees : 2 px de surface entre deux segments (le trait de surface, sans échelle,
   plutôt qu'un segment raccourci : la hauteur du segment reste exacte). Quatre teintes des encres
   du site, alternées olive / charbon pour que deux segments voisins ne se confondent pas. */
.chart--barres_empilees .chart-barre,
.chart--barres_signees .chart-barre { stroke: var(--ca-surface); stroke-width: 2; }
.chart--barres_empilees .chart-barre--c1 { fill: rgb(var(--ca-lien-rgb) / 0.85); }
.chart--barres_empilees .chart-barre--c2 { fill: rgb(var(--ca-lien-rgb) / 0.35); }
.chart--barres_empilees .chart-barre--c3 { fill: color-mix(in srgb, var(--ca-charbon) 70%, transparent); }
.chart--barres_empilees .chart-barre--c4 { fill: color-mix(in srgb, var(--ca-gris-fort) 40%, transparent); }

/* barres_signees : vert au-dessus du zéro, rouge dessous — exactement gain / perte (§6.7). */
.chart--barres_signees .chart-barre--gain { fill: rgb(var(--ca-vert-rgb) / 0.75); }
.chart--barres_signees .chart-barre--perte { fill: rgb(var(--ca-rouge-rgb) / 0.75); }

/* Les marques de légende de ces formes. */
.chart-legende-marque--s1 { height: 2px; background: var(--ca-lien); }
.chart-legende-marque--s2 { height: 2px; background: repeating-linear-gradient(90deg, var(--ca-charbon) 0 6px, transparent 6px 10px); }
.chart-legende-marque--s3 { height: 2px; background: repeating-linear-gradient(90deg, var(--ca-gris-fort) 0 1px, transparent 1px 5.5px); }
.chart-legende-marque--c1,
.chart-legende-marque--c2,
.chart-legende-marque--c3,
.chart-legende-marque--c4,
.chart-legende-marque--ici { width: 0.75rem; height: 0.75rem; }
.chart-legende-marque--c1 { background: rgb(var(--ca-lien-rgb) / 0.85); }
.chart-legende-marque--c2 { background: rgb(var(--ca-lien-rgb) / 0.35); }
.chart-legende-marque--c3 { background: color-mix(in srgb, var(--ca-charbon) 70%, transparent); }
.chart-legende-marque--c4 { background: color-mix(in srgb, var(--ca-gris-fort) 40%, transparent); }
.chart-legende-marque--ici { background: rgb(var(--ca-lien-rgb) / 0.55); }
.chart-legende-marque--reference { width: 1rem; height: 0.6rem; background: none; border: 1.4px solid var(--ca-charbon); }

/* ── Composant fourchette (components/fourchette.html ; plan-secteur-planches W2) ─────────
   La bande de prix : une à quatre rangées sur UNE échelle. Le libellé est AU-DESSUS de la piste
   (jamais à côté : une rangée ne déborde pas à 390 px) ; la bande Q1–Q3 est la teinte, la
   médiane la marque pleine ; les trois valeurs sont imprimées dessous, en mono. Tout est HTML
   posé en pourcentage de la piste. La rangée de référence (la population contre laquelle on
   compare) est au charbon ; les autres, dans l'olive de la série (§6.7 : aucune teinte de plus). */
.fourchette { margin: 0; }
.fourchette-rangees { position: relative; display: grid; gap: var(--sp-4); }
.fourchette-tete {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--sp-3);
  margin: 0 0 var(--sp-1);
  font-size: var(--fs-xs);
  color: var(--ca-gris-fort);
}
.fourchette-libelle { color: var(--ca-charbon); font-weight: 500; }
.fourchette-n { font-variant-numeric: tabular-nums; white-space: nowrap; }
.fourchette-piste {
  position: relative;
  height: 1.25rem;
  /* the scale's own baseline, so a band reads as a stretch of it */
  background: linear-gradient(var(--ca-filet), var(--ca-filet)) center / 100% 1px no-repeat;
}
.fourchette-bande {
  position: absolute;
  top: 0.1875rem;
  bottom: 0.1875rem;
  background: rgb(var(--ca-lien-rgb) / 0.22);
  border: 1px solid rgb(var(--ca-lien-rgb) / 0.55);
}
.fourchette-mediane {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 3px;
  margin-left: -1.5px;
  background: var(--ca-lien);
}
.fourchette-rangee--reference .fourchette-bande {
  background: color-mix(in srgb, var(--ca-charbon) 12%, transparent);
  border-color: color-mix(in srgb, var(--ca-charbon) 45%, transparent);
}
.fourchette-rangee--reference .fourchette-mediane { background: var(--ca-charbon); }
.fourchette-valeurs {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-1) var(--sp-4);
  margin: var(--sp-1) 0 0;
  padding: 0;
  list-style: none;
  font-size: var(--fs-xs);
  color: var(--ca-charbon);
  font-variant-numeric: tabular-nums;
}
.fourchette-valeur-nom { color: var(--ca-gris-fort); }
.fourchette-absent { margin: 0; font-size: var(--fs-xs); color: var(--ca-gris-fort); }
.fourchette-axe { position: relative; height: 1rem; }
.fourchette-axe-libelle {
  position: absolute;
  top: 0;
  font-size: var(--fs-xs);
  line-height: 1;
  color: var(--ca-gris);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.fourchette-axe-libelle--milieu { transform: translateX(-50%); }
.fourchette-axe-libelle--fin { transform: translateX(-100%); }

/* ============================================================================
   LES COMPOSANTS DE L'ATLAS (D0, 2026-09-23 — artifacts/site-structure.html §11.2)

   Un composant = un gabarit dans templates/graph/components/, ses règles dans UN bloc nommé
   ici (« Composant <nom> »), un contrat de contexte en tête du gabarit. Une page passe des données au composant et ne le
   restyle jamais ; un changement d'aspect est un changement dans un seul fichier ; une
   variante est un modificateur (`--<variante>`), jamais une copie. Ce que la revue de
   design a décidé est dans docs/specs/spec-design.md §8.1 ; ce qu'elle n'a pas revu garde
   les règles que la page de motifs /design/ (supprimée le 2026-10-14) a dessinées (B3, B4, B5, B6, B8, B12, B15, B16).

   Ordre de chargement (piège mesuré le 2026-09-23) : ce fichier est chargé AVANT tokens.css,
   donc une règle d'ici perd contre la même classe dans tokens.css à spécificité égale. Les
   classes des jetons (.ligne-donnee, .reperes, .planche-section, .avertissement, .etiquette,
   .bloc-source) ne sont donc jamais redéclarées ici : on les compose, on ne les corrige pas.
   ========================================================================== */

/* ── Aides : le texte réservé aux lecteurs d'écran ───────────────────────────────────────
   « (nouvel onglet) » sur un lien qui s'ouvre ailleurs (§6.5 demande le nom et interdit le
   signe visible : « ↗ » ne veut dire que « quitte le site »), « vers » entre la cible et
   l'acquéreur que la flèche dit à l'œil (§6.4). Les deux noms coexistent. */
.visually-hidden,
.sr-texte {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* La pastille active d'un filtre ou d'un motif (chronologie, QUAND) : un trait charbon,
   pas de fond. */
.chip--actif {
  border-color: var(--ca-charbon);
  color: var(--ca-charbon);
}

/* ── Tête de page sur surface claire : index, feuillet, page de compte ──────────────────
   Le kicker mono en capitales, le h1 au cran --fs-xl, la phrase d'accroche (§4.1, §5.5).
   Sur la surface sombre la cartouche a les siens (ci-dessous). */
.page-kicker {
  margin: 0 0 var(--sp-3);
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ca-gris-fort);
}

.page-titre {
  margin: 0 0 var(--sp-2);
  font-size: var(--fs-xl);
  font-weight: 500;
  line-height: 1.15;
  color: var(--ca-charbon);
}

.page-lead {
  font-size: var(--fs-m);
  line-height: 1.5;
  max-width: 68ch;
  margin: 0 0 var(--sp-6);
}

/* An index's coverage note (spec-experience §10.39): under the lead, which then gives up its
   bottom margin to it; grey and one step smaller, a qualification of the lead, not a second
   lead. */
.page-lead:has(+ .page-note) { margin-bottom: var(--sp-2); }
.page-note {
  font-size: var(--fs-s);
  line-height: 1.5;
  color: var(--ca-gris-fort);
  max-width: 68ch;
  margin: 0 0 var(--sp-6);
}

/* ── Colonne de lecture des feuillets (B3, non revu, §5.5) ─────────────────────────────
   68ch, la même mesure que .page-lead et .methode-ligne : une largeur de colonne pour tout
   long paragraphe du site ; un filet sous chaque h3 de feuillet (une section nommée, en
   bas-de-casse et en sans : un feuillet n'est pas une planche) ; la date de révision au pied. */
.colonne-lecture {
  max-width: 68ch;
}

.colonne-lecture h3 {
  margin: var(--sp-6) 0 var(--sp-2);
  padding-bottom: var(--sp-2);
  font-size: var(--fs-m);
  font-weight: 500;
  color: var(--ca-charbon);
  border-bottom: 1px solid var(--ca-filet);
}

.colonne-lecture p {
  font-size: var(--fs-m);
  line-height: 1.6;
  color: var(--ca-charbon);
}

.colonne-lecture .revision {
  margin-top: var(--sp-6);
}

/* ── Composant erreur (components/erreur.html ; §5.5 ; D7e) ─────────────────────────────
   Le rendu sans cartouche de graph/planche.html : la phrase (page-kicker/page-titre/page-lead
   ci-dessus), la recherche partagée, les six puces (.chips/.chip, déjà posés plus haut), puis
   le bouton de signalement (`erreur-signal-*`). */
.erreur-signal-bloc {
  margin-top: var(--sp-6);
  padding-top: var(--sp-3);
  border-top: 1px solid var(--ca-filet);
}

.erreur-signal {
  font: inherit;
  font-size: 0.9rem;
  padding: 0.5rem 0.9rem;
  cursor: pointer;
  border: 1px solid var(--ca-filet);
  background: transparent;
  color: var(--ca-lien);
}

.erreur-signal:hover {
  border-color: var(--ca-lien);
}

.erreur-signal[disabled] {
  cursor: default;
  color: var(--ca-text-muted);
  border-color: var(--ca-filet);
}

.erreur-signal-aide {
  margin: 0.6rem 0 0;
}

/* ── Feuillet (D9b, D10 ; B3 non revu) ───────────────────────────────────────────────────
   The column of an endpaper: centred, the short footer held at the foot of the window rather
   than in the middle of a short page. Its reader since 2026-10-09 is the six editorial pages
   alone (blog/base.html, `page-feuillet-projet`): the account pages left it that day for the
   index layout (accounts/base_compte.html, « Page compte » below), and `--large` with them. */
.page-feuillet {
  max-width: 40rem;
  margin: 0 auto;
  padding: var(--sp-8) var(--sp-4) var(--sp-12);
}

body.page-compte,
body.page-feuillet-projet {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

body.page-compte .ca-footer,
body.page-feuillet-projet .ca-footer {
  margin-top: auto;
}

/* Dans un conteneur flex, les marges automatiques de `.page-feuillet` l'emportent sur
   l'étirement transversal sans cette règle : la colonne se rétrécit à la largeur de son
   contenu au lieu de rester centrée sur toute la largeur disponible. */
body.page-feuillet-projet .page-feuillet {
  width: 100%;
}

/* ── Page compte (accounts/base_compte.html ; spec-experience §8.2, revised 2026-10-09) ────
   An account page is drawn as an index is (graph/index.html): the head on the grey ground at
   the atlas width, then `section` cards on the « Grille de panneaux ». Everything it shows is a
   component (section, formulaire, message, confirmation, tiroir, facets/rows) or a line of
   tokens.css; the one rule of its own is the foot link to the account's other home (« Ma
   veille › » / « Mon compte › »), under the grid, in the size of a source line. The `.veille-*`
   and `.lst-*` rules of D9e–D9f went with the pages they drew. */
body.page-compte main.compte { width: 100%; }

/* A head without a lead (Ma veille, a liste): the lead's own bottom margin is what an index puts
   between its head and its cards, so the h1 takes it when it ends the head. */
main.compte .page-titre:not(:has(+ .page-lead)) { margin-bottom: var(--sp-6); }

.compte-pied {
  margin: 0 0 var(--sp-6);
  font-size: var(--fs-s);
}

/* ── Composant cartouche (components/cartouche.html ; §3.1–3.2 ; B4 non revu) ──────────
   La surface sombre de la planche : le kicker et ses coordonnées en jaune (§6.2, « ici »),
   le h1 en mono, la ligne d'identité, l'adresse, la bande des repères de tokens.css sur sa
   variante sombre (B7), l'action, la ligne de source. La carte est un repère de plus (§3.2)
   et partage la largeur avec la bande ; sous 1024 px elle passe SOUS les chiffres, parce
   qu'un repère illisible ne trie rien (B17 Q40 : le seuil était 900 px, une largeur qu'aucune
   autre règle n'emploie ; entre 901 et 1023 px la carte côte à côte mesurait ~200 px avec une
   légende sur deux lignes).
   Cibles tactiles (B17 Q41, Q49) : les puces du kicker, « ☆ Suivre » et « Repères et carte ▾ »
   ont 44 px sur téléphone ET sur tablette au doigt (`pointer: coarse` sous 1024 px) ; une
   fenêtre de bureau rétrécie garde la densité de la grande palette.
   DENSITÉ VERTICALE (utilisateur, 2026-10-01 : « a lot of dead space »). Mesuré sur la planche
   de 552032534 à 1440 px : 881 px de haut, dont 216 de marges haute et basse (les 4rem / 3.5rem
   du `.hero` de l'accueil, plus les 3rem de `.section-inner`), 359 pour la colonne de la carte,
   et 16 à 24 px entre chaque bloc. Les réglages sont tous dans ce bloc : le cadre ci-dessous,
   puis un cran d'espacement de moins entre les lignes (--sp-4 → --sp-2, --sp-6 → --sp-4),
   la bande des repères resserrée, l'action et la recherche sur une rangée. La carte garde la
   hauteur de carte.css (300 px sur grand écran) : ramenée à 220 px, elle a été refusée le même
   jour ; elle s'ouvre en plein écran par son propre bouton (carte.css).
   Les planchers de 44 px du doigt ne
   sont pas touchés. */
.planche .cartouche.hero {
  padding-top: var(--sp-4);
  padding-bottom: var(--sp-2);
}

.planche .cartouche > .section-inner { padding-block: var(--sp-6); }

.cartouche-kicker {
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--ca-text-muted-dark);
  margin: 0 0 var(--sp-2);
}

.cartouche-kicker a { color: var(--ca-jaune); }

.cartouche-kicker .sep {
  margin: 0 var(--sp-1);
  color: var(--ca-text-muted-dark);
}

/* `.cartouche .cartouche-titre`, not the bare class: the homepage's OWN `.hero h1` (plus loin
   dans ce fichier, 32ch/2.4rem, pensé pour « ◉ entreprise atlas ») pèse (0,1,1) contre (0,1,0)
   pour la classe seule — une classe de plus ici (0,2,0) le bat sans toucher à cette règle plus
   ancienne ni à son propre commentaire ; découvert en câblant --fs-hero le 2026-09-29 : le token
   se résolvait, la cascade le perdait quand même. */
.cartouche .cartouche-titre {
  font-family: var(--font-mono);
  font-size: var(--fs-hero);
  font-weight: 500;
  line-height: 1.15;
  color: var(--ca-text-on-dark);
  margin: 0 0 var(--sp-3);
}

/* Un secteur ou une cellule ont pour h1 une PHRASE (§3.2 : « Prix de vente d'un fonds de
   boulangerie : 4 812 ventes réelles… »), pas un nom : à --fs-hero elle remplissait la moitié
   du viewport en mono. Les autres genres (entreprise, personne, opération, acte, fonds) gardent
   --fs-hero, un nom tient toujours sur peu de mots. Décision de revue B4-1, spec-design §8.1,
   2026-09-29 ; l'option refusée était de raccourcir la phrase elle-même. */
.cartouche--secteur .cartouche-titre,
.cartouche--cellule .cartouche-titre {
  font-size: var(--fs-xl);
}

.cartouche-titre a {
  color: var(--ca-text-on-dark);
  text-decoration: none;
}

/* B17 Q41 / Q49: the two names of an opération's h1 are links on their own (42 px measured).
   One pixel of padding above and below on the INLINE link: it adds to the box the finger hits
   and to nothing else (an inline box's vertical padding does not move the line). */
@media (max-width: 767.98px), (max-width: 1023.98px) and (pointer: coarse) {
  .planche .cartouche-titre a { padding-block: 1px; }
}

/* La flèche d'une opération, « cible → acquéreur » : un signe de donnée (§6.4), en jaune. */
.cartouche-fleche {
  margin: 0 var(--sp-3);
  color: var(--ca-jaune);
}

.cartouche-identite {
  font-size: var(--fs-s);
  color: var(--ca-text-muted-dark);
  margin: 0 0 var(--sp-4);
}

.cartouche-identite a { color: var(--ca-jaune); }

.cartouche-identite .sep { margin: 0 var(--sp-2); }

/* L'adresse du siège, une ligne sous l'identité (§3.1) : elle remonte sur la marge basse de
   la ligne d'identité pour lui rester attachée. */
.cartouche-adresse {
  font-size: var(--fs-s);
  color: var(--ca-text-muted-dark);
  margin: calc(-1 * var(--sp-3)) 0 var(--sp-4);
}

.cartouche-lead {
  font-size: var(--fs-m);
  color: var(--ca-text-muted-dark);
  margin: 0;
  max-width: 44rem;
}

.cartouche-corps {
  display: grid;
  grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
  gap: var(--sp-4) var(--sp-6);
  align-items: start;
}

.cartouche-corps--sans-carte { grid-template-columns: 1fr; }

/* `.planche` (the plate's <main>). */
@media (max-width: 1023.98px) {
  .planche .cartouche-corps { grid-template-columns: 1fr; }
}

/* « Repères et carte ▾ » : le repli du cartouche d'un onglet (components/cartouche.html,
   B17 Q39). Il n'existe que sous 1024 px, comme le bouton du panneau des critères ; au-dessus,
   la bande est ouverte et le bouton n'est jamais dessiné. `.cartouche` dans le sélecteur : le
   `display` de `.ca-action` (tokens.css, chargé après ce fichier) l'emporterait sinon. */
.cartouche .cartouche-bouton { display: none; margin: 0 0 var(--sp-4); }
@media (max-width: 1023.98px) {
  .cartouche .cartouche-bouton { display: inline-flex; align-items: center; gap: var(--sp-2); }
}

.cartouche-corps .reperes { margin: 0; }

/* La bande des repères dans le cartouche : 8 px de marge intérieure au lieu de 16, le libellé
   à 4 px de sa valeur au lieu de 8 (tokens.css pose les valeurs de la bande d'une section, qui
   respire sur une carte blanche ; ici elle est une ligne de la tête). */
.planche .cartouche .reperes {
  padding-block: var(--sp-2);
  row-gap: var(--sp-2);
}

.planche .cartouche .repere .libelle { margin-top: var(--sp-1); }

/* ── The company cartouche as the plate's overview (spec-design §8.1 decision 18, 2026-10-02) ──
   SIX FIGURES IN THE BAND (graph/entreprise/planche.py `_reperes`): the effectif, then the five
   of the latest exercice. One row from 1024 px: the first column is half as wide again for the
   effectif, whose value is words (« 10 000 et plus »), the five others hold « 133,6 M€ » at
   --fs-l (110 px with the trait). Keyed on the band having six tiles, so a company without
   accounts keeps its two repères on the ordinary grid. Under 1024 px: three columns, and two
   on a phone (tokens.css).
   THE NAME BESIDE THE MAP, from 1024 px: the map is the right column of the WHOLE cartouche
   and no longer of the band alone, so the kicker, the name and the identity sit beside it
   instead of above it: 699 px became about 500 on 301984563, the map keeping its 300 px
   (carte.css; 220 px was refused on 2026-10-01). `.cartouche-corps` is `display: contents`
   there: its two children become cells of the cartouche's own grid. The ninth row is the one
   that stretches when the map is taller than the text, so the lines of the left column stay
   together at the top. */
@media (min-width: 1024px) {
  .planche .cartouche--entreprise > .section-inner {
    display: grid;
    grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
    grid-template-rows: repeat(8, auto) 1fr;
    column-gap: var(--sp-6);
  }

  .planche .cartouche--entreprise > .section-inner > *,
  .planche .cartouche--entreprise .cartouche-principal { grid-column: 1; }

  .planche .cartouche--entreprise .cartouche-corps { display: contents; }

  .planche .cartouche--entreprise .cartouche-carte {
    grid-column: 2;
    grid-row: 1 / span 9;
    align-self: start;
  }

  .planche .cartouche--entreprise .reperes:has(> .repere:nth-child(6)) {
    grid-template-columns: minmax(0, 1.5fr) repeat(5, minmax(0, 1fr));
    column-gap: var(--sp-4);
  }
}

@media (min-width: 768px) and (max-width: 1023.98px) {
  .planche .cartouche--entreprise .reperes:has(> .repere:nth-child(6)) {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

/* The Secteur page's cartouche (plan-atlas-sans-fonds P2.3, spec-experience §3.2): the level
   below the fil (« 173 communes ▾ »), the critères as words, « Modifier ▾ » and « Comparer à … ▾ ».
   Three plain <details>; their list opens under the summary in the flow (no floating panel: a
   dropdown over the repères would hide what it compares). The summaries are the touch tier's
   44 px targets, the links of a list too. */
/* Block boxes with inline-flex summaries: as a plain inline summary the 44 px target of the
   touch tier overlapped the sentence under it (phone check of 2026-10-07 at 390 px). */
.cartouche-depli,
.cartouche-choix { display: block; margin: var(--sp-2) 0 var(--sp-3); }
.cartouche-depli > summary,
.cartouche-choix > summary { display: inline-flex; align-items: center; gap: var(--sp-1); cursor: pointer; list-style: none; }
.cartouche-depli > summary::-webkit-details-marker,
.cartouche-choix > summary::-webkit-details-marker { display: none; }
.cartouche-depli-liste {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-1) var(--sp-4);
  margin: var(--sp-2) 0 0;
  padding: 0;
  list-style: none;
  font-size: var(--fs-s);
}
.cartouche-criteres {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2) var(--sp-4);
  margin: var(--sp-3) 0 0;
  font-size: var(--fs-s);
}
.cartouche-criteres .cartouche-choix { margin: 0; }
.cartouche-criteres .cartouche-choix[open] { flex-basis: 100%; }
@media (max-width: 767.98px), (max-width: 1023.98px) and (pointer: coarse) {
  .cartouche .cartouche-depli > summary,
  .cartouche .cartouche-choix > summary,
  .cartouche .cartouche-depli-liste a { display: inline-flex; align-items: center; min-height: 44px; }
}

/* « Carte ▾ » (components/cartouche.html): the phone's door to the map; no such button from
   768 px, where the map is open. `.cartouche` in the selector for the same reason as
   `.cartouche-bouton` above (tokens.css's `.ca-action` is loaded after this file). */
.cartouche .cartouche-carte-bouton { display: none; margin: var(--sp-3) 0 0; }
@media (max-width: 767.98px) {
  .cartouche .cartouche-carte-bouton { display: inline-flex; align-items: center; gap: var(--sp-2); min-height: 44px; justify-self: start; }
  .cartouche .cartouche-carte { margin-top: var(--sp-3); }
}

/* La colonne des repères ; `min-width: 0` pour qu'un nom long de la liste ci-dessous se replie
   au lieu d'élargir la piste de la grille et de pousser la carte hors du cadre. */
.cartouche-principal { min-width: 0; }

/* La phrase d'une procédure en cours (planche entreprise, §3.2 révisé le 2026-10-01) :
   l'avertissement de tokens.css, filet jaune et rien d'autre, sur la surface sombre où son
   texte charbon serait illisible. Elle remonte sur la marge basse de la ligne au-dessus
   d'elle, comme l'adresse, et rend la même marge avant les repères. */
.cartouche .cartouche-avertissement {
  color: var(--ca-text-on-dark);
  margin: calc(-1 * var(--sp-1)) 0 var(--sp-4);
  padding-block: var(--sp-1);
}

/* « Dirigeants et associés » dans le cartouche (planche entreprise, §3.2 et §3.4 ligne 1
   révisés le 2026-10-01) : sous la bande des repères, une ligne par titulaire, le rôle en mono
   dans une colonne fixe pour que les noms s'alignent, puis le nom, l'âge entre parenthèses et
   « depuis … » en gris. Les noms sont des liens du cartouche et prennent le jaune de `.hero a`
   (tokens.css). Le titre a le gabarit du kicker, pas celui d'un titre de section : la liste
   appartient à la tête de la planche. */
.cartouche-mandats { margin: var(--sp-4) 0 0; }

.cartouche-mandats-titre {
  font-size: var(--fs-xs);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--ca-text-muted-dark);
  margin: 0 0 var(--sp-1);
}

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

.cartouche-mandat {
  display: grid;
  grid-template-columns: 12rem minmax(0, 1fr);
  gap: 0 var(--sp-4);
  /* 2 px, l'écart de `.repere .precision` : une ligne de 23 px, cinq lignes en 115 px. */
  padding: 2px 0;
  font-size: var(--fs-s);
  color: var(--ca-text-on-dark);
}

.cartouche-mandat-role,
.cartouche-mandat-detail,
.cartouche-mandats-vide { color: var(--ca-text-muted-dark); }

.cartouche-mandats-vide {
  font-size: var(--fs-s);
  margin: 0;
}

/* Le repli de fold.js (`data-fold="5"`) : ses deux règles ne sont posées que dans
   `.planche-section` (plus bas) ; sur le fond sombre
   le bouton prend l'inversion de `.hero .ca-action` (tokens.css). */
.cartouche .fold-hidden { display: none; }

.cartouche .fold-toggle {
  margin-top: var(--sp-2);
  border-color: var(--ca-jaune);
  color: var(--ca-jaune);
}

/* Sur téléphone le rôle passe au-dessus du nom : à 390 px la colonne de 12rem ne laissait que
   la moitié de la largeur au nom. Le nom est un lien seul sur sa ligne, il prend le plancher
   de 44 px (B17 Q41), le bouton du repli aussi. */
@media (max-width: 767.98px) {
  .cartouche-mandat { grid-template-columns: 1fr; }
}

@media (max-width: 767.98px), (max-width: 1023.98px) and (pointer: coarse) {
  .planche .cartouche-mandat-corps a,
  .planche .cartouche .fold-toggle { display: inline-flex; align-items: center; min-height: 44px; }
}

/* Le pied du cartouche : « ☆ Suivre » et la ligne de recherche sur UNE rangée, qui se replie
   quand la largeur manque. Ils occupaient deux rangées et 16 px entre elles. */
.cartouche-pied {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2) var(--sp-6);
  margin: var(--sp-4) 0 0;
}

.cartouche-pied .cartouche-action,
.cartouche-pied .cartouche-recherche { margin: 0; }

.cartouche-action { margin: var(--sp-4) 0 0; }

/* « Rechercher « <nom> » sur internet » : la ligne des moteurs, sous l'action (§3.1, révisé le
   2026-10-01 ; la planche entreprise seule). Une ligne au cran de l'identité, pas un second
   bouton : « Suivre » reste la seule action (§6.3). Les liens prennent le jaune de `.hero a`
   (tokens.css), comme ceux du kicker. Le `flex` pose les « · » à leur place et laisse la
   ligne se replier sous un nom long. */
.cartouche-recherche {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0 var(--sp-2);
  font-size: var(--fs-s);
  color: var(--ca-text-muted-dark);
  margin: var(--sp-4) 0 0;
}

@media (max-width: 767.98px), (max-width: 1023.98px) and (pointer: coarse) {
  /* Les moteurs sont des liens seuls sur leur rangée, pas des liens dans une phrase : le
     plancher de 44 px, comme les puces du kicker (B17 Q41). */
  .planche .cartouche-recherche a { display: inline-flex; align-items: center; min-height: 44px; }
  /* Le kicker devient une rangée de puces de 44 px (elles en mesuraient 14) ; le `flex` rend
     les « · » à leur place sans les compter comme des cibles. */
  .planche .cartouche-kicker { display: flex; flex-wrap: wrap; align-items: center; }
  .planche .cartouche-kicker a { display: inline-flex; align-items: center; min-height: 44px; }
  .planche .cartouche .cartouche-action .ca-action,
  .planche .cartouche .cartouche-bouton { display: inline-flex; align-items: center; min-height: 44px; }
}

/* L'état « suivi » du bouton du cartouche (D9d) : jaune plein sur le fond sombre — sa
   signification « ici » sur ce fond (§6.2), la même que le CTA de nav actif — jamais un
   second bouton plein à côté (§6.3, il REMPLACE le seul bouton du cartouche, il ne s'ajoute
   pas). */
.hero .ca-action.est-actif {
  background: var(--ca-jaune);
  border-color: var(--ca-jaune);
  color: var(--ca-noir);
}

.cartouche-source {
  font-size: var(--fs-xs);
  color: var(--ca-text-muted-dark);
  margin: var(--sp-3) 0 0;
}

/* ── Composant rail (components/rail.html ; §3.3 ; B5 revu 2026-09-29, spec-design §8.1) ──
   Collant sous l'en-tête, mono en capitales, défile avec son affordance (.rail, viewport.css) ;
   l'entrée courante porte un TRAIT JAUNE de 2 px (§6.2 : « ici » sur toute surface, jamais
   comme texte — remplace un trait olive, --ca-lien, qui n'était pas la couleur que la
   spec nomme pour ce rôle). Les ancres atterrissent sous lui : `scroll-margin-top` sur
   .planche-section (tokens.css).
   `top: var(--header-height)`, pas `0` : les deux étaient collants au même point, donc le
   header (z-index 100) peignait par-dessus le rail (z-index 40) dès que la page défilait — le
   défaut critique B5 de la revue. `--header-height` est le seul nombre : `.ca-header` ne le
   consomme pas lui-même (son header a d'autres soucis de hauteur, hors de cette revue) mais
   c'est la valeur mesurée sur SA boîte, donc la source unique reste bien là et pas un second
   littéral ici. */
.planche-rail {
  position: sticky;
  top: var(--header-height);
  z-index: 40;
  background: var(--ca-surface);
  border-bottom: 1px solid var(--ca-filet);
}

.planche-rail .section-inner {
  max-width: var(--max-width);
  margin: 0 auto;
  padding: var(--sp-2) 1.25rem;
  gap: var(--sp-6);
}

.planche-rail a {
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ca-gris-fort);
  white-space: nowrap;
  padding: var(--sp-1) 0;
}

.planche-rail a:hover { color: var(--ca-charbon); }

.planche-rail a.est-courant {
  color: var(--ca-charbon);
  box-shadow: inset 0 -2px 0 var(--ca-jaune);
}

/* B17 Q41 / Q49: an entry is 44 px tall on the touch tier (25 px in a 42 px band measured on
   12 plates, 78 links). The link fills the band, whose own vertical padding goes: the sticky
   chrome grows from 103 to 105 px, not by 44. The yellow rule of the current entry stays at
   the link's foot. The touch tier is a phone, or a tablet under 1024 px with a finger.
   `.planche` is the plate's <main>. */
@media (max-width: 767.98px), (max-width: 1023.98px) and (pointer: coarse) {
  .planche .planche-rail .section-inner { padding-block: 0; }
  .planche .planche-rail a { display: inline-flex; align-items: center; min-height: 44px; padding-block: 0; }
}

/* ── Grille de panneaux (graph/planche.html ; spec-design §8.1 decision 17, 2026-10-02) ──────
   The sections of a plate sit on twelve columns from 1280 px (the atlas header's own seuil,
   tailwind/viewport.json `seuils_atlas`) and take the width their content needs: a graph
   seven, a frise five. The user chose it on a drawing (artifacts/densite-propositions.html)
   over one column and over tabs: one column gave « Agréments et conventions » two lines of
   text in a card 1 336 px wide. Under 1280 px a cell is the full row.
   NO HOLES, two rules. (1) core/planche.py fills every row to twelve. (2) The cells of a row
   share its height (the grid stretches them) and the LAST card of a cell takes what is left,
   its source line at the foot: two cards side by side end on the same line, whatever each
   holds. The row gap is the cards' own bottom margin, so a pile and a row use one number
   (tokens.css `--densite-entre-cartes`).
   The spans are classes, not a style attribute: no template writes a style (spec-design §1). */
.panneaux {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--densite-entre-cartes);
}

.panneau {
  display: flex;
  flex-direction: column;
  min-width: 0;
  grid-column: span 12;
}

.panneau--4 { grid-column: span 4; }
.panneau--5 { grid-column: span 5; }
.panneau--6 { grid-column: span 6; }
.panneau--7 { grid-column: span 7; }
.panneau--8 { grid-column: span 8; }
.panneau--9 { grid-column: span 9; }
.panneau--10 { grid-column: span 10; }
.panneau--11 { grid-column: span 11; }

/* The last card of a cell that shares its row fills the cell. A column flex container, so
   that the source line can sit at the foot (`margin-top: auto`); `min-width: 0` because a flex
   item's default is its content's width, and a table's scroll box would push the card wider
   than its cell. A cell alone on its row keeps the card as a plain block: every plate that
   declares no width renders exactly as before. */
.panneau:not(.panneau--12) > .planche-section:last-child {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
}

.panneau:not(.panneau--12) > .planche-section:last-child > * { min-width: 0; }
.panneau:not(.panneau--12) > .planche-section:last-child > .bloc-source:last-child { margin-top: auto; padding-top: var(--sp-2); }

@media (max-width: 1279.98px) {
  .panneaux .panneau { grid-column: span 12; }
  .panneaux .panneau > .planche-section:last-child { display: block; }
}

/* A graph in a stretched card takes the height the card was given (« Réseau » beside a pile
   taller than its canvas): the canvas grows instead of leaving the card half empty.
   vis-network follows its container. The four boxes between the card and the canvas each pass
   the height down; `:not([hidden])`, since the vue control hides a panel by that attribute. */
@media (min-width: 1280px) {
  .panneau:not(.panneau--12) > .planche-section:last-child > [data-vue="graphe"]:not([hidden]),
  .panneau:not(.panneau--12) > .planche-section:last-child .graphe:not(.graphe--plein-ecran),
  .panneau:not(.panneau--12) > .planche-section:last-child .graphe:not(.graphe--plein-ecran) .graphe-cadre {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    min-height: 0;
  }

  .panneau:not(.panneau--12) > .planche-section:last-child .graphe:not(.graphe--plein-ecran) .graphe-canevas {
    /* 18 rem and not the 22 of a graph alone on its row: beside a pile that is one short card
       (« Historique » alone: 232 to 330 px) the graph's own 555 px left the pile's card half
       blank, 263 and 294 px on two of eight companies walked on 2026-10-02. It grows with a
       taller pile, and « Plein écran » is one button away. (16 rem was tried: five nodes of a
       force layout touched the frame on five of twenty-nine companies.) */
    flex: 1 1 18rem;
    height: auto;
    min-height: 18rem;
    /* No taller than it is wide (a cell of seven columns is about 45 rem): a network is
       round, and past the square the height is blank above and below it. */
    max-height: 45rem;
  }

  /* More than twelve neighbours (graphe.js `graphe--dense`): 26 rem at least, the fourteen
     rows a side of the fan's twenty-four neighbours at the size of the page's text. */
  .panneau:not(.panneau--12) > .planche-section:last-child .graphe--dense:not(.graphe--plein-ecran) .graphe-canevas {
    flex-basis: 26rem;
    min-height: 26rem;
  }

  /* The same for a map (the fonds plate: beside a pile of 1 019 px the map's card was 482 px of
     blank under a 300 px map, walk of 2026-10-02). Leaflet follows its box (carte.js). */
  .panneau:not(.panneau--12) > .planche-section:last-child > .carte:not(.carte--plein-ecran) {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    min-height: 0;
  }

  .panneau:not(.panneau--12) > .planche-section:last-child > .carte:not(.carte--plein-ecran) > .carte-cadre {
    flex: 1 1 auto;
    height: auto;
    min-height: 18.75rem;
  }
}

/* ── Sommaire (spec-design §8.1 decision 18, 2026-10-02; section.js) ────────────────────────
   On a phone a plate was a column of everything, open: 9.3 screens for 301984563, seven of
   them between « Réseau » and « Actes ». The sections now load CLOSED, each on its head: the
   title, the count and the key fact of the section (« dernier : fusion, 12/02/2026 »). A tap
   on the head opens the section in place; a rail entry opens the one it points at.
   CLOSED IS NOT `display: none`. The body keeps its width at zero height, so a script that
   measures its box at load (the chain's lanes, the graph's canvas) draws at the right size,
   ready when the section opens. `!important`: the bodies are whatever a block prints, each
   with its own margins and paddings.
   `(scripting: enabled)`: the closed state is the DEFAULT of the stylesheet, so that the page
   does not load open and then jump shut; without JavaScript nothing could open a section, and
   the rule does not apply (a browser that does not know the feature keeps everything open).
   A plate asks for it (`data-sommaire`, core/planche.py `sommaire_compact`): from three
   sections, and never on a tab. */
@media (max-width: 767.98px) and (scripting: enabled) {
  .panneaux[data-sommaire] .planche-section:not(.est-ouverte) > :not(.planche-section-tete) {
    /* A block: an inline child (the fold's button) would keep a line of the card's height. */
    display: block !important;
    height: 0 !important;
    min-height: 0 !important;
    margin: 0 !important;
    padding: 0 !important;
    border: 0 !important;
    overflow: hidden !important;
    visibility: hidden !important;
  }

  .panneaux[data-sommaire] .planche-section:not(.est-ouverte) > .planche-section-tete {
    margin-bottom: 0;
    padding-bottom: 0;
    border-bottom: 0;
  }

  .panneaux[data-sommaire] .planche-section:not(.est-ouverte) .vues { display: none; }
}

@media (max-width: 767.98px) {
  /* The head of a sommaire: the title, then the fact on its own line, in full; the sign at the
     right says the head opens (§6.4). 44 px at least: the head is the target. */
  .panneaux[data-sommaire] .planche-section-tete {
    position: relative;
    align-items: center;
    min-height: 44px;
    padding-right: var(--sp-6);
    cursor: pointer;
  }

  .panneaux[data-sommaire] .planche-section-tete::after {
    content: "▸";
    position: absolute;
    top: 0.75rem;
    right: 0;
    font-family: var(--font-mono);
    font-size: var(--fs-s);
    color: var(--ca-lien);
  }

  .panneaux[data-sommaire] .planche-section.est-ouverte > .planche-section-tete::after { content: "▾"; }

  .panneaux[data-sommaire] .planche-section-tete > .planche-section-titre { flex: 1 1 100%; }
  .panneaux[data-sommaire] .planche-section-fait { flex: 1 1 100%; white-space: normal; }

  /* The title's own button (section.js wraps the words in one, the accordion pattern: a
     heading that holds a button): the words as they were, no frame. */
  .planche-section-bascule {
    all: unset;
    cursor: pointer;
  }

  .planche-section-bascule:focus-visible { outline: 2px solid var(--ca-lien); outline-offset: 2px; }
}

/* The margins close with the sections (decision 19): « Autour de cette page » was 500 px of
   44 px links under the last section of a phone's plate. Its title is the head; section.js
   opens it. Links to other pages, nothing a script measures: `display: none` is enough. */
@media (max-width: 767.98px) and (scripting: enabled) {
  .panneaux[data-sommaire] ~ .planche-marges:not(.est-ouverte) > .marge-groupe { display: none; }
}

@media (max-width: 767.98px) {
  .panneaux[data-sommaire] ~ .planche-marges > .marges-titre {
    display: flex;
    align-items: center;
    justify-content: space-between;
    min-height: 44px;
    cursor: pointer;
  }

  .panneaux[data-sommaire] ~ .planche-marges > .marges-titre::after { content: "▸"; color: var(--ca-lien); }
  .panneaux[data-sommaire] ~ .planche-marges.est-ouverte > .marges-titre::after { content: "▾"; }
}

@media print {
  .panneaux[data-sommaire] .planche-section > * { height: auto !important; visibility: visible !important; overflow: visible !important; }
}

/* ── Composant section (components/section.html, the {% section %} tag; §3.6; B6: the card
   was decided by decision 7, the rest by decision 11 of 2026-09-29, spec-design §8.1) ─────
   The head: the mono caps title with its count and, at its right, the vue control when the
   section has two renderings of the same data. ONE RULE under the whole head (Q3): it used to
   sit under the title alone and left a 144 px hole above the control at 1 440 px (title 923 px
   in a 1 067 px head); on compact the control drops under the title, still above the rule.
   The three states are sentences (§7.5), a line's folded text is a <details> (§6.13), the
   fold of lists is fold.js. */
.planche-section-tete {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-2) var(--sp-4);
  flex-wrap: wrap;
  margin: 0 0 var(--densite-bloc);
  padding-bottom: var(--sp-2);
  border-bottom: 1px solid var(--ca-charbon);
}

.planche-section-titre {
  flex: 1 1 auto;
  margin: 0 0 var(--sp-4);
  font-size: var(--fs-s);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ca-gris-fort);
  border-bottom: 1px solid var(--ca-charbon);
  padding-bottom: var(--sp-2);
}

/* The key fact of a section (components/section.html, decision 18): a sentence at the size of
   a fact, after the title, cut with « … » on one line; the title then keeps its own width and
   the fact takes what is left before the vue control. */
.planche-section-fait {
  flex: 1 1 0;
  min-width: 0;
  margin: 0;
  font-size: var(--fs-s);
  color: var(--ca-charbon);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.planche-section-tete > .planche-section-titre:has(+ .planche-section-fait) { flex: 0 1 auto; }

/* The empty sentence as the key fact (the section tag sets it when a section has no body): a
   closed section on a phone says « Aucun changement de contrôle publié… » on its head instead
   of a title alone; on a wide screen the body says it, once. */
.planche-section-fait--vide { display: none; }
@media (max-width: 767.98px) {
  .panneaux[data-sommaire] .planche-section-fait--vide { display: block; color: var(--ca-gris-fort); }
}

/* A title bare in a card (« La pièce »'s page titles, the pattern page's specimens) keeps its
   own rule; inside a head it gives the rule to the head. */
.planche-section-tete > .planche-section-titre {
  margin: 0;
  padding-bottom: 0;
  border-bottom: 0;
}

/* One rule between two elements (B2 d): a head whose rule would fall directly on a band or on
   a table head loses its own. */
.planche-section-tete:has(+ .reperes, + .table-donnees-conteneur, + .table-donnees) {
  border-bottom: 0;
  padding-bottom: 0;
  margin-bottom: var(--sp-2);
}

/* Le contrôle de vue : deux boutons mono accolés, l'actif au trait charbon (§3.6). Sert aussi
   à la tête de liste d'un index (Liste · Carte). */
.vues {
  display: flex;
  gap: 0;
  margin: 0;
  flex: 0 0 auto;
}

.vue {
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  padding: var(--sp-1) var(--sp-3);
  border: 1px solid var(--ca-filet);
  background: transparent;
  color: var(--ca-gris-fort);
  cursor: pointer;
}

.vue + .vue { border-left: none; }

.vue.est-active {
  border-color: var(--ca-charbon);
  color: var(--ca-charbon);
}

/* The touch floor on compact (spec-design §2.4): the surface grows, not the type. */
@media (max-width: 767.98px) {
  /* A narrower pad on compact so that the vue control and « ☆ Suivre cette recherche » share
     one line of the list head at 390 px (121 + 186 px did not fit the 305 px of a card;
     decision 11, Q7). */
  .vue { min-height: 44px; min-width: 44px; padding-inline: var(--sp-2); }
}
/* And on a tablet held in the hand (768-1023 px): the toggle measured 24 px tall at 820 px
   (decision 12, B11 defaults); the floor of 44 px follows the touch tiers, not only the phone. */
@media (min-width: 768px) and (max-width: 1023.98px) {
  .vue { min-height: 44px; }
}

/* Les trois états de §3.6. La phrase vide est une phrase, en sans : c'est ce que dit §6.6. */
.bloc-vide,
.bloc-indisponible {
  font-size: var(--fs-m);
  color: var(--ca-gris-fort);
  margin: 0;
}

.bloc-gated a { font-family: var(--font-mono); }

.bloc-note {
  font-size: var(--fs-xs);
  color: var(--ca-gris-fort);
  margin: 0 0 var(--sp-3);
}

/* B17 Q48: a note in SANS is a sentence (« Ici, un fonds sur 500 change de mains… »), and a
   sentence's floor is 13 px; the notes written in mono (`.bloc-note.mono`: a cap, a legend)
   keep 11. Scoped to a plate's card. */
main:not(.planche-fonds) .planche-section .bloc-note:not(.mono) { font-size: var(--fs-s); }

/* The coverage note of a section (spec-experience §3.6, §10.39): a sentence above the source
   line, after a body or an empty sentence; both end flush, so it takes the gap the source line
   would have taken and the source line follows it closely. */
.bloc-note--couverture { margin: var(--sp-2) 0 var(--sp-1); }
/* Under a list followed by another group (« Publié, 12 mois », then « Issue des procédures »):
   the next group title needs the gap a section's source line would not have taken. */
.bloc-note--sous-liste { margin-bottom: var(--sp-6); }

/* B17 Q41 / Q49: « voir tous les comptes annuels › », « toutes les entreprises de … › » stand
   alone on their line (`.bloc-lien`), so they take the 44 px floor of the touch tier. */
@media (max-width: 767.98px), (max-width: 1023.98px) and (pointer: coarse) {
  .planche .planche-section .bloc-lien a { display: inline-flex; align-items: center; min-height: 44px; }
}

/* Le texte replié d'une ligne (« le texte ▸ », §6.13) et le texte lui-même. */
.ligne-texte { margin-top: var(--sp-1); }

.ligne-texte summary {
  cursor: pointer;
  font-size: var(--fs-xs);
  color: var(--ca-lien);
  list-style: none;
}

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

.texte-annonce {
  display: block;
  margin-top: var(--sp-2);
  white-space: pre-wrap;
  font-size: var(--fs-s);
  color: var(--ca-gris-fort);
}

/* The fold (fold.js): « ▸ Afficher les 25 suivantes », an action of the section (§3.6), the
   same words as an index. The button is a .ca-action of tokens.css (its frame, its hover, its
   44 px target under compact); the section only gives it a margin, in normal case (capitals
   are for titles, decision 11). Carried by .planche-section: the fonds cells, which have no
   rule of their own for this button, keep theirs as is.
   WHY `.planche-section .fold-hidden` AND NOT `.fold-hidden` ALONE: `.ligne-donnee` and the
   other components set a `display` (grid) that beat the one-class rule. On the plate a fold
   « hid » 27 lines that stayed on screen (measured 2026-09-29 on Danone's Réseau), and the
   `hidden` attribute of the motif filter hid nothing either. Two classes beat one; the
   attribute is treated the same way. */
.planche-section .fold-hidden,
.planche-section [hidden] { display: none; }

.planche-section .fold-toggle {
  margin-top: var(--sp-2);
}

/* ── Composant marges (components/marges.html ; §3.5 ; B8 non revu) ────────────────────
   « Autour de cette page » : jusqu'à trois groupes en colonnes, un titre mono par groupe,
   « tous les … › » en olive, « Ailleurs ↗ ». */
.planche-marges {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: var(--sp-6);
  border-top: 1px solid var(--ca-filet);
  padding-top: var(--sp-6);
}

.marges-titre {
  grid-column: 1 / -1;
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ca-gris-fort);
  margin: 0;
}

.marge-titre {
  font-size: var(--fs-xs);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ca-gris-fort);
  margin: 0 0 var(--sp-2);
}

.marge-ligne {
  padding: var(--sp-1) 0;
  font-size: var(--fs-s);
}

.marge-tous a { color: var(--ca-lien); }

/* A long group (the homonymes of a person: nineteen names on one plate, a column 600 px tall
   beside an empty row) takes the row and sets its lines in columns (2026-10-02). From eight
   lines: the three to five of §3.5 and their « tous … › » stay one column. */
.marge-groupe:has(.marge-ligne:nth-child(8)) { grid-column: 1 / -1; }
.marge-groupe:has(.marge-ligne:nth-child(8)) > .liste-donnees { columns: 15rem; column-gap: var(--sp-6); }
.marge-ligne { break-inside: avoid; }

/* B17 Q41 / Q49: a margin line is a link alone on its line, so it takes the 44 px floor on the
   touch tier (17 px measured, 84 links on 9 plates). The row grows by 27 px; a link inside a
   sentence would keep its size (spec-design §2.4, the one exception). */
@media (max-width: 767.98px), (max-width: 1023.98px) and (pointer: coarse) {
  .planche .marge-ligne { padding: 0; }
  .planche .marge-ligne a { display: flex; align-items: center; min-height: 44px; }
}

/* ── Composant methode (components/methode.html ; §3.4 « Fonds cell » ligne 6) ──────────
   Trois phrases en sans, au cran --fs-s, sur la colonne de lecture.
   DEUX COLONNES quand la carte en a la place (2026-10-02) : sur une carte de 1 290 px la colonne
   de 78ch laissait la moitié droite vide et la méthode d'une cellule mesurait 458 px. `columns`
   avec une largeur de colonne : sous 2 × 34rem la carte reste à une colonne d'elle-même, sans
   palier ; une phrase ne se coupe pas entre deux colonnes. */
.methode {
  columns: 2 34rem;
  column-gap: var(--sp-8);
}

.methode-ligne { break-inside: avoid; }

.methode-ligne {
  font-size: var(--fs-s);
  line-height: 1.55;
  max-width: 78ch;
  margin: 0 0 var(--sp-3);
  color: var(--ca-gris-fort);
}

/* ── Composant definition (components/definition.html ; §3.4 « Secteur » ligne 1 ; E0 #14 S4) ──
   Le texte explicatif de l'INSEE d'un code NAF : un résumé, puis des séries « Comprend »,
   « Comprend aussi », « Ne comprend pas » en listes à tirets. Une colonne de lecture (78ch, comme
   la méthode), le sans au cran --fs-s. Les séries sont séparées par un filet à gauche, celui de
   `.ligne-donnee` : « Ne comprend pas » a le sien, plus appuyé, pour que l'exclu se lise à part
   sans un mot de couleur (§6.7). Le repli d'un texte long est un <details> nu (§6.13). */
.definition { max-width: 78ch; }

.definition-texte {
  font-size: var(--fs-s);
  line-height: 1.55;
  color: var(--ca-charbon);
  margin: 0 0 var(--sp-3);
}

.definition-groupe {
  margin: 0 0 var(--sp-4);
  padding-left: var(--sp-3);
  border-left: 2px solid var(--ca-filet);
}

.definition-groupe--exclu { border-left-color: var(--ca-gris-fort); }

.definition-titre {
  font-size: var(--fs-xs);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ca-gris-fort);
  margin: 0 0 var(--sp-2);
}

.definition-liste {
  list-style: none;
  margin: 0 0 var(--sp-2);
  padding: 0;
  font-size: var(--fs-s);
  line-height: 1.55;
  color: var(--ca-charbon);
}

.definition-liste > li { padding: var(--sp-1) 0; }

/* A sub-item sits one step in, with its own dot: INSEE's « • ». */
.definition-liste--sous { margin: var(--sp-1) 0 0; padding-left: var(--sp-4); }
.definition-liste--sous > li::before { content: "• "; color: var(--ca-gris-fort); }

.definition-suite > summary {
  cursor: pointer;
  font-size: var(--fs-xs);
  color: var(--ca-lien);
  margin: 0 0 var(--sp-3);
}

/* The summary is a 44 px target on the touch tier, like the other one-line controls (B17 Q41). */
@media (max-width: 767.98px), (max-width: 1023.98px) and (pointer: coarse) {
  .planche .definition-suite > summary { display: flex; align-items: center; min-height: 44px; }
}

/* ── Composant tiroir (components/tiroir.html ; §6.13 ; décision du 2026-10-01) ──────────────
   Une partie d'une section repliée derrière son propre sous-titre : la seconde lecture de
   « Synthèse financière » (comptes consolidés ouverts, comptes sociaux dans le tiroir). Le
   titre EST un `.groupe-titre` (tokens.css) : ouvert ou fermé, le sous-titre se lit pareil ;
   seuls le signe ▸ / ▾ (§6.4) et le curseur disent qu'il se déplie. Un <details> nu, sans
   script. */
.tiroir { margin: var(--densite-groupe) 0 var(--sp-3); }

/* `.tiroir > …`: tokens.css is loaded after this sheet, so its `.groupe-titre` (space-between,
   its own margin) would win at equal specificity and push the words away from their sign. */
.tiroir > .tiroir-titre {
  justify-content: flex-start;
  margin: 0;
  cursor: pointer;
  list-style: none;
}

.tiroir-titre::-webkit-details-marker { display: none; }
.tiroir-titre::before { content: "▸"; }
.tiroir[open] > .tiroir-titre::before { content: "▾"; }
.tiroir-titre:hover { color: var(--ca-charbon); }

.tiroir-corps { padding-top: var(--sp-3); }

/* The summary is a 44 px target on the touch tier, like the other one-line controls (B17 Q41). */
@media (max-width: 767.98px), (max-width: 1023.98px) and (pointer: coarse) {
  .planche .tiroir-titre { align-items: center; min-height: 44px; }
}

/* ── Composant chronologie (components/chronologie.html ; §6.9 ; B12 revu 2026-09-29, décision 12)
   Les lignes sont des .ligne-donnee (tokens.css) ; ici le marqueur du jour : un <li> nu,
   jamais une .ligne-donnee, pour qu'il ne soit jamais pris pour une ligne (pas de
   data-motif : le filtre ne le touche pas, « aujourd'hui » est la seule chose que toute vue
   filtrée montre encore). Le trait est jaune (B1) ; le libellé est la marque du jour de
   tokens.css (jaune plein sous du charbon), la même que celle de la frise. */
.chronologie-aujourdhui {
  margin: var(--sp-2) 0;
  padding: var(--sp-1) var(--sp-3);
  border-left: 2px solid var(--ca-jaune);
  font-size: var(--fs-xs);
  letter-spacing: 0.04em;
  color: var(--ca-gris-fort);
}

/* La source d'une ligne, quand deux sources se mêlent (Historique : Sirene et BODACC) : à la
   taille de la date qu'elle accompagne. Elle mesurait 15 px à côté d'une date de 11 px. */
.chronologie .ligne-cote .discret { font-size: var(--fs-xs); }

/* Le filtre de motif : une ligne qui défile de côté sur compact, des pastilles de 44 px (elles
   faisaient 28 px et, à six, occupaient trois lignes). Une pastille ne rétrécit pas : c'est la
   ligne qui défile. */
.chronologie-filtre { margin-bottom: var(--sp-3); }
@media (max-width: 767.98px) {
  .chronologie-filtre { flex-wrap: nowrap; overflow-x: auto; }
  .chronologie-filtre .chip { flex: 0 0 auto; }
}
@media (max-width: 767.98px), (max-width: 1023.98px) and (pointer: coarse) {
  .chronologie-filtre .chip {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
  }
}

/* La cible d'un lien de ligne et de « le texte ▸ » sur compact : 17 px de haut mesurés. Le
   remplissage agrandit la zone qui répond au toucher, la marge négative rend la place ; rien ne
   bouge dans la page. */
@media (max-width: 767.98px) {
  .chronologie .ligne-corps > a {
    display: inline-block;
    padding: 13px 0;
    margin: -13px 0;
  }
  .chronologie .ligne-texte summary {
    padding: 13px 0;
    margin: -13px 0;
  }
}

/* ── Composant frise (components/frise.html ; spec-design §8.1 décision 2, revue le jour même)
   Un groupe de frises en HTML avec des pourcentages : le texte garde les crans des jetons à
   toute largeur. Une bande teintée par période, une nuance par attribut, un connecteur à
   travers les voies à chaque changement, des caps aux extrémités, des cartes au survol.

   LES NUANCES SONT CELLES DU SITE (décision du 2026-09-23, après une première passe en quatre
   teintes étrangères : « use the website colors or shades to keep a uniform look ») :
   dénomination olive (--ca-lien), forme juridique jaune (--ca-jaune, le surlignage), activité
   charbon, siège gris ; le nom de la voie est écrit à côté de chacune, l'identité n'est jamais
   la couleur seule. Chaque voie règle ses forces de teinte, les quatre nuances n'ayant pas la
   même clarté (un mélange de jaune à 22 % est invisible, de charbon déjà sombre). La voie
   état garde l'encre : son sens est porté par les caps (vert immatriculation, rouge
   cessation, §6.7). Aucun jeton nouveau. */
/* --frise-bas: the row under the axis that carries « aujourd'hui » (decision 12, B12 Q36): the
   label used to sit ON the axis and printed over the year 2026 of a company created in 2021. */
.frise {
  --frise-bas: 1.75rem;
  position: relative;
  padding: var(--sp-8) 0 calc(var(--sp-8) + var(--frise-bas));
  font-size: var(--fs-xs);
}

/* --voie : le trait et le contour ; --teinte / --teinte-courante : la bande, passée et courante. */
.frise-voie[data-voie="1"] { --voie: var(--ca-lien); --teinte: 22%; --teinte-courante: 40%; }
.frise-voie[data-voie="2"] { --voie: var(--ca-jaune); --teinte: 45%; --teinte-courante: 85%; }
.frise-voie[data-voie="3"] { --voie: var(--ca-charbon); --teinte: 14%; --teinte-courante: 26%; }
.frise-voie[data-voie="4"] { --voie: var(--ca-gris); --teinte: 24%; --teinte-courante: 42%; }
.frise-voie[data-voie="5"] { --voie: var(--ca-charbon); --teinte: 14%; --teinte-courante: 20%; }
/* 6: the lane of « Procédure collective » (spec-design §8.1 decision 15). Grey, the siège's own
   strengths: a procédure in progress is grey (§6.12). No new token. */
.frise-voie[data-voie="6"] { --voie: var(--ca-gris); --teinte: 24%; --teinte-courante: 42%; }

.frise-voie {
  display: grid;
  grid-template-columns: 9rem minmax(0, 1fr);
  align-items: center;
  gap: var(--sp-3);
  min-height: 2rem;
}

.frise-nom {
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ca-gris-fort);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  padding-left: var(--sp-3);
  border-left: 3px solid var(--voie, var(--ca-charbon));
  line-height: 1.2;
}

.frise-piste {
  position: relative;
  height: 2rem;
  min-width: 0;
}

/* La grille, les moments et l'axe couvrent la seule colonne des pistes : le même retrait de
   9 rem que les noms de voie. */
.frise-grille,
.frise-axe {
  position: absolute;
  left: calc(9rem + var(--sp-3));
  right: 0;
}

.frise-grille { top: 0; bottom: 0; pointer-events: none; }

.frise-annee {
  position: absolute;
  top: var(--sp-6);
  bottom: calc(var(--sp-6) + var(--frise-bas));
  border-left: 1px solid var(--ca-filet);
}

/* Un moment : toute voie qui change ici se lit sur un seul trait, daté en haut. */
.frise-moment {
  position: absolute;
  top: var(--sp-4);
  bottom: calc(var(--sp-6) + var(--frise-bas));
  border-left: 1px dashed var(--ca-gris-fort);
}

.frise-moment-date {
  position: absolute;
  top: -1rem;
  left: 0;
  transform: translateX(-50%);
  font-size: var(--fs-xs);
  color: var(--ca-gris-fort);
  white-space: nowrap;
}

/* The today rule: yellow, as everywhere (B1: yellow is « ici », a rule on any surface), from
   the moments' row down to the label's row, crossing the axis (core/charts.py keeps the year
   ticks out of its way). Its label is the token `.marque-aujourdhui`, the same one the
   chronology list prints, right-aligned so that it ends on the rule. */
.frise-aujourdhui {
  position: absolute;
  top: var(--sp-4);
  bottom: 0;
  border-left: 2px solid var(--ca-jaune);
}

.frise-aujourdhui-libelle {
  position: absolute;
  bottom: 0;
  right: 0;
}
.frise-aujourdhui-libelle[data-cote="g"] { right: auto; left: 0; }

/* A frise of the past (decision 15): no today rule, since today is off its axis; the sentence
   that says how long ago it ended takes the today label's place. It has the label's own build
   (`.marque-aujourdhui`: mono, the same padding) on the charbon ground instead of the yellow:
   a first version in small secondary grey was too light to say « this is over » (the user,
   2026-10-01), and yellow means « ici, aujourd'hui » and nothing else. */
.frise-passe {
  position: absolute;
  right: 0;
  bottom: 0;
  font-size: var(--fs-xs);
  font-weight: 500;
  line-height: 1.4;
  padding: 1px var(--sp-2);
  background: var(--ca-charbon);
  color: var(--ca-text-on-dark);
  white-space: nowrap;
}

.frise-axe { bottom: calc(var(--sp-1) + var(--frise-bas)); height: 1rem; }

.frise-axe-annee {
  position: absolute;
  transform: translateX(-50%);
  white-space: nowrap;
  font-size: var(--fs-xs);
  color: var(--ca-gris-fort);
}

/* A label at the edge of the track stays inside it instead of centring across the edge. */
.frise-axe-annee[data-alignement="debut"],
.frise-moment-date[data-alignement="debut"] { transform: none; }
.frise-axe-annee[data-alignement="fin"],
.frise-moment-date[data-alignement="fin"] { transform: translateX(-100%); }

/* THE THINNING (decision 12, B12 Q38): each label carries the first width tier at which it fits
   (core/charts.py `_rangs`, tracks of 275 / 527 / 783 px); a label under its tier is hidden,
   and a rang 4 one never shows (its value stays in the hover card). The tiers are the site's
   own: under 768 px, from 768, from 1024. */
.frise [data-rang="4"] { display: none; }
@media (max-width: 767.98px) {
  .frise [data-rang="2"], .frise [data-rang="3"] { display: none; }
}
@media (min-width: 768px) and (max-width: 1023.98px) {
  .frise [data-rang="3"] { display: none; }
}
/* In a panel that shares its row (« Grille de panneaux », decision 17) the track is about
   350 px at 1440 px (a cell of five columns, less the lane names): the phone's tier, not the
   screen's. With the labels of the wide tier « 1975 » and « 1980 » printed on each other. */
.panneau:not(.panneau--12) .frise [data-rang="2"],
.panneau:not(.panneau--12) .frise [data-rang="3"] { display: none; }
@media (min-width: 1024px) and (max-width: 1279.98px) {
  /* Under 1280 px the cell is the full row again and the wide tier's labels fit. */
  .panneau:not(.panneau--12) .frise [data-rang="2"],
  .panneau:not(.panneau--12) .frise [data-rang="3"] { display: revert; }
}
@media (min-width: 768px) and (max-width: 1023.98px) {
  .panneau:not(.panneau--12) .frise [data-rang="2"] { display: revert; }
}

/* Une période : une bande teintée de la nuance de sa voie, sa valeur en charbon dedans (le
   relief de contraste), 2 px de surface avant la bande suivante. La période courante est la
   teinte forte avec le trait pleine nuance dessous ; un début inconnu, un bord gauche en
   tirets. */
.frise-bande {
  position: absolute;
  top: 50%;
  height: 18px;
  margin-top: -9px;
  box-sizing: border-box;
  padding: 0 var(--sp-1);
  background: color-mix(in srgb, var(--voie) var(--teinte), var(--ca-surface));
  border-right: 2px solid var(--ca-surface);
  border-bottom: 2px solid color-mix(in srgb, var(--voie) calc(var(--teinte) * 2), var(--ca-surface));
  overflow: visible;
  cursor: default;
}

.frise-bande--courante {
  background: color-mix(in srgb, var(--voie) var(--teinte-courante), var(--ca-surface));
  border-bottom-color: var(--voie);
}

.frise-bande--courante .frise-valeur { font-weight: 500; }

.frise-bande--inconnue {
  border-left: 2px dashed var(--voie);
  background: repeating-linear-gradient(135deg, color-mix(in srgb, var(--voie) var(--teinte), var(--ca-surface)) 0 6px, var(--ca-surface) 6px 8px);
}

/* A band that carries a meaning of §6.7 over its lane's hue: the liquidation of the procédure
   lane is red (what ends the company) among the grey sauvegarde and redressement. --voie is
   reset on the band itself, so its rule, its outline and its card's edge follow. */
.frise-bande--perte { --voie: var(--ca-rouge-vif); --teinte: 18%; --teinte-courante: 30%; }

.frise-bande:hover,
.frise-bande:focus-visible {
  outline: 2px solid var(--voie);
  outline-offset: 1px;
}

/* The touch floor (decision 12, B12 Q38): a 9 px cap or a 18 px band is no target on a phone.
   An invisible box grows around the mark (44 px, at least 44 px wide) and belongs to it, so a
   tap on it focuses the mark and its card opens; nothing moves on the page. */
@media (max-width: 767.98px), (max-width: 1023.98px) and (pointer: coarse) {
  .frise-bande::after,
  .frise-cap::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    height: 44px;
    width: max(100%, 44px);
    transform: translate(-50%, -50%);
  }
  .frise-cap::after { width: 44px; }
}

.frise-valeur {
  display: block;
  font-size: var(--fs-xs);
  line-height: 16px;
  color: var(--ca-charbon);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* A cap INSIDE the band (the procédure lane): the value stops before it. --libre is the free
   stretch in percent of the band (core/charts.py), 18 px is the value's own left padding plus
   the half cap and its outline (`_RESERVE_CAP`, the same number). */
.frise-valeur[style*="--libre"] { max-width: calc(var(--libre) - 18px); }

/* Un événement sans durée : un carré sur la voie, son sens dans sa couleur (§6.7). */
.frise-cap {
  position: absolute;
  top: 50%;
  width: 9px;
  height: 9px;
  margin: -5px 0 0 -4px;
  background: var(--ca-charbon);
  outline: 2px solid var(--ca-surface);
  cursor: default;
  z-index: 1;
}

/* Les caps de la voie état posent sur les bords de sa bande : la valeur s'écarte. The procédure
   lane too: every band starts on the cap of its jugement. */
.frise-voie[data-voie="5"] .frise-valeur,
.frise-voie[data-voie="6"] .frise-valeur { padding-left: 10px; }

.frise-cap--gain { background: var(--ca-vert-vif); }
.frise-cap--perte { background: var(--ca-rouge-vif); }

.frise-cap:hover,
.frise-cap:focus-visible { outline-color: var(--ca-charbon); }

/* La carte au survol (§6.13 étendu pour la frise) : au survol et au focus clavier, au-dessus
   de la marque, dans la face de lecture ; la valeur d'abord, les dates, la durée. Un filet,
   pas d'ombre. */
.frise-carte {
  display: none;
  position: absolute;
  left: 0;
  bottom: calc(100% + 6px);
  z-index: 5;
  min-width: 14rem;
  max-width: 22rem;
  padding: var(--sp-2) var(--sp-3);
  background: var(--ca-surface);
  border: 1px solid var(--ca-charbon);
  border-left: 3px solid var(--voie, var(--ca-charbon));
  font-family: var(--font-sans);
  font-size: var(--fs-s);
  line-height: 1.4;
  color: var(--ca-charbon);
  white-space: normal;
}

.frise-carte strong { display: block; font-family: var(--font-mono); font-weight: 500; }
.frise-carte span { display: block; }

/* Toward the middle of the frise: a card opening to the right of a mark at 90 % ran off the
   card of the section at 390. */
.frise-bande[data-cote="d"] .frise-carte,
.frise-cap[data-cote="d"] .frise-carte { left: auto; right: 0; }

.frise-bande:hover .frise-carte,
.frise-bande:focus-visible .frise-carte,
.frise-bande:focus-within .frise-carte,
.frise-cap:hover .frise-carte,
.frise-cap:focus-visible .frise-carte { display: block; }

/* ── Comportement survol (static/graph/js/survol.js) ───────────────────────────────────────
   The hover card of a drawn mark: a chart's bar or point, a département or a métropole of a
   map (spec-experience §6.13 as extended on 2026-10-02). ONE card for the page, filled from
   the mark's `data-survol` / `data-survol-lignes`; the look is the frise's own card
   (.frise-carte above): the reading face, a filet, no shadow, the name first in mono. Fixed
   to the window, since the script places it from the pointer. */
.survol-carte {
  position: fixed;
  z-index: 60;
  max-width: 20rem;
  padding: var(--sp-2) var(--sp-3);
  background: var(--ca-surface);
  border: 1px solid var(--ca-charbon);
  border-left: 3px solid var(--ca-charbon);
  font-family: var(--font-sans);
  font-size: var(--fs-s);
  line-height: 1.4;
  color: var(--ca-charbon);
  pointer-events: none;
}

.survol-carte strong { display: block; font-family: var(--font-mono); font-weight: 500; }
.survol-carte span { display: block; }

/* A mark that carries a card and is not a link shows that it answers. */
[data-survol]:focus-visible { outline: 2px solid var(--ca-charbon); outline-offset: 1px; }

/* Compact : le nom de la voie passe au-dessus de sa piste, la grille et l'axe prennent toute
   la largeur. */
@media (max-width: 767.98px) {
  .frise-voie { grid-template-columns: 1fr; gap: 0; min-height: 3rem; }
  .frise-grille, .frise-axe { left: 0; }
  .frise-nom { border-left-width: 3px; margin-bottom: 2px; }
  .frise-carte { max-width: 16rem; }
}

/* ── Composant chaine (components/chaine.html ; spec-experience §6.9, cinquième forme ;
   spec-design §8.1 décision 1 : les voies des changements de contrôle, dessinées en d3). chaine.js pose la géométrie, cette feuille pose
   toutes les encres : aucune couleur n'est écrite dans le script.

   LE JAUNE veut dire « ici » (§6.2) : la voie de l'entreprise de la page, le trait du jour.
   Une voie cessée passe au gris sur le fond de bloc. Les événements portent la seule encre
   charbon du dessin : les durées de vie sont le contexte (contour gris fort), les événements
   le contenu.

   LE TEXTE est au plancher des jetons (--fs-xs) : le SVG est dessiné à sa taille réelle (une
   unité = un pixel), il ne s'étire jamais ; sous 900 px c'est l'enveloppe qui défile de côté. */
.chaine { margin: 0 0 var(--sp-4); }

.chaine-defilement {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

/* max-width: none — la règle globale des images ramènerait le SVG à la largeur de la colonne
   et le réduirait à l'échelle : sur compact, dix voies sur 350 px. Ici c'est l'enveloppe qui défile. */
.chaine-dessin svg { display: block; max-width: none; }

.chaine-dessin text {
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  fill: var(--ca-charbon);
  user-select: none;
  -webkit-user-select: none;
}

.chaine-grille { stroke: var(--ca-filet); stroke-width: 1; }
.chaine-axe line { stroke: var(--ca-filet); }
.chaine-dessin .chaine-axe text { fill: var(--ca-gris-fort); }

/* La gaine : le fond de la carte autour de chaque voie, pour qu'un trait passe visiblement
   SOUS les voies qu'il ne concerne pas. */
.chaine-voie-gaine { fill: none; stroke: var(--ca-surface); pointer-events: none; }
.chaine-voie-corps { fill: var(--ca-surface); stroke: var(--ca-gris-fort); stroke-width: 1.25; cursor: pointer; }
.chaine-voie--cessee .chaine-voie-corps { fill: var(--ca-surface-2); stroke: var(--ca-gris); }
.chaine-voie--centre .chaine-voie-corps { fill: var(--ca-jaune); stroke: var(--ca-charbon); cursor: default; }
.chaine-voie--centre.chaine-voie--cessee .chaine-voie-corps { fill: var(--ca-surface-2); stroke: var(--ca-gris); }

.chaine-voie-cap { fill: none; stroke: var(--ca-gris); stroke-width: 2.5; pointer-events: none; }
.chaine-voie--centre:not(.chaine-voie--cessee) .chaine-voie-cap { stroke: var(--ca-charbon); }
.chaine-dessin .chaine-voie-coupe { fill: var(--ca-gris-fort); pointer-events: none; }

/* Le nom d'une voie et le libellé d'un événement portent un liseré du fond : ils restent
   lisibles par-dessus un trait ou le bord d'une voie. */
.chaine-voie-nom,
.chaine-libelle {
  font-weight: 600;
  paint-order: stroke;
  stroke: var(--ca-surface);
  stroke-width: 3px;
  stroke-linejoin: round;
}
.chaine-voie-nom { cursor: pointer; }
.chaine-voie--centre .chaine-voie-nom { font-weight: 700; cursor: default; }

.chaine-lien-cible { stroke: transparent; stroke-width: 14; cursor: pointer; }
.chaine-lien-trait { stroke: rgb(var(--ca-noir-rgb) / 0.32); stroke-width: 1.25; pointer-events: none; }
.chaine-lien.est-actif .chaine-lien-trait { stroke: var(--ca-charbon); stroke-width: 1.75; }

.chaine-marque-evenement { cursor: pointer; }
.chaine-point-cible { fill: transparent; }
.chaine-point { fill: var(--ca-charbon); stroke: var(--ca-surface); stroke-width: 2; }
.chaine-fleche { fill: var(--ca-charbon); stroke: var(--ca-surface); stroke-width: 1.5; stroke-linejoin: round; }
/* L'encre dit la source (demande de l'utilisateur, 2026-10-01) : un signal lu dans un acte est
   rouge, ce que le BODACC a publié reste charbon. C'est la seule exception du site au sens du
   rouge (§6.7 : négatif, cession) : ici il ne dit pas une perte, il dit « lu dans un texte, pas
   déclaré ». La source n'est jamais dite par la couleur seule : le survol nomme l'événement,
   la ligne de la liste sous le dessin porte « INPI, actes · signal ». */
.chaine-marque-evenement--acte .chaine-point,
.chaine-marque-evenement--acte .chaine-fleche { fill: var(--ca-rouge); }
.chaine-lien--acte .chaine-lien-trait { stroke: rgb(var(--ca-rouge-rgb) / 0.45); }
.chaine-lien--acte.est-actif .chaine-lien-trait { stroke: var(--ca-rouge); }
.chaine-libelle { opacity: 0; pointer-events: none; }
.chaine-marque-evenement.est-actif .chaine-libelle { opacity: 1; }

/* « +N » : les changements plus anciens, repliés sous la voie de l'entreprise. */
.chaine-plus { cursor: pointer; }
.chaine-plus rect { fill: var(--ca-surface); stroke: var(--ca-lien); stroke-width: 1.5; rx: 3px; }
.chaine-dessin .chaine-plus text { fill: var(--ca-lien); font-weight: 700; text-anchor: middle; pointer-events: none; }

/* Le jour : le trait jaune, et la marque du jour de tokens.css redessinée en SVG (jaune plein
   sous du charbon), la même que celle de la chronologie et de la frise. */
.chaine-aujourdhui { pointer-events: none; }
.chaine-aujourdhui-trait,
.chaine-aujourdhui-fond { fill: var(--ca-jaune); }
.chaine-aujourdhui-libelle { text-anchor: middle; }

.chaine-legende {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2) var(--sp-4);
  margin: var(--sp-2) 0 0;
  padding: 0;
  list-style: none;
  font-size: var(--fs-xs);
  color: var(--ca-gris-fort);
}

.chaine-legende li {
  display: flex;
  align-items: center;
  gap: var(--sp-1);
}

.chaine-marque {
  display: inline-block;
  width: 2rem;
  height: 0.75rem;
  border: 1px solid var(--ca-gris-fort);
  border-radius: 4px;
  background: var(--ca-surface);
}
.chaine-marque--centre { background: var(--ca-jaune); border-color: var(--ca-charbon); }
.chaine-marque--cessee { background: var(--ca-surface-2); border-color: var(--ca-gris); }

.chaine-marque-point {
  display: inline-block;
  width: 0.6rem;
  height: 0.6rem;
  border-radius: 50%;
  background: var(--ca-charbon);
}
.chaine-marque-point--acte { background: var(--ca-rouge); }

.chaine-marque-plus {
  padding: 0 var(--sp-1);
  border: 1px solid var(--ca-lien);
  border-radius: 3px;
  color: var(--ca-lien);
  font-weight: 700;
}

/* ── Composant formulaire (components/formulaire.html ; §6.11 ; B16, decision 10) ───────
   B16 (2026-09-29), mesuré avant : le texte d'erreur était charbon (rgb 10 10 10) — `.colonne-
   lecture p` (0,1,1) battait `.champ-erreur` (0,1,0) — et seule la bordure de 1 px du champ
   était rouge ; les champs mesuraient 38 à 42 px, le bouton 35, « Mot de passe oublié › » 25 ;
   le <select> de contact faisait 404 px de large à 390 (30 px hors écran) ; le groupe de cases
   du profil s'éparpillait sur six retraits (la règle `.champ input { width: 100% }` s'appliquait
   aussi aux cases). Ici : la règle de 2 px rouge à gauche du champ en erreur, le texte rouge,
   le plancher de 44 px sous 1024, le <select> natif dans le cadre du champ, la liste de cases,
   le lien secondaire nu, l'« Afficher » du mot de passe.
   Le libellé au-dessus du champ en mono, pas d'anneau sur le champ lui-même — l'enveloppe le
   signale par :focus-within (même technique que .ca-header-search-field) ; un seul bouton
   plein par formulaire (.bouton-primaire, §6.3 ; le jaune sous du charbon est admis sur toute
   surface, B1) ; une case garde son libellé à droite, en sans. */
.formulaire { max-width: 26rem; }

.champ { margin: 0 0 var(--sp-4); }

.champ label {
  display: block;
  font-family: var(--font-mono);
  font-size: var(--fs-s);
  color: var(--ca-charbon);
  margin: 0 0 var(--sp-1);
}

.champ input:not([type="checkbox"], [type="radio"]) {
  width: 100%;
  font: inherit;
  font-size: var(--fs-s);
  padding: var(--sp-2) var(--sp-3);
  border: 1px solid var(--ca-filet);
  background: var(--ca-surface);
  color: var(--ca-charbon);
}

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

/* B17 (decision 13): the line above removes the global ring for every input of a form, and the
   frame rule below draws a border and a shadow for the TEXT fields only. The checkbox and the
   two radios got nothing at all: « Rester connecté » and the usage radios had no visible focus
   (measured on /compte/connexion/ and the pattern page; the recette did not measure focus). They
   take the site's ring back (§2.4: 2 px --ca-lien). */
.champ input[type="checkbox"]:focus-visible,
.champ input[type="radio"]:focus-visible {
  outline: 2px solid var(--ca-lien);
  outline-offset: 2px;
}

.champ:focus-within input:not([type="checkbox"], [type="radio"]) {
  border-color: var(--ca-lien);
  box-shadow: 0 0 0 1px var(--ca-lien);
}

/* D10 addition: the "textarea" champ type (blog/formulaire.py, contact's own "Votre
   message" — no account form needed one before). Same box as `.champ input` above, composed
   rather than redeclared save for the one property a single-line input never needs. */
.champ textarea {
  width: 100%;
  font: inherit;
  font-size: var(--fs-s);
  padding: var(--sp-2) var(--sp-3);
  border: 1px solid var(--ca-filet);
  background: var(--ca-surface);
  color: var(--ca-charbon);
  resize: vertical;
}

.champ textarea:focus-visible { outline: none; }

.champ:focus-within textarea {
  border-color: var(--ca-lien);
  box-shadow: 0 0 0 1px var(--ca-lien);
}

/* A field in error (Q27): a 2 px `--ca-rouge` rule at the left of the label, the field and its
   message: the trait of the data line with a sign (B2), the site's one way of saying « this is
   wrong » — a line, not a box, and thick enough to see on a phone in daylight. The field's own
   border keeps its ordinary colour: the 1 px red frame it replaces was easy to miss. */
.champ--erreur {
  border-left: 2px solid var(--ca-rouge);
  padding-left: var(--sp-3);
}

.champ-aide {
  display: block;
  margin-top: var(--sp-1);
  font-size: var(--fs-s);   /* B17 Q48: a help sentence in sans, 13 px (it was 11) */
  color: var(--ca-gris-fort);
}

/* `.champ .champ-erreur`: one class higher than `.colonne-lecture p`, which otherwise paints the
   message charbon at 15 px (measured: rgb 10 10 10). Red text, one sentence, no icon (§6.11). */
.champ .champ-erreur,
.formulaire .formulaire-erreur {
  margin: var(--sp-1) 0 0;
  font-size: var(--fs-s);   /* B17 Q48: an error sentence in sans, 13 px (it was 11) */
  line-height: 1.4;
  color: var(--ca-rouge);
}

/* The form's own error (a refused login, a spam refusal) carries the same rule, above the fields. */
.formulaire .formulaire-erreur {
  margin: 0 0 var(--sp-4);
  padding-left: var(--sp-3);
  border-left: 2px solid var(--ca-rouge);
}

.champ--case {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
}

.champ--case input { flex: none; width: 18px; height: 18px; margin: 0; }

.champ--case label {
  display: inline;
  font-family: var(--font-sans);
  font-size: var(--fs-s);
  margin: 0;
}

.bouton-primaire {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: var(--fs-s);
  padding: var(--sp-2) var(--sp-6);
  border: 1px solid var(--ca-jaune);
  background: var(--ca-jaune);
  color: var(--ca-noir);
  cursor: pointer;
}

.bouton-primaire:hover { opacity: 0.85; }

/* The secondary action of a form: a plain link after the button (§6.11, Q28), the body's own
   olive underlined link; the chip it was is kept where it is an action of the PAGE. */
.formulaire-secondaire {
  display: inline-flex;
  align-items: center;
  font-size: var(--fs-s);
}

/* Select (Q27/B16 default): native behaviour kept (a phone opens its own picker), the field's
   frame, mono `--fs-s` and a « ▾ » of our own in place of the browser arrow, never wider than
   the column (404 px at 390 before: 30 px past the screen). */
.champ-select {
  position: relative;
  display: block;
  max-width: 100%;
}

.champ-select::after {
  content: "▾";
  position: absolute;
  right: var(--sp-3);
  top: 50%;
  transform: translateY(-50%);
  color: var(--ca-gris-fort);
  pointer-events: none;
}

.champ select {
  appearance: none;
  display: block;
  width: 100%;
  max-width: 100%;
  font-family: var(--font-mono);
  font-size: var(--fs-s);
  padding: var(--sp-2) calc(var(--sp-3) * 2) var(--sp-2) var(--sp-3);
  border: 1px solid var(--ca-filet);
  border-radius: 0;
  background: var(--ca-surface);
  color: var(--ca-charbon);
  text-overflow: ellipsis;
}

.champ select:focus-visible { outline: none; }

.champ:focus-within select {
  border-color: var(--ca-lien);
  box-shadow: 0 0 0 1px var(--ca-lien);
}

/* « Afficher » (Q29): a mono word at the right of the password field, inside its frame. */
.champ-bascule { position: relative; display: block; }

.champ-bascule input { padding-right: 5.5rem; }

.champ-bascule-bouton {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  padding: 0 var(--sp-3);
  border: 0;
  background: none;
  color: var(--ca-lien);
  font-size: var(--fs-xs);
  cursor: pointer;
}

.formulaire-actions {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  margin: var(--sp-6) 0 0;
}

.formulaire-pied {
  margin: var(--sp-6) 0 0;
  font-size: var(--fs-s);
  color: var(--ca-gris-fort);
}

/* D9 additions to « Composant formulaire »: the advantages bullets (signup's own two lines,
   plan-web-structure-d9-compte.md §3), the checkbox GROUP (profile's "usage", distinct from
   the single `.champ--case` above), and the ghost button `verification_sent.html`'s "Renvoyer
   le lien" needs — a real `<button type=submit>` styled as a plain action, never a second
   filled control on the page (§6.3). */
.formulaire-avantages {
  list-style: none;
  margin: 0 0 var(--sp-4);
  padding: 0;
}

.formulaire-avantages li {
  margin: var(--sp-1) 0;
  font-size: var(--fs-s);
}

.formulaire-avantages li::before {
  content: "✓";
  color: var(--ca-jaune);
  margin-right: var(--sp-2);
  font-weight: 500;
}

.champ-groupe-label {
  display: block;
  font-family: var(--font-mono);
  font-size: var(--fs-s);
  color: var(--ca-charbon);
  margin: 0 0 var(--sp-1);
}

.champ-groupe-options {
  list-style: none;
  margin: 0;
  padding: 0;
}

/* A plain list, box left, label right in sans, one column (§6.11). Measured before: boxes and
   labels at six different left offsets (114 to 205 px at 820) because `.champ label` is a block
   and `.champ input` a full-width field: the group was a spreadsheet of floating cells. */
.champ-groupe-options li {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  margin: var(--sp-1) 0;
}

.champ-groupe-options input {
  flex: none;
  width: 18px;
  height: 18px;
  margin: 0;
}

.champ-groupe-options label {
  flex: 1 1 auto;
  margin: 0;
  font-family: var(--font-sans);
  font-size: var(--fs-s);
}

.bouton-fantome {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: var(--fs-s);
  padding: var(--sp-2) var(--sp-6);
  border: 1px solid var(--ca-filet);
  background: transparent;
  color: var(--ca-charbon);
  cursor: pointer;
}

.bouton-fantome:hover { border-color: var(--ca-lien); }

/* The touch floor of a form under 1024 px (spec-design §2.4, decision 10): one field height, 44 px;
   the primary button 44 px tall at its own width; the secondary link, the tiers link, the foot
   link and the checkbox rows at 44. Measured before at 390: inputs 42 px, the button 35, « Mot de
   passe oublié › » 25, « Créer un compte › » 19, the « Rester connecté » box 13. */
@media (max-width: 1023.98px) {
  .champ input:not([type="checkbox"], [type="radio"]),
  .champ select { min-height: 44px; }

  .bouton-primaire,
  .bouton-fantome,
  .bouton-danger,
  .formulaire-secondaire,
  .formulaire-pied a { display: inline-flex; align-items: center; justify-content: center; min-height: 44px; }

  .champ--case,
  .champ-groupe-options li { min-height: 44px; }
}

/* ── Composant message (components/message.html ; §5.5, §8.2 ; D9) ─────────────────────────
   `formulaire`'s sibling for a page with no field: the same kicker/h1/lead head, a lone
   same-page action (a real `<button>` in its own tiny form, never a link that silently GETs
   a state change) and a row of plain links. */
/* The sentence of a message drawn in a card (`sans_tete`): the body size, a lead is a head's. */
.message-phrase {
  margin: 0 0 var(--sp-4);
  font-size: var(--fs-m);
  line-height: 1.5;
  max-width: 68ch;
}

.message-liens {
  margin: var(--sp-4) 0 0;
  font-size: var(--fs-s);
}

.message-liens .sep {
  margin: 0 var(--sp-2);
  color: var(--ca-gris-fort);
}

/* ── Composant confirmation (components/confirmation.html ; §6.11 "confirmed inline, never
   by a browser dialog" ; D9) ───────────────────────────────────────────────────────────────
   <details>/<summary> gives the two-step fold with no JavaScript: the label opens, the
   question and the real button sit inside. Red is this site's one "négatif" ink (§6.7); a
   destructive action carries it on its rule, never a fill of its own. */
.confirmation-corps {
  margin-top: var(--sp-2);
  padding: var(--sp-3);
  border-left: 2px solid var(--ca-rouge);
}

.confirmation-question {
  margin: 0 0 var(--sp-3);
  font-size: var(--fs-s);
  color: var(--ca-charbon);
}

.ca-action--danger {
  border-color: var(--ca-rouge);
  color: var(--ca-rouge);
}

.ca-action--danger:hover {
  background: var(--ca-rouge);
  border-color: var(--ca-rouge);
  color: var(--ca-surface);
}

.bouton-danger {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: var(--fs-s);
  padding: var(--sp-2) var(--sp-6);
  border: 1px solid var(--ca-rouge);
  background: var(--ca-rouge);
  color: var(--ca-surface);
  cursor: pointer;
}

.bouton-danger:hover { opacity: 0.85; }

/* ── Composant choroplethe (components/choroplethe.html ; D3f, docs/plans/plan-web-structure-
   d3-secteur.md §6) ───────────────────────────────────────────────────────────────────────
   Une carte de France par département, un lien par forme (« each a link », site-structure
   §4/§5) : cinq classes = cinq marches de --ca-charbon par color-mix, jamais une teinte
   nouvelle — la palette de §6.7 est fermée (vert/rouge un signe, jaune §6.2, gris le texte
   secondaire) et une carte de grandeur ne l'ouvre pas plus que la frise de « Historique » ne
   l'a fait (spec-design §8.1 décision 2, « quatre nuances des deux familles du site »). Un
   département SANS ligne (ce métier n'y a jamais été vu) est un état à part, la trame du
   filet, jamais le premier échelon de l'échelle — un fait absent ne doit pas se lire comme
   « la plus petite des valeurs connues » (§7.4). */
/* No margin on the figure: the browser's default 40 px each side left France 225 px wide in a
   350 px card at 390 (decision 12, B11 defaults: the figure takes the card's full width). */
.choroplethe-figure { margin: 0; }

.choroplethe {
  display: block;
  width: 100%;
  height: auto;
}

.choroplethe-departement {
  stroke: var(--ca-surface);
  stroke-width: 0.5;
  vector-effect: non-scaling-stroke;
  transition: opacity 0.1s;
}

.choroplethe-departement--classe-1 { fill: color-mix(in srgb, var(--ca-charbon) 12%, var(--ca-surface)); }
.choroplethe-departement--classe-2 { fill: color-mix(in srgb, var(--ca-charbon) 30%, var(--ca-surface)); }
.choroplethe-departement--classe-3 { fill: color-mix(in srgb, var(--ca-charbon) 50%, var(--ca-surface)); }
.choroplethe-departement--classe-4 { fill: color-mix(in srgb, var(--ca-charbon) 70%, var(--ca-surface)); }
.choroplethe-departement--classe-5 { fill: color-mix(in srgb, var(--ca-charbon) 90%, var(--ca-surface)); }

/* La trame, pas une marche : un hachurage léger dit « rien de publié », jamais « zéro ». */
.choroplethe-departement--absent {
  fill: var(--ca-surface-2);
}

a:hover .choroplethe-departement,
a:focus-visible .choroplethe-departement {
  opacity: 0.72;
}

.choroplethe-legende {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-3);
  margin-top: var(--sp-3);
  font-size: var(--fs-xs);
  font-family: var(--font-mono);
  color: var(--ca-gris-fort);
}

.choroplethe-legende-item {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
}

.choroplethe-legende-marque {
  display: inline-block;
  width: 0.75rem;
  height: 0.75rem;
  border: 1px solid var(--ca-filet);
}

.choroplethe-legende-marque--classe-1 { background: color-mix(in srgb, var(--ca-charbon) 12%, var(--ca-surface)); }
.choroplethe-legende-marque--classe-2 { background: color-mix(in srgb, var(--ca-charbon) 30%, var(--ca-surface)); }
.choroplethe-legende-marque--classe-3 { background: color-mix(in srgb, var(--ca-charbon) 50%, var(--ca-surface)); }
.choroplethe-legende-marque--classe-4 { background: color-mix(in srgb, var(--ca-charbon) 70%, var(--ca-surface)); }
.choroplethe-legende-marque--classe-5 { background: color-mix(in srgb, var(--ca-charbon) 90%, var(--ca-surface)); }
.choroplethe-legende-marque--absent { background: var(--ca-surface-2); }

/* ── Composant choroplethe, la carte à mesures (la forme `build_mesures` du même gabarit ;
   docs/plans/plan-secteur-planches.md §5 W3 : la section « Où » d'une planche secteur). Tout
   ce qui suit est sous `.choroplethe-mesures`, la racine de cette forme : la carte à une
   mesure de « La liste » garde les règles ci-dessus, inchangées.

   UN ÉTAT, UNE ENCRE, TROIS PORTEURS. `.choroplethe-etat--<état>` pose la variable
   `--choroplethe-encre` ; la forme d'un département, le disque d'une métropole et le carré de
   la légende la lisent. choroplethe.js ne change que cette classe sur la marque : la couleur
   d'une classe est écrite une fois, ici, et la légende ne peut pas diverger de la carte.
   - `classe-1…5` : l'échelle séquentielle, cinq marches de la teinte de série, l'olive
     (--ca-lien, §6.9 : la carte porte la couleur des graphiques qu'elle côtoie ; le charbon
     de la première version pesait sur la planche, et la maquette retenue était olive).
   - `ecart-1…5` : l'échelle divergente d'une croissance. §6.7 : le vert est le gain, le rouge
     la perte, rien d'autre ; la classe 3, à cheval sur zéro, est donc un gris (la première
     marche du charbon), jamais un vert pâle. Deux marches par signe, la pleine et sa moitié.
   - `absent` : « non publié » pour CETTE mesure. Le blanc de la surface cerné d'un tireté,
     jamais une marche : sur l'échelle divergente le gris clair est déjà « stable », et un
     département sans valeur ne doit pas se lire comme stable (§7.4). */
.choroplethe-mesures { container-type: inline-size; }

.choroplethe-etat--classe-1 { --choroplethe-encre: color-mix(in srgb, var(--ca-lien) 14%, var(--ca-surface)); }
.choroplethe-etat--classe-2 { --choroplethe-encre: color-mix(in srgb, var(--ca-lien) 34%, var(--ca-surface)); }
.choroplethe-etat--classe-3 { --choroplethe-encre: color-mix(in srgb, var(--ca-lien) 56%, var(--ca-surface)); }
.choroplethe-etat--classe-4 { --choroplethe-encre: color-mix(in srgb, var(--ca-lien) 78%, var(--ca-surface)); }
.choroplethe-etat--classe-5 { --choroplethe-encre: color-mix(in srgb, var(--ca-lien) 100%, var(--ca-surface)); }
.choroplethe-etat--ecart-1 { --choroplethe-encre: var(--ca-rouge-vif); }
.choroplethe-etat--ecart-2 { --choroplethe-encre: color-mix(in srgb, var(--ca-rouge-vif) 38%, var(--ca-surface)); }
.choroplethe-etat--ecart-3 { --choroplethe-encre: color-mix(in srgb, var(--ca-charbon) 12%, var(--ca-surface)); }
.choroplethe-etat--ecart-4 { --choroplethe-encre: color-mix(in srgb, var(--ca-vert-vif) 38%, var(--ca-surface)); }
.choroplethe-etat--ecart-5 { --choroplethe-encre: var(--ca-vert-vif); }
.choroplethe-etat--absent { --choroplethe-encre: var(--ca-surface); }

/* Les commandes : la mesure (le contrôle de vue de la section, repris tel quel : `.vues` /
   `.vue`, 44 px sur compact), la région, la couche classée. Elles passent à la ligne entre
   elles ; les mesures, elles, ne se replient pas : six boutons côte à côte défilent de côté
   sur un téléphone (mesuré à 390 sur le spécimen : trois mesures font déjà 325 px pour 314),
   ce qui garde UN contrôle dans le DOM (§6.14 : rien n'existe sur un palier qui n'existe pas
   sur l'autre). */
.choroplethe-commandes {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2) var(--sp-4);
  margin-bottom: var(--densite-bloc);
}

.choroplethe-bascule {
  flex: 0 1 auto;
  min-width: 0;
  max-width: 100%;
  overflow-x: auto;
}

.choroplethe-bascule .vue,
.choroplethe-couches .vue {
  flex: 0 0 auto;
  white-space: nowrap;
}

.choroplethe-couches { margin-left: auto; }

.choroplethe-region select {
  max-width: 100%;
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  padding: var(--sp-1) var(--sp-2);
  border: 1px solid var(--ca-filet);
  border-radius: 0;
  background: var(--ca-surface);
  color: var(--ca-charbon);
}

/* La carte et son classement : côte à côte dès que la CARTE DE LA SECTION est assez large,
   pas l'écran — une section peut n'occuper qu'une demi-largeur de la grille des panneaux, et
   une requête sur l'écran y aurait serré la carte dans 250 px. Sous 46rem, le classement
   passe sous la carte. */
.choroplethe-plan {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--densite-groupe);
  align-items: start;
}

@container (min-width: 46rem) {
  /* The list takes the wider share: at 11fr the map was 700 px tall on a full row and the
     ten rows beside it left half the card empty (first walk, 2026-10-02). At 9fr the map is
     about 560 px and the fifteen rows the plates fold at fill its height. */
  .choroplethe-plan { grid-template-columns: minmax(0, 9fr) minmax(0, 11fr); }
}

.choroplethe-mesures .choroplethe-departement { fill: var(--choroplethe-encre); }

.choroplethe-mesures .choroplethe-etat--absent .choroplethe-departement,
.choroplethe-mesures .choroplethe-etat--absent .choroplethe-metropole {
  stroke: var(--ca-gris-fort);
  stroke-dasharray: 2 2;
}

/* Une région choisie : le reste de la France reste dessiné, estompé, pour que la région se
   lise dans son voisinage ; une métropole hors de la région sort du dessin. */
.choroplethe-marque.est-hors-region .choroplethe-departement { opacity: 0.18; }
.choroplethe-couche-metropoles .est-hors-region { display: none; }

/* Le contour du lieu pointé, sur la carte ou dans le classement. Le jaune veut dire « ici »
   (§6.2), comme le point choisi d'une carte (§6.15) ; il est posé sur un trait charbon plus
   large, parce que le jaune seul ne se lit pas sur une forme claire (1,1:1 sur blanc). */
.choroplethe-ici {
  fill: none;
  pointer-events: none;
  stroke: var(--ca-jaune);
  stroke-width: 2;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}

.choroplethe-ici--fond {
  stroke: var(--ca-charbon);
  stroke-width: 5;
}

/* Une métropole : un disque d'une seule taille (§6.15 : jamais une bulle comptée), dans la
   classe de la mesure, cerné d'un anneau de surface et d'un filet charbon pour se lire sur un
   département de la dernière marche comme sur un département absent. */
.choroplethe-metropole-anneau {
  fill: var(--ca-surface);
  stroke: var(--ca-charbon);
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
}

.choroplethe-metropole {
  fill: var(--choroplethe-encre);
  vector-effect: non-scaling-stroke;
}

.choroplethe-marque.est-survole .choroplethe-metropole-anneau,
a.choroplethe-marque:hover .choroplethe-metropole-anneau,
a.choroplethe-marque:focus-visible .choroplethe-metropole-anneau {
  fill: var(--ca-jaune);
}

/* La légende : une par mesure, celle de la mesure montrée seule visible. `display: flex`
   l'emporterait sur l'attribut `hidden` hors d'une section. */
.choroplethe-legendes { margin-top: var(--sp-3); }
.choroplethe-mesures .choroplethe-legende { margin-top: 0; }

.choroplethe-mesures .choroplethe-legende[hidden],
.choroplethe-reference[hidden],
.choroplethe-rangs[hidden],
.choroplethe-rang[hidden] {
  display: none;
}

.choroplethe-legende-titre,
.choroplethe-legende-precision {
  flex-basis: 100%;
}

.choroplethe-legende-titre { color: var(--ca-charbon); }

.choroplethe-mesures .choroplethe-legende-marque { background: var(--choroplethe-encre); }
.choroplethe-legende-marque.choroplethe-etat--absent { border: 1px dashed var(--ca-gris-fort); }

.choroplethe-mesures .choroplethe-legende-marque--metropole {
  border: 1px solid var(--ca-charbon);
  border-radius: 50%;
  background: var(--ca-surface);
}

.choroplethe-note {
  margin: var(--sp-2) 0 0;
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  color: var(--ca-gris-fort);
}

/* Le classement : la ligne de référence (la mesure et le chiffre de la France, une bande
   grise, §6.1) puis une ligne par lieu. Le repli est celui de la section (fold.js). */
.choroplethe-classement { min-width: 0; }

.choroplethe-reference {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-1) var(--sp-3);
  margin: 0;
  padding: var(--sp-2) var(--sp-3);
  background: var(--ca-surface-2);
  font-family: var(--font-mono);
  font-size: var(--fs-s);
}

.choroplethe-reference-mesure {
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ca-gris-fort);
}

.choroplethe-reference strong { font-weight: 600; }
.choroplethe-reference .discret { font-size: var(--fs-xs); }

/* Sans script les deux couches sont listées l'une sous l'autre, chacune sous son nom ; avec
   lui la bascule « Départements · Métropoles » dit laquelle est montrée. */
.choroplethe-couche-titre {
  margin: var(--sp-4) 0 0;
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ca-gris-fort);
}

.choroplethe-mesures.est-anime .choroplethe-couche-titre { display: none; }

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

.choroplethe-rang {
  display: grid;
  grid-template-columns: 1.75rem minmax(0, 1fr) auto;
  gap: 0 var(--sp-2);
  align-items: baseline;
  padding: var(--densite-cellule) var(--sp-1);
  border-bottom: 1px solid var(--ca-filet);
  font-size: var(--fs-s);
}

.choroplethe-rang:hover,
.choroplethe-rang.est-survole {
  background: var(--ca-surface-2);
}

.choroplethe-rang-no {
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  text-align: right;
}

.choroplethe-rang-nom { min-width: 0; }
/* The touch tier: a ranked place is a 44 px target (17 px measured at 390 on the Secteur page's
   map of France, 2026-10-07; the métier plate had the same rows). The row grows to hold it. */
@media (max-width: 767.98px), (max-width: 1023.98px) and (pointer: coarse) {
  .choroplethe-rang-nom > a { display: inline-flex; align-items: center; min-height: 44px; }
}
.choroplethe-rang-nom .discret { font-family: var(--font-mono); font-size: var(--fs-xs); }

.choroplethe-rang-cote {
  font-family: var(--font-mono);
  text-align: right;
  white-space: nowrap;
}

.choroplethe-rang-n { font-size: var(--fs-xs); }

/* Dans une carte étroite (un téléphone, une demi-largeur), l'effectif passe sous la valeur :
   sur une ligne, « 320 k€ 151 prix publiés » ne laissait que 100 px au nom à 390 et
   « Hauts-de-Seine › 92 » se coupait en deux. */
@container (max-width: 30rem) {
  .choroplethe-rang-n { display: block; }
}

/* Le plancher tactile (spec-design §2.4), aux deux paliers tenus en main comme pour `.vue` :
   le select et la ligne du classement, dont le nom est un lien. */
@media (max-width: 1023.98px) {
  .choroplethe-region select { min-height: 44px; }
  .choroplethe-rang { min-height: 44px; align-items: center; }
}

/* ── Composant comparaison (components/comparaison.html ; plan-secteur-planches W5) ───────────
   Des frères comparés sur une mesure à la fois, en barres horizontales, chacun un lien vers sa
   page. La bascule est `.vues` / `.vue` de la carte à mesures, reprise telle quelle : un seul
   dialecte pour « changer de mesure ». Une barre est un <rect> d'un viewBox de 100 de large
   étiré à sa piste (aucun style en ligne) ; l'encre est celle de la
   série (olive, 55 %), le vert et le rouge n'apparaissent que pour un gain ou une perte sur une
   mesure signée (§6.7). Une ligne sans valeur n'a pas de barre : « non publié » en gris, jamais
   une barre vide qui se lirait « zéro » (§7.4). */
.comparaison-bascule {
  max-width: 100%;
  overflow-x: auto;
  margin-bottom: var(--densite-bloc);
}

.comparaison-bascule .vue {
  flex: 0 0 auto;
  white-space: nowrap;
}

.comparaison-bascule[hidden],
.comparaison-mesure[hidden],
.comparaison-ligne[hidden] { display: none; }

.comparaison-titre {
  margin: 0 0 var(--sp-2);
  font-size: var(--fs-xs);
  color: var(--ca-gris-fort);
}

/* The columns belong to the list and every row is a subgrid of it, so that the bars of all rows
   start on one line and share one length: with a grid per row, a value wider than 7rem took
   its row's track and shifted that bar alone (user, 2026-10-10). */
.comparaison-lignes {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: 4.5rem minmax(10rem, 20rem) minmax(4rem, 1fr) minmax(7rem, auto);
  column-gap: var(--sp-3);
}

.comparaison-ligne {
  display: grid;
  grid-column: 1 / -1;
  grid-template-columns: subgrid;
  row-gap: 0;
  align-items: center;
  padding: var(--densite-cellule) var(--sp-1);
  border-bottom: 1px solid var(--ca-filet);
  font-size: var(--fs-s);
}

.comparaison-ligne:hover { background: var(--ca-surface-2); }

.comparaison-code { font-size: var(--fs-xs); color: var(--ca-gris-fort); }
.comparaison-nom { min-width: 0; }

.comparaison-piste {
  position: relative;
  display: block;
  height: 1.125rem;
}

.comparaison-svg { display: block; width: 100%; height: 100%; }

.comparaison-barre { fill: rgb(var(--ca-lien-rgb) / 0.55); }
.comparaison-barre--gain { fill: var(--ca-vert); }
.comparaison-barre--perte { fill: var(--ca-rouge); }
.comparaison-zero { fill: var(--ca-gris-fort); }

.comparaison-valeur {
  font-family: var(--font-mono);
  text-align: right;
  white-space: nowrap;
}

.comparaison-valeur .unite { display: block; font-size: var(--fs-xs); }

/* Sur un téléphone le nom prend la première ligne, la barre et la valeur la seconde : à 390 px
   quatre colonnes ne laissent pas 100 px au libellé. Le plancher tactile (§2.4) est celui de la
   ligne entière, dont le nom est le lien. */
@media (max-width: 767.98px) {
  .comparaison-lignes { grid-template-columns: minmax(0, 1fr) minmax(7rem, auto); }
  .comparaison-ligne {
    row-gap: var(--sp-1);
    min-height: 44px;
  }
  .comparaison-code { display: none; }
  .comparaison-nom { grid-column: 1 / -1; }
  .comparaison-piste { grid-column: 1; }
  .comparaison-valeur .unite { display: inline; margin-left: var(--sp-2); }
}

/* ── Composant section, les colonnes d'une section (spec-experience §10.37 B, 2026-10-09) ─────
   « Inside a section the blocks sit in columns on a wide screen »: the Secteur page measured
   7 666 px at 1440 with every block stacked full width, a ten-point line 1 300 px wide. A
   section body lays its blocks in `.colonnes`, one column per block from 1024 px (the
   cartouche's own seuil), stacked under it. The modifier says the shares, written once here:
   `--trois` the Entreprises row (a table, then two charts), `--deux` halves, `--sept-cinq` a
   wide block and its companion, `--quatre` four small charts, `--multi` the Multi-établissements
   row (a bar chart, the four-column table, the networks). A block's sub-title opening a column
   loses its top margin: the row's tops align. */
.colonnes {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--densite-bloc) var(--sp-6);
  align-items: start;
}
.colonnes > * { min-width: 0; }
/* Two rows of columns in one section (Finances: the four charts, then the ratios): the second
   row's titles lost their margin above (first child), so the rows keep a group's gap between. */
.colonnes + .colonnes { margin-top: var(--densite-groupe); }
.colonnes > * > .groupe-titre:first-child,
.colonnes > * > .chart:first-child { margin-top: 0; }
@media (min-width: 768px) and (max-width: 1023.98px) {
  .colonnes--quatre { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (min-width: 1024px) {
  .colonnes--deux { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .colonnes--trois { grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr) minmax(0, 1fr); }
  .colonnes--quatre { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .colonnes--sept-cinq { grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); }
  /* Three equal columns (§10.40): « Rentabilité »'s three charts, « Transmissions »' three parts. */
  .colonnes--trois-egales { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
/* A sub-title's second part, what the block reads (« 22 · un titre de colonne trie »): the
   flex row of `.groupe-titre` puts it at the right; plain case, grey, no capitals. */
.groupe-titre .groupe-titre-note {
  text-transform: none;
  letter-spacing: 0;
  font-weight: 400;
  color: var(--ca-gris-fort);
}
/* A line that says a figure was read one level up (« … ceux du niveau au-dessus, Rhône »): kept
   visible (§10.37 G, the effectif rule), marked by the yellow rule of « ici » (§6.2). */
.bloc-note--repli {
  border-left: 2px solid var(--ca-jaune);
  padding-left: var(--sp-2);
  font-size: var(--fs-s);
}

/* ── Composant chart, la variante serrée (`chart.serre`, spec-experience §10.37 D) ─────────
   « Horizontal bars as tall as their label, the label column as wide as its words »: in a third
   of a row the 18 rem label column and the 22 px rows left a bar of 60 px. Charts small enough
   to sit four in a row take a smaller title and a two-line note. */
/* max-content is the LONGEST label of the chart (the rows are subgrids of .chart-rangees), so
   the bars of a serré chart start on one line too. */
.chart--serre .chart-rangees { grid-template-columns: max-content minmax(3rem, 1fr) auto; gap: 3px var(--sp-2); }
.chart--serre .chart-rangee-piste { height: 0.95rem; }
@media (max-width: 767.98px) {
  .chart--serre .chart-rangees { grid-template-columns: max-content minmax(3rem, 1fr) auto; }
  .chart--serre .chart-rangee-libelle { grid-column: auto; }
}
.colonnes--quatre .chart .chart-titre { font-size: var(--fs-s); }
/* The year labels of a line chart are thinned by the SCREEN's width (`data-rang`, « Composant
   chart »): in a third of a row the plane is the 768 px tier's, in a quarter the phone's, and
   all eleven years printed on one another (« 2016201720182019… », first walk of 2026-10-09). */
@media (min-width: 1024px) {
  .colonnes--trois .chart-etiquette[data-rang="3"],
  .colonnes--trois .chart-etiquette[data-rang="2"],
  .colonnes--trois-egales .chart-etiquette[data-rang="3"],
  .colonnes--trois-egales .chart-etiquette[data-rang="2"],
  .colonnes--quatre .chart-etiquette[data-rang="3"],
  .colonnes--quatre .chart-etiquette[data-rang="2"] { display: none; }
}
.colonnes--quatre .chart .chart-note {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* ── Composant cartouche, la page Secteur (spec-experience §10.37 A, F) ─────────────────────
   Eight repères: four a row from 768 px (two on a phone, tokens.css). At France the map of
   « Où » takes the right column, on a white panel (its inks are drawn for a light ground);
   the « Carte ▾ » fold of the company plate's map serves it on a phone. The `renvoi` of a live
   selection is one mono line, its door in yellow (« ici », the kicker's own links). */
@media (min-width: 768px) {
  .planche .cartouche--secteur .reperes { grid-template-columns: repeat(4, minmax(0, 1fr)); column-gap: var(--sp-4); }
}
.cartouche-carte--choroplethe {
  background: var(--ca-surface);
  color: var(--ca-charbon);
  padding: var(--sp-2) var(--sp-3);
}
.cartouche-carte--choroplethe svg.choroplethe { max-height: 15.5rem; width: 100%; }
/* Four measures on one row of the panel: the vue control's own padding cut « CA médian » off. */
.cartouche-carte--choroplethe .vue { padding: var(--sp-1) var(--sp-2); font-size: var(--fs-xs); }
.cartouche-renvoi {
  margin: var(--sp-3) 0;
  font-size: var(--fs-xs);
  color: var(--ca-text-muted-dark);
}
.cartouche-renvoi a { color: var(--ca-jaune); }

/* « En bref » (spec-experience §10.40, 2026-10-12): five sentences in place of the repères. The
   number in the largest of the five sizes (§2.2), white, not yellow: yellow means « ici » and the
   primary action and nothing else (§6.2). The words in the reading size; the comparison under
   them in mono, small and muted, as a repère's precision. A rule between sentences, not a tile:
   a sentence is read, a tile is compared. On a phone the number sits above its words. */
.cartouche-bref-titre {
  margin: var(--sp-4) 0 var(--sp-1);
  font-size: var(--fs-xs);
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ca-text-muted-dark);
}
.cartouche-bref { list-style: none; margin: 0; padding: 0; max-width: 62rem; }
.bref {
  display: grid;
  grid-template-columns: 9.5rem minmax(0, 1fr);
  column-gap: var(--sp-6);
  align-items: baseline;
  padding: var(--sp-3) 0;
  border-top: 1px solid rgb(var(--ca-blanc-rgb) / 0.14);
}
.bref:first-child { border-top: 0; }
.bref-valeur {
  font-family: var(--font-mono);
  font-size: var(--fs-xl);
  font-weight: 500;
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  color: var(--ca-text-on-dark);
}
.bref--absent .bref-valeur { color: var(--ca-text-muted-dark); }
.bref-texte { display: block; font-size: var(--fs-m); color: var(--ca-text-on-dark); }
.bref-texte a { color: var(--ca-jaune); white-space: nowrap; }
.bref-precision { display: block; margin-top: var(--sp-1); font-size: var(--fs-xs); color: var(--ca-text-muted-dark); }
@media (max-width: 767.98px) {
  .bref { grid-template-columns: minmax(0, 1fr); row-gap: var(--sp-1); }
}

/* ── Composant choroplethe, en deux parties (`partie`, §10.37 A) ──────────────────────────────
   One part alone fills its plan (no side-by-side grid). The ranked list drawn apart is the
   départements of the Secteur page's « Où »: in three columns from 1024 px, fifteen rows read as
   three blocks of five, never cut inside a row. */
.choroplethe-mesures--carte .choroplethe-plan,
.choroplethe-mesures--classement .choroplethe-plan { grid-template-columns: minmax(0, 1fr); }
@media (min-width: 1024px) {
  .choroplethe-mesures--classement .choroplethe-rangs { column-count: 3; column-gap: var(--sp-6); }
  .choroplethe-mesures--classement .choroplethe-rang { break-inside: avoid; }
}

/* ── Composant palmares (components/palmares.html ; spec-experience §10.37 G) ─────────────────
   Places on several measures: the value then its bar in every cell, the bar on the places'
   scale in the series tint, the reference's tick in charbon (« trait noir : France »). The
   reference row is a band (`--ca-surface-2`, §6.1) under a charbon rule; the place the page is
   about is surligné (« ici », §6.2). A column title is a plain button (sort, palmares.js).
   Under 1280 px (the atlas header's seuil) the bars go: seven columns of value + bar overflowed
   a 1 000 px card. */
.palmares { font-size: var(--fs-s); }
.palmares th, .palmares td { padding-inline: var(--sp-1); }
/* 23 rows: one line each, 26 px (34 at the table's default line height and cell padding). */
.palmares tbody th, .palmares tbody td { padding-block: 3px; line-height: 1.3; }
.table-donnees.palmares thead th { white-space: normal; vertical-align: bottom; line-height: 1.25; }
.palmares thead th.num { text-align: right; }
.palmares-tri {
  all: unset;
  white-space: normal;
  cursor: pointer;
  font: inherit;
  text-transform: inherit;
  letter-spacing: inherit;
}
.palmares-tri:hover, .palmares-tri:focus-visible { text-decoration: underline; }
.palmares-tri[aria-sort="descending"]::after { content: " ▾"; }
.palmares-tri[aria-sort="ascending"]::after { content: " ▴"; }
.palmares tbody th {
  position: static;
  text-align: left;
  font: 400 var(--fs-s) var(--font-sans);
  text-transform: none;
  letter-spacing: 0;
  color: var(--ca-charbon);
  border-bottom: 1px solid var(--ca-filet);
  white-space: nowrap;
}
/* The bar of a cell is pinned to the cell's right edge, not set after its value: after the value,
   « 1 234 567 » pushed its bar further right than « 812 » did, and a column's bars no longer
   started on one line (user, 2026-10-10). The cell keeps room for it on the right. */
.palmares td { white-space: nowrap; }
.palmares td:has(> .palmares-piste) { position: relative; padding-right: calc(3rem + 2 * var(--sp-1)); }
.palmares-valeur { display: inline-block; min-width: 3.4rem; }
.palmares-piste {
  position: absolute;
  right: var(--sp-1);
  top: 50%;
  width: 3rem;
  height: 0.6rem;
  margin-top: -0.3rem;
  background: var(--ca-surface-2);
}
.palmares-barre { position: absolute; inset: 0 auto 0 0; background: rgb(var(--ca-lien-rgb) / 0.55); }
.palmares-repere { position: absolute; top: -2px; bottom: -2px; width: 2px; margin-left: -1px; background: var(--ca-charbon); }
.palmares-vide { color: var(--ca-gris-fort); font-size: var(--fs-xs); }
.palmares .palmares-reference th, .palmares .palmares-reference td {
  font-weight: 600;
  background: var(--ca-surface-2);
  border-bottom: 1px solid var(--ca-charbon);
}
.palmares-reference .palmares-barre { background: var(--ca-gris-fort); }
.palmares .palmares-ici th, .palmares .palmares-ici td { background: var(--ca-jaune-surlignage); font-weight: 600; }
.palmares-legende { font-size: var(--fs-xs); margin-top: var(--sp-1); }
@media (max-width: 1279.98px) {
  .palmares-piste { display: none; }
  .palmares td:has(> .palmares-piste) { padding-right: var(--sp-1); }
  .palmares-valeur { min-width: 0; }
}
/* On a phone the table scrolls sideways (eight columns do not become cards: the comparison IS
   the row); the place's name stays pinned at the left, and a title breaks between words only
   (« ENTRE PRISE S » at 390 on the first walk). */
@media (max-width: 767.98px) {
  .table-donnees.palmares thead th { min-width: 5.5rem; word-break: keep-all; }
  .palmares thead th:first-child, .palmares tbody th {
    position: sticky;
    left: 0;
    z-index: 2;
    min-width: 0;
    background: var(--ca-surface);
    white-space: normal;
  }
}

/* ── Composant ratios (components/ratios.html ; spec-experience §10.37 C, K) ──────────────────
   One row per ratio, six columns: name over its definition, the 26 px distribution, Q1, the
   médiane in bold, Q3, n in grey. The row is a <details>: a click opens the full histogram
   under it. On a phone: name, médiane and the distribution under them; Q1, Q3, n and the
   definition go (the full chart, one tap away, carries them). Inks: the classes in the series
   tint, the open end classes in the hairline grey (they gather everything beyond), the médiane
   in charbon, the baseline grey, the 0 dashed. */
.ratios { font-size: var(--fs-s); }
.ratios-tete, .ratio > summary {
  display: grid;
  grid-template-columns: minmax(9rem, 1.5fr) minmax(7rem, 1fr) 4.4rem 4.6rem 4.4rem 3.4rem;
  gap: 0 var(--sp-3);
  align-items: center;
}
.ratios-tete {
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ca-gris-fort);
  padding-bottom: var(--sp-1);
  border-bottom: 1px solid var(--ca-charbon);
}
.ratios-tete > :nth-child(n+3), .ratio > summary > :nth-child(n+3) { text-align: right; }
.ratios-groupe {
  margin: var(--sp-2) 0 0;
  padding-bottom: 2px;
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ca-gris-fort);
  border-bottom: 1px solid var(--ca-filet);
}
.ratio > summary {
  list-style: none;
  cursor: pointer;
  padding: var(--sp-1) 0;
  border-bottom: 1px solid var(--ca-filet);
}
.ratio > summary::-webkit-details-marker { display: none; }
.ratio > summary:hover, .ratio[open] > summary { background: var(--ca-surface-2); }
.ratio-nom { display: flex; flex-direction: column; line-height: 1.2; min-width: 0; }
.ratio-definition {
  font-size: var(--fs-xs);
  color: var(--ca-gris-fort);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.ratio-etincelle { display: flex; flex-direction: column; min-width: 0; }
.ratio-etincelle svg { display: block; width: 100%; height: 26px; }
.ratio-barre { fill: rgb(var(--ca-lien-rgb) / 0.55); }
.ratio-barre--ouverte { fill: var(--ca-filet); }
.ratio-base { stroke: var(--ca-gris); stroke-width: 1.5; vector-effect: non-scaling-stroke; }
.ratio-zero { stroke: var(--ca-gris-fort); stroke-width: 1; stroke-dasharray: 2 2; vector-effect: non-scaling-stroke; }
.ratio-mediane { stroke: var(--ca-charbon); stroke-width: 2; vector-effect: non-scaling-stroke; }
.ratio-echelle {
  position: relative;
  display: flex;
  justify-content: space-between;
  margin-top: 1px;
  font-size: var(--fs-xs);
  line-height: 1;
  color: var(--ca-gris-fort);
}
.ratio-echelle-zero { position: absolute; top: 0; transform: translateX(-50%); }
.ratio-chiffre { font-variant-numeric: tabular-nums; white-space: nowrap; }
.ratio-chiffre--mediane { font-weight: 600; }
.ratio-chiffre--n { font-size: var(--fs-xs); color: var(--ca-gris-fort); }
.ratio-plein { padding: var(--sp-2) 0 var(--sp-3); max-width: 40rem; }
.ratio-plein .chart-titre { display: none; }
@media (max-width: 767.98px) {
  .ratios-tete, .ratio > summary { grid-template-columns: minmax(0, 1fr) 7.5rem 4.4rem; }
  .ratios-tete > :is(:nth-child(3), :nth-child(5), :nth-child(6)),
  .ratio > summary > :is(:nth-child(3), :nth-child(5), :nth-child(6)) { display: none; }
  .ratio-definition { display: none; }
  .ratio-echelle-zero { display: none; }
}

/* ── Composant parts (components/parts.html ; spec-experience §10.37 K) ───────────────────────
   The strip of the whole, then a row per part on the same 0–100 € scale, the total under a
   charbon rule. The four inks are the split bars' (« Composant chart », §10.33), on HTML. */
.parts { margin: 0; }
.parts-bande { display: flex; height: 14px; margin: var(--sp-1) 0 var(--sp-2); background: var(--ca-surface-2); }
.parts-lignes { display: grid; gap: 3px; font-size: var(--fs-xs); }
.parts-ligne {
  display: grid;
  grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr) 2.8rem;
  gap: var(--sp-2);
  align-items: center;
}
.parts-nom { display: flex; gap: var(--sp-1); align-items: center; min-width: 0; }
.parts-marque { display: block; height: 100%; }
.parts-pastille { width: 0.6rem; height: 0.6rem; flex: none; }
.parts-piste { display: block; height: 0.7rem; background: var(--ca-surface-2); }
.parts-valeur { text-align: right; white-space: nowrap; }
.parts-total { border-top: 1px solid var(--ca-charbon); padding-top: 2px; font-weight: 600; }
.parts-marque--0 { background: rgb(var(--ca-text-muted-rgb) / 0.45); }
.parts-marque--1 { background: rgb(var(--ca-lien-rgb) / 0.3); }
.parts-marque--2 { background: var(--ca-lien); }
.parts-marque--3 { background: var(--ca-vert-vif); }
.parts .chart-definitions { margin-top: var(--sp-2); }

/* ── Composant explication (components/explication.html ; spec-experience §10.37 E) ───────────
   A « ? » in a ring, inline with the line it explains; open, the text under it at the width of
   a sentence. 44 px of target on the touch tier, by padding and a negative margin. */
.explication { display: inline-block; margin: var(--sp-1) var(--sp-3) 0 0; font-size: var(--fs-s); vertical-align: baseline; }
.explication > summary {
  list-style: none;
  cursor: pointer;
  display: inline-grid;
  place-items: center;
  width: 1.2rem;
  height: 1.2rem;
  border: 1px solid var(--ca-gris-fort);
  border-radius: 50%;
  font: 500 var(--fs-xs)/1 var(--font-mono);
  color: var(--ca-gris-fort);
}
.explication > summary::-webkit-details-marker { display: none; }
.explication[open] { display: block; }
.explication[open] > summary { background: var(--ca-surface-2); }
.explication > p { margin: var(--sp-1) 0 0; max-width: 36rem; color: var(--ca-gris-fort); }
@media (max-width: 767.98px), (max-width: 1023.98px) and (pointer: coarse) {
  .explication > summary { box-sizing: content-box; padding: 0.7rem; margin: -0.7rem; background-clip: content-box; }
}

/* ── La page Secteur, simplifiée (spec-experience §10.40, 2026-10-12) ─────────────────────────
   A paragraph of a section read as a sentence (« À quel rythme », « Comment elles finissent »):
   the reading size, not a note. The ratio cards: three to a row from 1024 px, each the name and
   its médiane on one line, the plain words, the histogram, the foot. « Où » at France: the map
   7 and the métropoles 13 (the map capped at 26 rem); a métropole's row lit by
   its disc (choroplethe.js `est-survole`). */
.bloc-texte { margin: 0 0 var(--sp-3); font-size: var(--fs-m); max-width: 46rem; }
.ratio-cartes { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--sp-4) var(--sp-6); }
@media (min-width: 768px) and (max-width: 1023.98px) {
  .ratio-cartes { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (min-width: 1024px) {
  .ratio-cartes { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
.ratio-carte { min-width: 0; }
.ratio-carte .chart { margin-top: var(--sp-2); }
.ratio-carte-tete { display: flex; justify-content: space-between; align-items: baseline; gap: var(--sp-3); margin: 0; }
.ratio-carte-nom { font-weight: 600; font-size: var(--fs-m); }
.ratio-carte-mediane { font-size: var(--fs-l); font-weight: 500; font-variant-numeric: tabular-nums; }
.ratio-carte-lecture { margin: var(--sp-1) 0 0; font-size: var(--fs-s); color: var(--ca-gris-fort); min-height: 2.6em; }
.ratio-carte-definition { font-size: var(--fs-xs); color: var(--ca-gris); }
.ratio-carte-pied { margin: var(--sp-1) 0 0; font-size: var(--fs-xs); color: var(--ca-gris-fort); }
.tiroir .ratios-groupe { margin-top: var(--densite-groupe); }
.tiroir .ratios-groupe:first-child { margin-top: 0; }
.ou-france { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--densite-bloc) var(--sp-6); align-items: start; margin-top: var(--densite-groupe); }
@media (min-width: 1024px) {
  /* 7 for the map, 13 for the métropoles: at 9/11 the map was 570 × 551 px and the user found it
     far too big (2026-10-12); the table it gives width to wraps fewer names onto two lines. */
  .ou-france { grid-template-columns: minmax(0, 7fr) minmax(0, 13fr); }
}
/* The map is a locator here, not the section's subject: never wider than 26 rem (≈ 416 px), which
   also keeps it from spanning the whole row under 1024 px, where the two columns stack. */
.ou-france .choroplethe-figure .choroplethe { display: block; max-width: 26rem; }
.ou-france > * > .groupe-titre:first-child { margin-top: 0; }
.palmares tr.est-survole > * { background: rgb(var(--ca-lien-rgb) / 0.10); }
/* Beside the map the table has eleven twelfths of a card, not the card: with each bar BESIDE its
   value (3 rem + 3,4 rem a cell) the last two columns ran out of sight. Here the bar goes UNDER
   the value, as wide as the cell (measured 1440 px: 1 040 px of table in 710). */
.ou-france .palmares td:has(> .palmares-piste) { padding-right: var(--sp-1); }
.ou-france .palmares-valeur { display: block; min-width: 0; }
.ou-france .palmares-piste { position: relative; display: block; right: auto; top: auto; width: 100%; height: 4px; margin-top: 3px; }
.ou-france .palmares-repere { top: -3px; bottom: -3px; }
/* « non comparable* » and « trop peu » may take two lines there: they were the widest cells */
.ou-france .table-donnees.palmares td.palmares-vide,
.ou-france .table-donnees.palmares tbody th { white-space: normal; }
/* the independents' box, then the charts: a group's gap between them */
.bloc-lien + .avertissement, .bloc-lien + .colonnes { margin-top: var(--densite-bloc); }

/* ── Multi-établissements (graph/blocks/secteur_plus.html, the drawer « Indépendants et réseaux » ; §10.37 J) ──
   The four-column comparison is a `.table-donnees`; its « Plusieurs » column, the one the
   section is about, is a band (`.colonne-forte`). The networks' second line (the siège's
   commune) is mono and small, under the name. */
.table-donnees .colonne-forte { background: var(--ca-surface-2); font-weight: 600; }
/* The comparison of the four populations on its own row: five columns of figures do not need
   the card's width, and spread over it the eye lost the row between label and value. */
.reseaux-comparaison { max-width: 46rem; margin-top: var(--densite-groupe); }
/* A row's head is a label in the reading face, not the mono capitals of a column head: the
   measures of the comparison (« Croissance du CA médiane ») and the networks' names. It holds
   its line where it can (9 rem) and wraps past it rather than push the figures out. Was
   `.table-donnees--serree`, which also set the whole table in --fs-xs; at full size since
   2026-10-12 (the drawer's polish: each table has half a row or 46 rem now, not a third). */
.table-donnees.table-donnees--libelles tbody th {
  min-width: 9rem;
  position: static;
  font: 400 var(--fs-s) var(--font-sans);
  text-transform: none;
  letter-spacing: 0;
  color: var(--ca-charbon);
  border-bottom: 1px solid var(--ca-filet);
  white-space: normal;
}
/* A network's name may be long (« JEAN TROGNEUX LA MAISON DES BAPTEMES »): it wraps. */
.table-donnees.table-donnees--libelles tbody th a { white-space: normal; }
.cellule-sous { display: block; font-family: var(--font-mono); font-size: var(--fs-xs); color: var(--ca-gris-fort); }
