/* Hallmark · shape: Index-led studio, from draw b4b584 (Split Studio swapped: no photographs, the console is the material) · genre: atmospheric · theme: Lumen (deal 1/3, seed veloppeur-php-wordpress-ind-47a8·09cf57f9·2026-10-29·r0) · redesign: full · copy: verbatim
 * hero: Stage (text on 5 columns, the console on 7; draw said Poster) · nav: floating pill, solid (draw said search-led bar) · footer: mast, the wordmark over the real site map (draw said letter close) · imagery: the product, the intervention console replayed live · signature: the console replaying one intervention, the status turning from 500 to 200 OK
 * axes: dark/roman-serif/warm · posture: restrained · contrast: pass · fold: pass · v2.0.0 */
/* Hallmark · pre-emit critique: P4 H4 E4 S4 R4 V4 · weakest: H, the verbatim headline runs ten words, so it is set lowercase in the serif at the hero cap on five columns and the lead steps down to ink-2 */
/* Hallmark · waive 47c · theme geometry · la trame de plans vit dans le corps de la console, la bande du rail des étapes de service et les puits qui portent un schéma ou des mesures (seuils et courbes des guides) : derrière des mesures, jamais sous de la prose ; les vraies captures (Suite, MCT, Atari) n'ont qu'un cadre, sans trame */
/* Hallmark · waive 49b · real phrase, two lines at most · the copy is verbatim: « Faille PHP du 21 octobre » and the FAQ links sit mid-sentence, so at 375px they wrap with their sentence, never past two lines */
/* Hallmark · waive 78 · Long Document · contact, charte, pages légales, glossaire et guides se lisent comme un document : intertitres au corps de section (--text-section) en minuscules Instrument Serif, dans la colonne de lecture pour les guides (sommaire collant en marge), en marge pour les documents ; un seul registre, annexes au corps xl ; texte verbatim ; la casse normale reste aux légendes et aux têtes de tableau */
/* Hallmark · waive 44c · Banner posture · les pages intérieures s'ouvrent sur un bandeau titre : le h1 et son chapô sur la même rangée sur grand écran, sous un filet, les index y ajoutant leurs puces de rubrique ; les guides à schéma posent leur figure dans le bandeau ; la matière réelle commence dans le premier écran */
/* Hallmark · waive 38iii · lumen verb, once per page in a hero head · the verb of an inner page's h1 takes the rose of Lumen and a hairline underline drawn once; never on the home page, never a noun, never a second accented word */
/* Hallmark · waive 37 · four families at most · « Lumen Chiffres » n'est pas une famille de plus : c'est le fichier Geist déjà chargé, limité aux chiffres (unicode-range U+30-39), pour que le « 1 » des titres en Instrument Serif minuscule ne se lise plus « l » (numéros des CGV, FAQ, références CVE des guides) */
/* Hallmark · dismissed 23 · .read-progress est un filet fixe de 2 px de haut qui grandit en scaleX avec la lecture, jamais un aplat d'écran */
/* Hallmark · dismissed F7 · vérifié : la pilule ne couvre que la nav flottante, le lien d'évitement et des liens-étiquettes cliquables (rubriques, alphabet, sommaire des ressources, catégorie d'article), aucun bloc ni média */
/* Hallmark · dismissed F8 · le tracé .method/.steps vit sur l'accueil (sous la fiche de #tarifs), le tracé de méthode .service-method sur les pages de service qui le prennent (dont /automatisation-ia), la barre .read-progress seulement sur les guides : jamais deux de ces motifs sur une même page */
/* Hallmark · dismissed 77 · vérifié sur /devis, /contact, la charte, les pages légales et les guides : un formulaire ou un document se lit d’un bloc, le découper en six sections l’allongerait sans rien ajouter */
/* Hallmark · dismissed F20 · vérifié sur /ressources : une rubrique au nombre impair d'entrées laisse la dernière seule sur sa rangée, à sa largeur de colonne, note en bas à gauche comme les autres ; l'étirer sur deux colonnes en faisait un objet à part */
/* Hallmark · waive 79 · pages de service à 1440×900 (dépannage WordPress, WordPress piraté, WordPress lent, SEO WordPress) : la fiche finit à 701 px, la section suivante commence à 742 px et son titre à 766 px · le lint lit les sections d'une page de service comme un seul bloc (main > div.service-page) et compte jusqu'au pli un vide que la console ou le relevé occupe déjà */
/* Hallmark · dropped hidden _token=, hidden t= · valeurs régénérées à chaque session : les champs _token et t sont toujours dans le formulaire du devis */
/* Hallmark · waive 59 · .hero + .pledges-section, 49 px à 1440 · accueil seulement : le filet des engagements est le pied du héros, pas une section de plus ; méta et pied resserrés pour que la première ligne des engagements tienne dans le pli de 1440 × 900 et la méta entière dans celui de 1280 × 800, sans toucher au titre, à la phrase ni au bouton ; les autres jonctions gardent 120 px et plus */

/* ==========================================================================
   greenlog.fr : thème Lumen sur tout le portail. Ordre : jetons Lumen et
   alias des noms hérités de site.css, base, composants des pages
   intérieures, chrome et accueil, retouches Lumen des pages intérieures,
   puis en-tête mobile, lecture longue, pages d'index et conversion.
   site.css reste en place pour une page qui le demanderait
   (@section('stylesheet', 'site')).
   ========================================================================== */

@font-face { font-family: "Instrument Serif"; src: url("/fonts/instrument-serif-latin-400-normal.woff2") format("woff2"); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: "Geist"; src: url("/fonts/geist-latin-wght-normal.woff2") format("woff2"); font-weight: 100 900; font-style: normal; font-display: swap; }
@font-face { font-family: "Geist Mono"; src: url("/fonts/geist-mono-latin-wght-normal.woff2") format("woff2"); font-weight: 100 900; font-style: normal; font-display: swap; }

:root {
  color-scheme: dark;
  --space-3xs: 2px; --space-2xs: 4px; --space-xs: 8px; --space-sm: 12px; --space-md: 16px; --space-lg: 24px; --space-xl: 40px; --space-2xl: 64px; --space-3xl: 96px; --space-4xl: 144px;
  --text-xs: 0.8125rem; --text-sm: 0.875rem; --text-md: 1rem; --text-lg: 1.25rem; --text-xl: 1.5625rem; --text-2xl: 1.953rem; --text-3xl: 2.441rem;
  --text-display-s: clamp(2.25rem, 4vw + 0.5rem, 3.75rem); --text-display: clamp(2.75rem, 5vw + 1rem, 5.25rem);
  --text-section: clamp(2rem, 2.5vw + 1rem, 3.5rem); --text-title: clamp(1.25rem, 0.75vw + 0.875rem, 1.625rem); --text-lead: clamp(1.125rem, 0.35vw + 1rem, 1.375rem);
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1); --ease-in: cubic-bezier(0.7, 0, 0.84, 0); --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
  --dur-micro: 120ms; --dur-short: 220ms; --dur-long: 420ms;
  --color-error: oklch(72% 0.15 27); --color-success: oklch(76% 0.13 150);
  --container: 1440px; --gutter: 64px; --gap-columns: 32px; --section-gap-s: 120px; --section-gap: 144px; --section-gap-l: 176px;
  --z-base: 1; --z-raised: 10; --z-dropdown: 100; --z-sticky: 200; --z-sticky-nav: 300; --z-modal: 400; --z-toast: 500; --z-tooltip: 600;
  --color-paper: oklch(12.5% 0.027 290); --color-paper-2: oklch(16% 0.03 290); --color-paper-3: oklch(20% 0.032 290);
  --color-ink: oklch(96% 0.01 300); --color-ink-2: oklch(85% 0.017 298); --color-muted: oklch(69% 0.026 295);
  --color-rule: oklch(27% 0.034 290); --color-rule-2: oklch(36% 0.04 292); --rule-blueprint: oklch(96% 0.01 300 / 0.05);
  --color-accent: oklch(80% 0.15 62); --color-accent-2: oklch(72% 0.15 12); --color-accent-ink: oklch(14% 0.028 290);
  --color-live: oklch(80% 0.13 155); --color-focus: oklch(80% 0.15 62);
  --radius-card: 10px; --radius-pill: 999px; --rule-hair: 1px;
  --shadow-card: 0 28px 64px -30px oklch(4% 0.02 290 / 0.8);
  --tracking-display: -0.015em; --display-weight: 400;
  --text-body: 1.0625rem;
  --text-page: var(--text-display-s);
  --text-h2: clamp(1.5rem, 0.9vw + 1.15rem, 2rem);
  --measure: 56ch;
  --radius-field: 10px;
  --radius-chip: 6px;
  --color-amber-wash: color-mix(in oklch, var(--color-accent) 10%, var(--color-paper-2));
  --color-red-wash: color-mix(in oklch, var(--color-error) 12%, var(--color-paper));
  --color-red-rule: color-mix(in oklch, var(--color-error) 40%, var(--color-rule));
  --color-wp-blue: oklch(80% 0.08 235);
  --radius-lg: 14px;
  --header-h: 64px;
  --font-display: "Lumen Chiffres", "Instrument Serif", "Instrument Serif Fallback", ui-serif, Georgia, serif;
  --font-body: "Geist", "Geist Fallback", ui-sans-serif, system-ui, sans-serif;
  --font-outlier: "Geist Mono", "Geist Mono Fallback", ui-monospace, monospace;
}

/* Jetons des pages intérieures (noms hérités de site.css), ramenés aux
   valeurs Lumen : tout est sombre, l'ancienne « encre » devient la surface. */
*, *::before, *::after { box-sizing: border-box; }
html, body { overflow-x: clip; }
html { scrollbar-color: var(--color-muted) var(--color-paper); scroll-padding-top: var(--space-3xl); }
body { margin: 0; background: var(--color-paper); color: var(--color-ink); font-family: var(--font-body); font-size: var(--text-md); line-height: 1.55; -webkit-font-smoothing: antialiased; caret-color: var(--color-accent); font-variant-numeric: tabular-nums; }
::selection { background: color-mix(in oklab, var(--color-accent) 22%, transparent); color: var(--color-ink); }
:focus-visible { outline: 2px solid var(--color-focus); outline-offset: 2px; }
a { color: inherit; text-decoration-thickness: 1px; text-underline-offset: 0.16em; }
h1, h2, h3 { margin: 0; font-family: var(--font-display); font-weight: var(--display-weight, 700); font-synthesis: none; letter-spacing: var(--tracking-display); line-height: 1.05; overflow-wrap: break-word; min-width: 0; text-wrap: balance; }
h1 { max-width: 20ch; font-size: var(--text-display); }  h3 { max-width: 40ch; font-size: var(--text-title); line-height: 1.2; }
.lead { font-size: var(--text-lead); line-height: 1.45; max-width: 52ch; }
p { margin: 0; text-wrap: pretty; }
p:not([class]) { max-width: 60ch; }
img, video { max-width: 100%; height: auto; display: block; }
svg { display: block; }
[hidden] { display: none !important; }
button, input, select, textarea { font: inherit; }
.container { width: 100%; max-width: var(--container); margin-inline: auto; padding-inline: var(--gutter); box-sizing: border-box; }
.num, .figure, td.num { font-variant-numeric: tabular-nums; }
.visually-hidden { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
[data-slot] { position: relative; overflow: hidden; background: linear-gradient(160deg, var(--color-paper-2, var(--color-paper)), var(--color-paper-3, var(--color-paper))); }
[data-slot] > img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; z-index: 0; filter: grayscale(1) contrast(1.08); mix-blend-mode: multiply; }
[data-slot]:has(> img) > :not(img):not([data-keep]) { display: none !important; }
@media (max-width: 60rem) { :root { --gutter: 24px; --section-gap-s: 80px; --section-gap: 96px; --section-gap-l: 120px; } }
@media (max-width: 40rem) { :root { --gutter: 16px; --section-gap-s: 56px; --section-gap: 72px; --section-gap-l: 96px; --gap-columns: 16px; } }
@media (prefers-reduced-motion: reduce) { *:not(.keep-motion), *:not(.keep-motion)::before, *:not(.keep-motion)::after { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; scroll-behavior: auto !important; }
 .read-progress { display: none; }
}
/* photographs: duotone paper ink-2 */
[data-slot]:has(> img) { isolation: isolate; background: var(--color-ink-2); outline: 1px solid color-mix(in oklab, var(--color-ink) 8%, transparent); outline-offset: -1px; }
[data-slot]:has(> img)::before { content: ""; position: absolute; inset: 0; z-index: 1; background: var(--color-paper); mix-blend-mode: lighten; pointer-events: none; }
/* ---------- Typographie ---------- */
:where(main:not(:has(> .hero))) h1, :where(main:not(:has(> .hero))) h2, :where(main:not(:has(> .hero))) h3, :where(main:not(:has(> .hero))) h4 {
    color: var(--color-ink); font-family: var(--font-display); font-synthesis: none;
    text-wrap: balance; overflow-wrap: break-word; min-width: 0;
}
:where(main:not(:has(> .hero))) h1 {
    font-size: var(--text-page); font-weight: var(--display-weight); letter-spacing: var(--tracking-display);
    line-height: 1.05; margin-bottom: var(--space-md);
}
:where(main:not(:has(> .hero))) h2 {
    font-size: var(--text-h2); font-weight: var(--display-weight); letter-spacing: -0.02em; line-height: 1.15;
    margin-top: var(--space-xl); margin-bottom: var(--space-sm);
}
:where(main:not(:has(> .hero))) h3 { font-size: var(--text-lg); font-weight: var(--display-weight); letter-spacing: -0.01em; line-height: 1.25; margin-top: var(--space-lg); margin-bottom: var(--space-xs); }
:where(main:not(:has(> .hero))) h4 { font-size: var(--text-md); font-weight: var(--display-weight); margin-top: var(--space-lg); margin-bottom: var(--space-2xs); }
:where(main:not(:has(> .hero))) p { color: var(--color-ink-2); margin-bottom: var(--space-md); line-height: 1.65; text-wrap: pretty; }
:where(main:not(:has(> .hero))) p:last-child { margin-bottom: 0; }
:where(main:not(:has(> .hero))) ul, :where(main:not(:has(> .hero))) ol { padding-left: var(--space-lg); color: var(--color-ink-2); }
:where(main:not(:has(> .hero))) li { margin-bottom: var(--space-xs); line-height: 1.6; }
:where(main:not(:has(> .hero))) strong { color: var(--color-ink); font-weight: 500; }
:where(main:not(:has(> .hero))) hr { border: none; border-top: var(--rule-hair) solid var(--color-rule); margin: var(--space-xl) 0; }
:where(main:not(:has(> .hero))) .lead { font-size: var(--text-lead); line-height: 1.5; color: var(--color-ink-2); }

/* Lien dans un texte : souligné, pas seulement coloré (WCAG 1.4.1). */
main :where(p, li, td) > a:not(.btn) { text-decoration: underline; text-underline-offset: 0.2em; text-decoration-thickness: 1px; }
main :where(p, li, td) > a:not(.btn):hover { text-decoration-thickness: 2px; }
.link-row { display: flex; flex-wrap: wrap; gap: var(--space-xs) var(--space-lg); }
/* ---------- Contenu éditorial (guides, pages légales) ---------- */
.page-content { max-width: var(--container); margin: 0 auto; padding: var(--space-2xl) var(--gutter) var(--space-3xl); }
.breadcrumb { margin-bottom: var(--space-xl); font-family: var(--font-body); font-size: var(--text-sm); line-height: 1.5; text-transform: lowercase; color: var(--color-muted); overflow-wrap: break-word; text-wrap: pretty; }
.breadcrumb a { text-decoration: underline; text-underline-offset: 0.2em; display: inline-block; padding-block: var(--space-sm); margin-block: calc(-1 * var(--space-sm)); color: var(--color-muted); text-decoration-color: var(--color-rule-2); transition: color var(--dur-micro) var(--ease-out), text-decoration-color var(--dur-micro) var(--ease-out); }
/* Zone tactile de 44 px sans décaler la ligne (WCAG 2.5.5). */
.breadcrumb span::before { content: " / "; color: var(--color-muted); }
.page-content a:not(.btn) { text-underline-offset: 0.2em; }
.page-content p a:not(.btn), .page-content li a:not(.btn) { color: var(--color-ink); font-weight: 500; }
.page-content > h1, .page-content header h1 { max-width: 22ch; }
.page-content > p { max-width: var(--measure); }
.page-content > h1 + p { max-width: 60ch; font-size: var(--text-lead); line-height: 1.5; color: var(--color-ink-2); margin-bottom: var(--space-2xl); }

/* Documents (contact, à propos, charte, pages légales) : intertitres en marge, texte à 56ch.
   Chaque h2 ouvre une rangée : il occupe la marge, ce qui le suit la colonne de lecture. */
.page-content.is-doc { display: grid; grid-template-columns: minmax(0, 4fr) minmax(0, 8fr); column-gap: var(--gap-columns); align-items: start; }
.page-content.is-doc > * { grid-column: 2; max-width: var(--measure); min-width: 0; }
.page-content.is-doc > :is(.breadcrumb, h1) { grid-column: 1 / -1; max-width: none; }
.page-content.is-doc > h1 { max-width: 20ch; }
.page-content.is-doc > h1 + p { grid-column: 1 / -1; max-width: 60ch; line-height: 1.5; margin-bottom: var(--space-2xl); font-family: var(--font-outlier); font-size: var(--text-sm); color: var(--color-muted); }
.page-content.is-doc > h2 {
    grid-column: 1; max-width: 16ch; margin: var(--space-2xl) 0 0; padding-top: var(--space-md);
    border-top: var(--rule-hair) solid var(--color-rule-2); position: sticky; top: calc(var(--header-h) + var(--space-lg));
    font-size: var(--text-2xl);
    line-height: 1.1;
}
.page-content.is-doc > h2 + * { margin-top: var(--space-2xl); padding-top: var(--space-md); border-top: var(--rule-hair) solid var(--color-rule-2); max-width: none; }
.page-content.is-doc > :is(ul, ol) li { max-width: var(--measure); margin-bottom: 0.45em; padding-left: 0.2em; }
.page-content.is-doc > hr { display: none; }
/* Fiches en rangée (contact, éditeur et hébergeur) : elles passent la largeur entière. */
.doc-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr)); gap: var(--space-xl) var(--gap-columns); }
.page-content.is-doc > .doc-cards { grid-column: 1 / -1; max-width: none; margin-bottom: var(--space-lg); }
.doc-card { border-top: var(--rule-hair) solid var(--color-rule-2); padding-top: var(--space-lg); display: flex; flex-direction: column; align-items: flex-start; gap: var(--space-sm); }
.doc-card h2 { font-size: var(--text-title); margin: 0; }
.doc-card p { margin: 0 0 var(--space-xs); max-width: 48ch; }
.contact-email { font-size: var(--text-lg); text-decoration: underline; overflow-wrap: anywhere; }
.contact-email:hover { text-decoration-thickness: 2px; }
/* Blocs larges d'un document (grilles, encadrés) : toute la colonne de lecture, pas la mesure. */
.page-content.is-doc > :where(div, section, figure, table, form, details) { max-width: none; }
/* Index des outils et projets : une rangée par projet, titre à gauche, texte et liens à droite. */
.tools-grid { display: grid; border-bottom: var(--rule-hair) solid var(--color-rule-2); border-top: 0; }
.tool-row { display: grid; grid-template-columns: minmax(0, 4fr) minmax(0, 8fr); gap: var(--space-lg) var(--gap-columns); padding: var(--space-2xl) 0; border-top: var(--rule-hair) solid var(--color-rule-2); }
.tool-row-head { display: grid; grid-template-columns: auto minmax(0, 1fr); align-content: start; align-items: baseline; gap: var(--space-xs) var(--space-md); }
.tool-row .tag { grid-column: 2; justify-self: start; font-size: var(--text-xs); font-weight: 500; }
.tool-row h2 { grid-column: 2; font-size: var(--text-title); margin: 0; }
.tool-row-body p { margin: 0 0 var(--space-lg); max-width: var(--measure); }
.tool-links { display: flex; flex-wrap: wrap; gap: var(--space-sm); }

/* ---------- Glossaire ---------- */
.gh-intro { max-width: var(--measure); margin: 0 0 var(--space-2xl); font-size: var(--text-lead); line-height: 1.5; color: var(--color-ink-2); }
.gh-cards { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 var(--gap-columns); border-bottom: var(--rule-hair) solid var(--color-rule); }
.gh-card { position: relative; display: grid; grid-template-columns: 4.5rem minmax(0, 1fr); grid-template-areas: "count title" "count text"; align-content: start; gap: var(--space-xs) var(--space-lg); padding: var(--space-lg) var(--space-md); border-top: var(--rule-hair) solid var(--color-rule); transition: background-color var(--dur-short) var(--ease-out); }
.gh-card h2 { grid-area: title; font-size: var(--text-2xl); line-height: 1.02; margin: 0; }
.gh-card h2 a { color: inherit; text-decoration: underline; text-decoration-color: transparent; text-decoration-thickness: var(--rule-hair); text-underline-offset: 0.14em; transition: text-decoration-color var(--dur-micro) var(--ease-out); }
.gh-card h2 a::after { content: ""; position: absolute; inset: 0; }
.gh-card p { grid-area: text; margin: 0; max-width: var(--measure); font-size: var(--text-sm); color: var(--color-ink-2); }
.gh-count { grid-area: count; display: grid; align-content: start; gap: var(--space-2xs); font: 400 var(--text-xs)/1.4 var(--font-outlier); color: var(--color-muted); font-variant-numeric: tabular-nums; }
.gh-num { font-family: var(--font-display); font-size: var(--text-display-s); line-height: 0.9; letter-spacing: var(--tracking-display); color: var(--color-ink); }
/* Lettres de l'index : pilules à filet, Geist 500 en minuscules, paper-2 au survol. */
.gh-azbar { display: flex; flex-wrap: wrap; gap: var(--space-2xs); margin: 0 0 var(--space-2xl); }
.gh-azbar a { display: grid; place-items: center; min-width: 44px; height: 44px; font-weight: 500; text-transform: lowercase; color: var(--color-ink-2); background: none; border: var(--rule-hair) solid var(--color-rule-2); border-radius: var(--radius-pill); text-decoration: none; transition: background-color var(--dur-micro) var(--ease-out), border-color var(--dur-micro) var(--ease-out), color var(--dur-micro) var(--ease-out); }
.gh-azbar a:hover { color: var(--color-ink); background: var(--color-paper-2); border-color: var(--color-muted); }
.gh-letter { display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 10fr); gap: var(--space-sm) var(--gap-columns); padding: var(--space-lg) 0; border-top: var(--rule-hair) solid var(--color-rule-2); scroll-margin-top: calc(var(--header-h) + var(--space-sm) + var(--space-2xl) + var(--space-lg)); }
.gh-letter h3 { margin: 0; font-weight: var(--display-weight); line-height: 1.1; font-size: var(--text-3xl); color: var(--color-ink); }
.gh-list { list-style: none; margin: 0; padding: 0; columns: 3 15rem; column-gap: var(--gap-columns); }
.gh-entry { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--space-3xs) var(--space-xs); padding: var(--space-2xs) 0; break-inside: avoid; }
.gh-entry a { font-weight: 500; color: var(--color-ink); text-decoration: none; text-decoration-line: underline; text-decoration-color: transparent; text-underline-offset: 0.2em; transition: color var(--dur-micro) var(--ease-out), text-decoration-color var(--dur-micro) var(--ease-out); }
.gh-entry a:hover { text-decoration: underline; }
.gh-tag { font-size: var(--text-xs); color: var(--color-muted); white-space: nowrap; }
.gh-foot { max-width: var(--measure); margin: var(--space-2xl) 0 0; padding-top: var(--space-lg); border-top: var(--rule-hair) solid var(--color-rule-2); color: var(--color-ink-2); }

/* ---------- Outil version PHP ---------- */
.vp-layout { display: grid; grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); gap: var(--space-2xl) var(--gap-columns); align-items: start; }
.vp-form { display: flex; flex-wrap: wrap; gap: var(--space-sm); align-items: flex-end; }
.vp-form .field { flex: 1 1 16rem; }
.vp-form .btn { flex: 0 0 auto; }
.vp-hint { margin: var(--space-sm) 0 0; font-size: var(--text-sm); color: var(--color-muted); }
.vp-box { margin-top: var(--space-lg); padding: var(--space-lg); border: var(--rule-hair) solid var(--color-rule); border-radius: var(--radius-field); background: var(--color-paper); }
.vp-box h2 { font-size: var(--text-title); margin: 0 0 var(--space-xs); }
.vp-box p { margin: var(--space-xs) 0; }
.vp-verdict-warn { border-color: var(--color-accent); background: var(--color-amber-wash); }
.vp-verdict-warn h2 { color: var(--color-accent); }
.vp-verdict-ok { background: var(--color-paper-2); color: var(--color-ink); border-color: var(--color-live); }
.vp-verdict-ok h2 { color: var(--color-ink); }
.vp-details { display: grid; gap: var(--space-sm); margin: var(--space-md) 0 0; padding: 0; list-style: none; }
.vp-details li { padding-top: var(--space-sm); border-top: var(--rule-hair) solid var(--color-rule); font-size: var(--text-sm); overflow-wrap: anywhere; }
.vp-details dl { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: var(--space-3xs) var(--space-sm); margin: var(--space-2xs) 0 0; }
.vp-details dt { color: var(--color-muted); }
.vp-details dd { margin: 0; font-family: var(--font-outlier); font-size: var(--text-sm); }
.vp-aside { padding-top: var(--space-md); border-top: var(--rule-hair) solid var(--color-rule-2); }
.vp-note p { margin: 0; max-width: var(--measure); color: var(--color-ink-2); }
.vp-versions { min-width: 0; }
.vp-table { width: 100%; border-collapse: collapse; font-variant-numeric: tabular-nums; color: var(--color-ink); }
.vp-table th, .vp-table td { text-align: left; padding: var(--space-sm) var(--space-md) var(--space-sm) 0; border-bottom: var(--rule-hair) solid var(--color-rule); }
.vp-table th { font-size: var(--text-sm); font-weight: 400; color: var(--color-muted); border-bottom-color: var(--color-rule-2); }
.vp-table td + td { font-family: var(--font-outlier); font-size: var(--text-sm); }
.vp-table tr:last-child td { border-bottom: 0; }
.vp-versions .vp-hint { margin-top: var(--space-md); }
.vp-more { display: inline-flex; align-items: center; min-height: 48px; text-decoration: underline; }

/* ---------- Ressources ---------- */

/* ---------- Études de cas ---------- */
.cases-intro { display: grid; grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); gap: var(--space-xl) var(--gap-columns); }
.cases-intro-body p { max-width: var(--measure); color: var(--color-ink-2); }
.cases-intro-body p:last-child { margin-bottom: 0; }
/* Une phrase de méthode : une note à filet calée en haut, pas un puits étiré à la hauteur de l'intro. */
.cases-note { align-self: start; max-width: var(--measure); margin: 0; padding-top: var(--space-md); border-top: var(--rule-hair) solid var(--color-rule-2); color: var(--color-ink-2); }
.tool-row-body .case-source { margin-bottom: var(--space-sm); font-size: var(--text-sm); color: var(--color-muted); }
.case-meta { display: flex; flex-wrap: wrap; gap: var(--space-2xs) var(--space-md); font-size: var(--text-xs); color: var(--color-muted); font-variant-numeric: tabular-nums; }
/* La date et la durée de lecture sont des étiquettes, pas des relevés : Geist, comme la rubrique. */
.case-meta a { font-weight: 500; color: var(--color-ink); }
.cases-list { margin-top: var(--space-3xl); }

/* ---------- Page auteur ---------- */
.author-role { margin: 0 0 var(--space-lg); font-weight: 500; color: var(--color-ink-2); }
.prose-body.author-prose { max-width: var(--measure); }
.author-prose p { color: var(--color-ink-2); }
.author-prose p:last-child { margin-bottom: 0; }
.author-facts { margin-top: var(--space-2xl); }
.author-proofs { margin: 0; padding: 0; list-style: none; }
.author-aside { max-width: var(--measure); margin: var(--space-2xl) 0 0; color: var(--color-ink-2); }
.author-scope { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-2xl) var(--gap-columns); }
.author-scope-col { padding-top: var(--space-lg); border-top: var(--rule-hair) solid var(--color-rule-2); }
.author-scope-col h2 { margin: 0 0 var(--space-md); font-size: var(--text-title); letter-spacing: -0.02em; }
.author-scope-col p { max-width: var(--measure); margin: 0; color: var(--color-ink-2); }
.author-scope-col p a { color: var(--color-ink); font-weight: 500; }
.author-topics { display: flex; flex-wrap: wrap; gap: var(--space-xs); margin: var(--space-lg) 0 0; padding: 0; list-style: none; }
.author-topics li { margin: 0; }
.author-topics a { display: inline-flex; align-items: center; min-height: 44px; padding: 0 var(--space-md); font-size: var(--text-sm); font-weight: 500; color: var(--color-ink); background: var(--color-paper-2); border: var(--rule-hair) solid var(--color-rule); border-radius: var(--radius-pill); text-decoration: none; transition: border-color var(--dur-micro) var(--ease-out); }
.author-topics a:hover { border-color: var(--color-rule-2); }

/* ---------- À propos ---------- */
.about-statement { display: grid; grid-template-columns: minmax(0, 4fr) minmax(0, 8fr); gap: var(--space-lg) var(--gap-columns); }
.about-statement h2 { grid-column: 1 / -1; margin: 0; letter-spacing: var(--tracking-display); font-size: var(--text-display-s); line-height: 0.98; max-width: 24ch; }
.about-statement .prose-body { grid-column: 2; font-size: var(--text-lead); line-height: 1.5; }
.about-services { max-width: var(--measure); margin: 0; padding: 0; list-style: none; border-top: var(--rule-hair) solid var(--color-rule-2); }
.about-services li { margin: 0; padding: var(--space-md) 0; border-bottom: var(--rule-hair) solid var(--color-rule); color: var(--color-ink-2); }
.about-services a { font-weight: 500; color: var(--color-ink); }
.about-services li > a:first-child { color: var(--color-ink); }
/* La note des prix devient une fiche en puits : une rangée à filet par tarif, le montant en serif
   au corps display, l'unité en relevé mono ; la phrase reste entière dans le code. */
.about-note { max-width: none; margin: var(--space-xl) 0 0; padding: var(--space-md) var(--space-lg); line-height: 1.5; color: var(--color-ink-2); background: var(--color-paper-2); border: var(--rule-hair) solid var(--color-rule); border-radius: var(--radius-card); }
.about-note-lead, .about-note-foot { display: block; }
.about-note-lead { padding-block: var(--space-xs) var(--space-md); }
.about-rate { display: grid; grid-template-columns: minmax(0, 8.5rem) minmax(0, 1fr); gap: var(--space-lg); align-items: last baseline; padding-block: var(--space-md); border-top: var(--rule-hair) solid var(--color-rule); }
.about-rate-pre { display: block; margin-bottom: var(--space-2xs); font-size: var(--text-sm); color: var(--color-muted); }
.about-fig { font-family: var(--font-display); font-size: var(--text-display-s); font-weight: var(--display-weight); line-height: 1; letter-spacing: var(--tracking-display); color: var(--color-ink); white-space: nowrap; font-variant-numeric: lining-nums tabular-nums; }
.about-unit { font-family: var(--font-outlier); font-size: var(--text-sm); letter-spacing: 0; color: var(--color-muted); }
.about-note-foot { padding-block: var(--space-md) var(--space-xs); border-top: var(--rule-hair) solid var(--color-rule); font-size: var(--text-sm); }
.about-note a { font-weight: 500; color: var(--color-ink); }
/* Les quatre preuves en puits de largeurs alternées (7 + 5, puis 5 + 7 colonnes) : pas quatre colonnes égales. */
/* Preuves d'à propos : rangées à filet, deux par deux, comme les réalisations de la page auteur. */
.about-proofs { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 var(--gap-columns); margin: 0; padding: 0; list-style: none; }
.about-proofs li { margin: 0; padding: var(--space-lg) 0 var(--space-xl); color: var(--color-ink-2); border-top: var(--rule-hair) solid var(--color-rule-2); line-height: 1.6; }
.about-proofs strong { font-family: var(--font-display); font-size: var(--text-xl); font-weight: var(--display-weight); line-height: 1.1; letter-spacing: var(--tracking-display); }
.about-proofs strong { color: var(--color-ink); }
.about-proofs a { font-weight: 500; color: var(--color-ink); }
.stack-list { display: flex; flex-wrap: wrap; gap: var(--space-xs); margin: 0 0 var(--space-lg); }
.stack-tag { display: inline-flex; align-items: center; min-height: 32px; padding: 0 var(--space-md); font-size: var(--text-xs); color: var(--color-ink-2); border: var(--rule-hair) solid var(--color-rule-2); border-radius: var(--radius-pill); }
.tool-row h3 { grid-column: 2; margin: 0; font-size: var(--text-title); }
.tool-row h3 a { color: inherit; display: inline-block; text-decoration: none; transition: transform var(--dur-short) var(--ease-out); }
.about-links { margin: 0; padding: 0; list-style: none; }
.about-links li { margin: 0; padding: var(--space-sm) 0; border-bottom: var(--rule-hair) solid var(--color-rule); color: var(--color-ink-2); }
.about-links a { font-weight: 500; color: var(--color-ink); }

/* ---------- Paiement et confirmations ---------- */
.pricing.is-pay { grid-template-columns: repeat(auto-fit, minmax(min(100%, 16rem), 1fr)); }
.pricing.is-pay .price-card { justify-content: space-between; }
.pricing.is-pay .price-amount { font-size: var(--text-2xl); font-variant-numeric: tabular-nums; }
.thanks-hero { min-height: 62svh; display: flex; align-items: center; }
.thanks-hero .wrap { width: 100%; }
.thanks-status { display: inline-flex; width: fit-content; margin-bottom: var(--space-lg); }
.page-hero.thanks-hero .lead { margin-bottom: var(--space-lg); }
.thanks-text { max-width: var(--measure); margin: 0 0 var(--space-sm); font-size: var(--text-body); color: var(--color-ink-2); }
.thanks-text a { font-weight: 500; color: var(--color-ink); }
.page-hero.is-404 { min-height: calc(100svh - var(--header-h)); }
.page-hero.is-404 h1 { font-size: var(--text-display); line-height: 1; letter-spacing: var(--tracking-display); max-width: 12ch; }

/* ---------- Guides et études de cas : article ---------- */
.article-hero h1 { max-width: 24ch; margin-bottom: var(--space-md); }
.article-meta { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-xs) var(--space-md); font-size: var(--text-sm); color: var(--color-ink-2); }
.article-meta a:not(.article-cat) { color: var(--color-ink); font-weight: 500; }
.article-cat {
    display: inline-flex; align-items: center; min-height: 32px; padding: 0 var(--space-sm); border-radius: var(--radius-chip);
    background: var(--color-paper-2); border: var(--rule-hair) solid var(--color-rule); color: var(--color-ink); font-weight: 500; text-decoration: none;
    transition: border-color var(--dur-micro) var(--ease-out);
}
.article-cat:hover { border-color: var(--color-rule-2); }
.article-section { padding-top: var(--space-3xl); }
.article-layout { display: grid; grid-template-columns: minmax(0, 4fr) minmax(0, 8fr); gap: var(--space-2xl) var(--gap-columns); align-items: start; }
.article-rail { display: flex; flex-direction: column; gap: var(--space-xl); align-self: stretch; }
/* « À retenir » suit la lecture tant que l'écran le permet. */
.article-rail > :last-child { position: sticky; top: calc(var(--header-h) + var(--space-lg)); max-height: calc(100vh - var(--header-h) - var(--space-2xl)); overflow-y: auto; overscroll-behavior: contain; scrollbar-width: thin; }
.article-main { min-width: 0; }
.article-main > * + * { margin-top: var(--space-2xl); }

.article-toc { padding-top: var(--space-md); border-top: var(--rule-hair) solid var(--color-rule-2); }
.article-toc h2, .takeaways h2 { margin: 0 0 var(--space-md); font-size: var(--text-lg); }
.article-toc ol { margin: 0; padding: 0; list-style: none; }
.article-toc li { margin: 0; font-size: var(--text-sm); display: grid; grid-template-columns: 2.25em minmax(0, 1fr); align-items: baseline; gap: 0; padding: 0 0 0 var(--space-sm); border-bottom: 0; border-left: var(--rule-hair) solid var(--color-rule); transition: border-color var(--dur-short) var(--ease-out); }
.article-toc li span { font-variant-numeric: tabular-nums; min-width: 0; font-size: var(--text-xs); transition: color var(--dur-short) var(--ease-out); }
.article-toc a { color: var(--color-ink); text-decoration: none; }
.article-toc a:hover { color: var(--color-ink); text-decoration: underline; text-underline-offset: 0.2em; }
.takeaways { padding-top: var(--space-md); border-top: var(--rule-hair) solid var(--color-rule-2); color: var(--color-ink); }
.takeaways ul { margin: 0; padding: 0; list-style: none; }
.takeaways li { position: relative; margin: 0 0 var(--space-sm); padding-left: var(--space-lg); font-size: var(--text-md); line-height: 1.55; color: var(--color-ink-2); }
.takeaways li::before { content: ""; position: absolute; left: 0; top: 0.78em; top: round(nearest, 0.78em, 1px); width: var(--space-sm); height: var(--rule-hair); background: var(--color-muted); }
.takeaways li strong { color: var(--color-ink); font-weight: 500; }
.takeaways li:last-child { margin-bottom: 0; }

.dataset { padding: var(--space-lg) var(--space-xl); border-radius: var(--radius-card); background: var(--color-paper-2); color: var(--color-ink); }
.dataset h2 { margin: 0 0 var(--space-md); font-size: var(--text-lg); }
.dataset dl { display: grid; grid-template-columns: 8rem minmax(0, 1fr); gap: var(--space-xs) var(--space-lg); margin: 0; }
.dataset dt { font-size: var(--text-sm); font-weight: 500; color: var(--color-muted); }
.dataset dd { margin: 0; font-size: var(--text-md); color: var(--color-ink-2); }

.article-figure { margin: 0; padding: var(--space-lg); border-radius: var(--radius-card); background: var(--color-paper-2); color: var(--color-ink); }
.article-figure svg { display: block; width: 100%; height: auto; }
.article-figure figcaption { margin-top: var(--space-sm); font-size: var(--text-sm); color: var(--color-muted); text-align: center; }

.article-body > :first-child { margin-top: 0; }
.article-body :is(p, ul, ol, blockquote, h2, h3) { max-width: var(--measure); }
.article-body p, .article-body li { color: var(--color-ink-2); }
.article-body .lead { color: var(--color-ink); margin-bottom: var(--space-xl); font-size: var(--text-lead); line-height: 1.55; }
.article-body a { color: var(--color-ink); font-weight: 500; text-underline-offset: 0.2em; }
.article-body blockquote { color: var(--color-ink); background: none; border-left: 2px solid var(--color-rule-2); border-radius: 0; margin: var(--space-xl) 0; padding: var(--space-2xs) 0 var(--space-2xs) var(--space-lg); }
.article-body blockquote p { margin: 0; font-size: var(--text-lead); line-height: 1.55; color: var(--color-ink); }
.article-body pre { margin: var(--space-xl) 0; padding: var(--space-md) var(--space-lg); overflow-x: auto; border-radius: 0; font-family: var(--font-outlier); font-size: var(--text-sm); line-height: 1.6; background: var(--color-paper-2); color: var(--color-ink); border: var(--rule-hair) solid var(--color-rule); }
.article-body pre code { padding: 0; background: none; color: inherit; font-size: inherit; }
.article-body code { padding: 0.1em 0.35em; border-radius: var(--radius-chip); font-family: var(--font-outlier); font-size: 0.88em; background: var(--color-paper-3); color: var(--color-ink); }
.article-body table { display: block; overflow-x: auto; margin: var(--space-xl) 0; border-collapse: collapse; max-width: 100%; width: max-content; min-width: min(100%, var(--measure)); font-size: var(--text-sm); line-height: 1.5; font-variant-numeric: tabular-nums; border-radius: 0; background:
    linear-gradient(to right, var(--color-paper-2), var(--color-paper-2)) left / 24px 100% no-repeat local,
    linear-gradient(to left, var(--color-paper-2), var(--color-paper-2)) right / 24px 100% no-repeat local,
    linear-gradient(to right, var(--color-rule-2), transparent) left / 12px 100% no-repeat scroll,
    linear-gradient(to left, var(--color-rule-2), transparent) right / 12px 100% no-repeat scroll; background-color: var(--color-paper-2); }
.article-body thead th { border-bottom: var(--rule-hair) solid var(--color-rule-2); text-align: left; white-space: nowrap; padding: var(--space-xs) var(--space-md) var(--space-xs) 0; font-size: var(--text-sm); font-weight: 400; color: var(--color-ink-2); vertical-align: bottom; }
.article-body tbody td { border-bottom: var(--rule-hair) solid var(--color-rule); color: var(--color-ink-2); padding: var(--space-sm) var(--space-md) var(--space-sm) 0; vertical-align: top; }
.article-body tbody td:nth-child(2) { font-variant-numeric: tabular-nums; }
.article-body tbody td:nth-child(2):not(:last-child) { white-space: nowrap; }

.tool-note { padding: var(--space-lg) var(--space-xl); border: var(--rule-hair) dashed var(--color-muted); border-radius: var(--radius-card); }
.tool-note-flag { margin: 0 0 var(--space-xs); font-size: var(--text-sm); font-weight: 500; color: var(--color-muted); }
.tool-note h2 { margin: 0; font-size: var(--text-title); }
.tool-note-kind { margin: 0 0 var(--space-md); font-size: var(--text-sm); color: var(--color-muted); }
.tool-note p { max-width: var(--measure); margin: 0 0 var(--space-sm); color: var(--color-ink-2); }
.tool-note p.tool-note-limit { font-size: var(--text-sm); }
.tool-note a { color: var(--color-ink); font-weight: 500; }

.article-faq h2, .sources h2, .changelog h2, .glo-related h2 { margin: 0 0 var(--space-md); padding-top: var(--space-md); border-top: var(--rule-hair) solid var(--color-rule-2); font-size: var(--text-h2); letter-spacing: -0.02em; }
.faq-item { max-width: var(--measure); padding: var(--space-md) 0; border-bottom: var(--rule-hair) solid var(--color-rule); }
.faq-item h3 { margin: 0 0 var(--space-xs); font-size: var(--text-lg); }
.faq-item p { margin: 0; color: var(--color-ink-2); }
.faq-item p a, .changelog > p a, .glo-related a { color: var(--color-ink); font-weight: 500; }
.sources ul, .glo-related ul { max-width: var(--measure); margin: 0; padding-left: var(--space-lg); }
.sources li, .glo-related li { margin-bottom: var(--space-xs); color: var(--color-ink-2); }
.sources a { color: var(--color-ink); font-weight: 500; }
.glo-related li span { color: var(--color-muted); }
.glo-related > p { margin: var(--space-md) 0 0; }
.changelog > p { max-width: var(--measure); margin: 0 0 var(--space-md); color: var(--color-ink-2); }
.changelog ol { margin: 0; padding: 0; list-style: none; }
.changelog li { display: grid; grid-template-columns: 7rem minmax(0, 1fr); gap: var(--space-md); padding: var(--space-sm) 0; border-bottom: var(--rule-hair) solid var(--color-rule); }
.changelog time { font-variant-numeric: tabular-nums; }
.changelog li p { max-width: var(--measure); margin: 0; color: var(--color-ink-2); }

.author-box { display: grid; color: var(--color-ink); grid-template-columns: minmax(0, 1fr); gap: var(--space-md) var(--space-lg); padding: var(--space-xl) 0 0; border-top: var(--rule-hair) solid var(--color-rule-2); border-radius: 0; background: none; }
.author-box h2 { margin: 0 0 var(--space-xs); font-size: var(--text-xl); line-height: 1.2; }
.author-box h2 a { color: var(--color-ink); text-decoration: none; }
.author-box p { max-width: var(--measure); margin: 0 0 var(--space-sm); color: var(--color-ink-2); }
.author-links { display: flex; flex-wrap: wrap; font-size: var(--text-sm); gap: 0 var(--space-lg); margin-top: var(--space-xs); }
.author-links a { display: inline-flex; align-items: center; min-height: 44px; font-weight: 500; color: var(--color-ink); text-decoration: underline; text-decoration-color: var(--color-rule-2); text-underline-offset: 0.3em; transition: color var(--dur-micro) var(--ease-out), text-decoration-color var(--dur-micro) var(--ease-out); }

.guide-nav { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-md); }
.guide-nav a { display: flex; flex-direction: column; gap: var(--space-2xs); padding: var(--space-md) var(--space-lg); border: var(--rule-hair) solid var(--color-rule); border-radius: var(--radius-card); text-decoration: none; transition: border-color var(--dur-short) var(--ease-out); }
.guide-nav a:hover { border-color: var(--color-rule-2); }
.gn-label { font-size: var(--text-sm); color: var(--color-muted); }
.gn-title { font-weight: 500; color: var(--color-ink); }
.guide-nav .gn-next { text-align: right; }

/* ---------- Glossaire : page d'un domaine ---------- */
.glo-side { position: sticky; top: 96px; display: flex; flex-direction: column; padding-top: var(--space-md); border-top: var(--rule-hair) solid var(--color-rule-2); }
.glo-side h2 { margin: 0 0 var(--space-sm); font-size: var(--text-lg); }
.glo-side a { display: flex; align-items: center; min-height: 44px; font-size: var(--text-sm); color: var(--color-ink); border-bottom: var(--rule-hair) solid var(--color-rule); text-decoration: none; }
.glo-side a:hover { color: var(--color-ink); }
.glo-side a.is-active { font-weight: 500; color: var(--color-ink); }
.glo-toc { margin-bottom: var(--space-xl); }
.glo-term { padding: var(--space-xl) 0; border-top: var(--rule-hair) solid var(--color-rule-2); scroll-margin-top: 96px; transition: border-color var(--dur-long) var(--ease-out); }
.glo-term h2 { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--space-xs); margin: 0 0 var(--space-md); font-size: var(--text-title); }
.glo-anchor { font-family: var(--font-outlier); font-size: var(--text-sm); font-weight: 400; color: var(--color-muted); text-decoration: none; display: inline-block; min-width: 24px; min-height: 24px; line-height: 24px; text-align: center; opacity: 0; transition: opacity var(--dur-micro) var(--ease-out), color var(--dur-micro) var(--ease-out); }
.glo-def { max-width: var(--measure); margin: 0 0 var(--space-md); font-size: var(--text-body); line-height: 1.7; color: var(--color-ink); }
.glo-meta { display: grid; gap: var(--space-sm); }
.glo-row { display: grid; grid-template-columns: 9rem minmax(0, 1fr); gap: var(--space-sm) var(--space-lg); align-items: baseline; }
.glo-row p { max-width: var(--measure); margin: 0; font-size: var(--text-md); color: var(--color-ink-2); }
.glo-label { font-family: var(--font-body); font-size: var(--text-sm); font-weight: 400; text-transform: lowercase; color: var(--color-muted); }
.glo-guide { max-width: var(--measure); margin: var(--space-md) 0 0; font-size: var(--text-sm); }
.glo-guide a { font-weight: 500; color: var(--color-ink); }
.glo-foot { padding-top: var(--space-xl); border-top: var(--rule-hair) solid var(--color-rule-2); }
.glo-foot > p { max-width: var(--measure); margin: 0 0 var(--space-xl); color: var(--color-ink-2); }

/* ---------- Guides : index et rubriques ---------- */
/* Signature sur une ligne, les deux liens sur la suivante : pas de points médians. */
.hero-byline { display: grid; justify-items: start; gap: var(--space-2xs); margin: var(--space-md) 0 0; font-size: var(--text-sm); color: var(--color-ink-2); }
.hero-byline-links { display: flex; flex-wrap: wrap; gap: 0 var(--space-lg); }
.hero-byline a { display: inline-flex; align-items: center; min-height: 24px; color: var(--color-ink); font-weight: 500; text-underline-offset: 0.2em; text-decoration-color: var(--color-rule-2); transition: text-decoration-color var(--dur-micro) var(--ease-out); }
.hero-byline a:hover { text-decoration-color: var(--color-accent); }
.cat-nav { display: flex; flex-wrap: wrap; gap: var(--space-xs); margin: 0 0 var(--space-2xl); }
.cat-nav a {
    display: inline-flex; align-items: center; min-height: 44px; padding: 0 var(--space-md); white-space: nowrap;
    font-size: var(--text-sm); font-weight: 500; text-transform: lowercase; color: var(--color-ink-2); background: none;
    border: var(--rule-hair) solid var(--color-rule-2); border-radius: var(--radius-pill); text-decoration: none;
    transition: background-color var(--dur-micro) var(--ease-out), border-color var(--dur-micro) var(--ease-out), color var(--dur-micro) var(--ease-out);
}
.cat-nav a:hover { color: var(--color-ink); background: var(--color-paper-2); border-color: var(--color-muted); }
/* Introduction de rubrique : le texte de la page, au corps courant et à 60ch, pas une note de marge. */
.cat-body { max-width: 60ch; margin: 0; }
.cat-body p { margin: 0 0 0.85em; font-size: var(--text-md); line-height: 1.6; color: var(--color-ink-2); }
.cat-body p:last-child { margin-bottom: 0; }
.cat-list-title { margin: 0 0 var(--space-xl); font-size: var(--text-display-s); line-height: 0.98; }
.guide-cards { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-2xl) var(--gap-columns); }
.guide-card { position: relative; display: flex; flex-direction: column; gap: var(--space-sm); padding-top: var(--space-md); border-top: var(--rule-hair) solid var(--color-rule-2); }
/* Étiquette de rubrique : Geist un cran sous le texte, minuscules, atténuée ; filet laiton au survol. */
.guide-card-cat { position: relative; z-index: 1; align-self: flex-start; font-size: var(--text-xs); text-transform: lowercase; color: var(--color-muted); text-decoration: underline; text-decoration-color: transparent; text-underline-offset: 0.25em; transition: color var(--dur-micro) var(--ease-out), text-decoration-color var(--dur-micro) var(--ease-out); }
.guide-card-cat:hover { color: var(--color-ink); text-decoration-color: var(--color-accent); }
.guide-card :is(h2, h3) { margin: 0; font-size: var(--text-title); font-weight: var(--display-weight); line-height: 1.25; }
.guide-card :is(h2, h3) a { color: inherit; text-decoration: none; }
.guide-card :is(h2, h3) a::after { content: ""; position: absolute; inset: 0; }
.guide-card :is(h2, h3) a:hover { color: var(--color-ink); }
.guide-card p { flex: 1; margin: 0; font-size: var(--text-sm); color: var(--color-ink-2); }
.guide-card-foot { display: flex; align-items: center; gap: var(--space-xs); font-size: var(--text-xs); color: var(--color-muted); font-variant-numeric: tabular-nums; }
.guide-card p, .guide-card :is(h2, h3) { max-width: var(--measure); }
/* ---------- Sections ---------- */
.section.is-tight { padding: var(--section-gap-s) 0; }
.section.is-roomy { padding: var(--section-gap-l) 0; }
.section.is-ruled { border-top: var(--rule-hair) solid var(--color-rule); }

/* Tête à gauche, contenu à droite */
.wrap.is-split { display: grid; grid-template-columns: minmax(0, 4fr) minmax(0, 8fr); gap: var(--space-xl) var(--gap-columns); align-items: start; }
.wrap.is-split .section-head { display: block; margin: 0; }
.wrap.is-split .section-head p { margin-top: var(--space-md); }

/* Page service : hero posé, texte et offre */
.service-hero { color: var(--color-ink); padding: var(--space-2xl) 0; }
.service-hero .breadcrumb { margin-bottom: var(--space-lg); }
.service-hero-grid { display: grid; grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); gap: var(--space-2xl); align-items: center; }
.service-hero-grid > * { min-width: 0; }
.service-hero .lead { font-size: var(--text-lead); max-width: 44ch; }

/* Pages secondaires : bandeau (Banner), la première section monte dans l'écran */
.page-hero { color: var(--color-ink); padding: var(--space-2xl) 0 var(--space-xl); }
.page-hero .breadcrumb { margin-bottom: var(--space-lg); }
.page-hero h1 { margin-bottom: var(--space-lg); animation: settle 640ms var(--ease-out) both; }
.page-hero .lead { font-size: var(--text-lead); line-height: 1.55; max-width: 62ch; color: var(--color-ink-2); margin: 0; animation: settle 640ms var(--ease-out) both; }
.page-hero .hero-actions { animation: settle 640ms var(--ease-out) both; display: flex; flex-wrap: wrap; gap: var(--space-sm); margin-top: var(--space-xl); }

/* ---------- Tarifs ---------- */
.offer-box .pricing-note { margin-top: var(--space-sm); }
.offer-box .offer-name { display: block; margin: 0 0 var(--space-2xs); }
/* Étiquettes de l'offre (nom, unité) : Geist un cran plus petit, minuscules, atténuées ; la mono reste aux relevés. */
.offer-box .price-unit { font: 400 var(--text-sm)/1.5 var(--font-body); text-transform: lowercase; color: var(--color-muted); }

.pricing.is-four { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.pricing.is-four .price-card { padding: var(--space-lg); }

/* Notes de périmètre : un filet d'accent, pas une carte */
.scope-note { margin-top: var(--space-xl); max-width: none; }
/* L'amorce est une étiquette Lumen ; la liste, des rangées à filet comme un index. */
.scope-note strong { display: block; margin-bottom: var(--space-sm); font: 500 var(--text-sm)/1.5 var(--font-body); color: var(--color-muted); text-transform: lowercase; }
.scope-note ul { list-style: none; margin: 0; padding: 0; border-top: var(--rule-hair) solid var(--color-rule-2); }
.scope-note li { margin: 0; padding: var(--space-sm) 0; border-bottom: var(--rule-hair) solid var(--color-rule); color: var(--color-ink-2); }
.scope-note p { margin: 0; padding-top: var(--space-sm); border-top: var(--rule-hair) solid var(--color-rule-2); color: var(--color-ink-2); }
.scope-notes { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 var(--gap-columns); }

/* Maintenance : le prix en grand, la liste à côté, sur le 6/6 de la page (la liste part au milieu, comme la colonne « non » du périmètre). */
.maint { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-xl) var(--gap-columns); padding: var(--space-2xl) 0; border-top: var(--rule-hair) solid var(--color-rule-2); border-bottom: var(--rule-hair) solid var(--color-rule); }
.maint-price .price-amount { font-size: var(--text-display); font-variant-numeric: tabular-nums; }
.maint-price .price-unit { max-width: 24ch; }
.maint-list { list-style: none; padding: 0; margin: 0; display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-md); max-width: 72ch; }
.maint-list li { position: relative; padding-left: var(--space-lg); margin: 0; }
.maint-list li::before {
    content: ""; position: absolute; left: var(--space-3xs); top: 0.5em; width: 0.6em; height: 0.32em;
    border-left: 2px solid var(--color-ink-2); border-bottom: 2px solid var(--color-ink-2); transform: rotate(-45deg);
}

/* Liens d'index : une ligne par destination */
.link-index { list-style: none; padding: 0; margin: 0; border-top: var(--rule-hair) solid var(--color-rule-2); }
.link-index li { margin: 0; padding: var(--space-md) 0; border-bottom: var(--rule-hair) solid var(--color-rule); color: var(--color-ink-2); }
.link-index a { color: var(--color-ink); font-weight: 500; text-decoration-color: var(--color-accent); text-underline-offset: 0.25em; }
.link-index a:hover { color: var(--color-ink); }
.link-index-foot { margin-top: var(--space-lg); }
/* Grille de liens courts (autres services) */
/* Autres services : des rangées à filets sur la grille, quatre colonnes (trois sous 60rem, deux sur téléphone),
   libellés à gauche ; la dernière rangée garde les colonnes, sans case étirée. */
.link-grid { list-style: none; padding: 0; margin: 0; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); column-gap: var(--gap-columns); border-top: var(--rule-hair) solid var(--color-rule-2); }
.link-grid li { display: flex; min-width: 0; margin: 0; border-bottom: var(--rule-hair) solid var(--color-rule); }
.link-grid a { display: flex; flex: 1; align-items: center; justify-content: flex-start; min-height: 64px; padding: var(--space-sm) var(--space-sm) var(--space-sm) 0; color: var(--color-ink); font-weight: 500; text-align: left; text-decoration: none; transition: color var(--dur-short) var(--ease-out); }
.link-grid a:focus-visible { outline-offset: -2px; }
/* Corps de texte d'une section en grille titre / corps */
.prose-body { max-width: 68ch; }
.prose-body > :first-child { margin-top: 0; }
.prose-body p a, .case-body p a { color: var(--color-ink); font-weight: 500; }
/* Tête empilée : le titre au-dessus de son contenu */
.section-head.is-stacked { display: block; }
.section-head.is-stacked h2 { max-width: 28ch; }
.link-index-foot a { color: var(--color-ink); font-weight: 500; }

/* ---------- Étapes (vraie séquence) ---------- */

.steps.is-prose li { font-size: var(--text-md); color: var(--color-ink-2); line-height: 1.6; }
/* La phrase continue après le gras : il reste en ligne. */
.steps.is-prose strong { font-weight: 500; color: var(--color-ink); }
/* L'engagement : un énoncé de section en Instrument Serif minuscule, son explication décalée dessous. */
.ink-pledge { margin-top: var(--space-3xl); display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); gap: var(--space-xl) var(--gap-columns); }
.ink-pledge strong { grid-column: 1 / span 9; min-width: 0; font: var(--display-weight) var(--text-display-s)/0.98 var(--font-display); letter-spacing: var(--tracking-display); text-transform: lowercase; text-wrap: balance; overflow-wrap: break-word; color: var(--color-ink); }
.ink-pledge p { grid-column: 7 / -1; margin: 0; padding-top: var(--space-md); border-top: var(--rule-hair) solid var(--color-rule-2); font-size: var(--text-lead); line-height: 1.5; color: var(--color-ink-2); }

/* ---------- Oui / non ---------- */
.split { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-2xl) var(--gap-columns); }
.split-card { color: var(--color-ink); }
.split-card h3 { margin-top: 0; font-size: var(--text-2xl); line-height: 1.05; margin-bottom: var(--space-md); }
.split-card ul { list-style: none; padding: 0; margin: 0; border-top: var(--rule-hair) solid var(--color-rule); }
.split-card li { position: relative; margin: 0; padding: var(--space-sm) 0 var(--space-sm) var(--space-lg); border-bottom: var(--rule-hair) solid var(--color-rule); color: var(--color-ink-2); }
.split-card.is-no { color: var(--color-ink); }
.split-card.is-no li::before {
    content: ""; position: absolute; left: var(--space-3xs); top: calc(var(--space-sm) + 0.5lh - 1px); width: 0.65em; height: 2px; background: var(--color-muted);
}

/* ---------- Preuves ---------- */
.proof a { color: var(--color-ink); font-weight: 500; }

.proofs.is-four { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.proofs.is-four .proof { border-top-color: var(--color-rule-2); }
.proofs.is-three { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.proofs.is-three .proof { border-top-color: var(--color-rule-2); }

/* Offre de lancement (présentation de la Suite) : pastille menthe et liste cochée sur la bande encre. */
.launch-badge { display: inline-block; margin-bottom: var(--space-md); padding: var(--space-3xs) var(--space-sm); border-radius: var(--radius-pill); font-size: var(--text-sm); font-weight: 500; background: none; color: var(--color-live); box-shadow: inset 0 0 0 var(--rule-hair) var(--color-live); font-family: var(--font-outlier); }
.launch-body > p { margin: 0 0 var(--space-lg); max-width: var(--measure); font-size: var(--text-lead); line-height: 1.5; }
.launch-list { list-style: none; margin: 0 0 var(--space-xl); padding: 0; border-top: var(--rule-hair) solid var(--color-rule); }
.launch-list li { position: relative; margin: 0; padding: var(--space-sm) 0 var(--space-sm) var(--space-xl); border-bottom: var(--rule-hair) solid var(--color-rule); color: var(--color-ink); }
.launch-list li::before { content: "✓" / ""; position: absolute; left: 0; color: var(--color-live); font-weight: 500; }
.guide-links-all { margin: var(--space-lg) 0 0; }
.guide-links-all a { color: var(--color-ink); font-weight: 500; }

/* Variante index (projets en production) */
.proofs.is-index { grid-template-columns: minmax(0, 1fr); gap: 0; border-top: var(--rule-hair) solid var(--color-rule-2); }
.is-index .proof {
    display: grid; grid-template-columns: minmax(0, 3fr) minmax(0, 4fr) minmax(0, 5fr); grid-template-areas: "kicker title text";
    gap: var(--space-xs) var(--gap-columns); align-items: baseline;
    padding: var(--space-xl) 0; border-top: 0; border-bottom: var(--rule-hair) solid var(--color-rule);
}
.is-index .proof h3 { grid-area: title; margin: 0; font-size: var(--text-title); letter-spacing: -0.02em; }
.is-index .proof p { grid-area: text; }
.is-index .proof-kicker { grid-area: kicker; }

/* ---------- FAQ ---------- */
.faq details p a { color: var(--color-ink); font-weight: 600; }
.faq-foot { margin: var(--space-lg) 0 0; font-size: var(--text-md); }
.faq-foot a { color: var(--color-ink); font-weight: 500; }

/* ---------- Appel final : pied d'appel (email, mentions) ---------- */
.cta-band-foot { grid-column: 1 / -1; display: flex; flex-wrap: wrap; justify-content: space-between; gap: var(--space-xs) var(--space-xl); padding-top: var(--space-lg); border-top: var(--rule-hair) solid var(--color-rule); }
.cta-band .cta-band-foot p { margin-top: 0; font-size: var(--text-sm); color: var(--color-ink-2); max-width: none; }
.cta-band-foot a { color: var(--color-ink); font-weight: 500; }

/* ---------- Offre et symptômes (pages service) ---------- */
.offer-box .price-amount { font-size: var(--text-3xl); font-variant-numeric: tabular-nums; }
.offer-box ul { list-style: none; padding: 0; margin: 0 0 var(--space-lg); border-top: 0; }
.offer-box li { position: relative; margin: 0; padding: var(--space-sm) 0 var(--space-sm) var(--space-lg); border-bottom: var(--rule-hair) solid var(--color-rule); color: var(--color-ink-2); font-size: var(--text-sm); line-height: 1.5; }
.offer-box .btn { width: 100%; }
.offer-box .btn + .btn { margin-top: var(--space-xs); }
.symptoms { list-style: none; display: block; margin: 0; padding: 0; border-top: var(--rule-hair) solid var(--color-rule-2); }
/* Une liste sans ordre : pas de numéros, chaque ligne commence sur son texte. */
.symptoms li {
    position: relative;
    margin: 0;
    padding: var(--space-lg) 0;
    border: 0;
    border-bottom: var(--rule-hair) solid var(--color-rule);
    border-radius: 0;
    background: none;
    font-size: var(--text-xl);
    line-height: 1.3;
    color: var(--color-ink);
    text-wrap: pretty;
}

/* ---------- Formulaires ---------- */
.form { display: grid; gap: var(--space-lg); }
.form-row { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-lg); }
.field { display: flex; flex-direction: column; gap: var(--space-xs); min-width: 0; border: 0; }
.field label, .field legend { font-weight: 400; font-size: var(--text-sm); color: var(--color-muted); }
.field .hint { font-size: var(--text-sm); color: var(--color-muted); }
.field input, .field select, .field textarea {
    font: inherit; font-size: var(--text-md); color: var(--color-ink); background: var(--color-paper-2);
    border: var(--rule-hair) solid var(--color-muted); border-radius: var(--radius-field);
    min-height: 48px; padding: var(--space-sm) var(--space-md); width: 100%;
    transition: background-color var(--dur-micro) var(--ease-out);
}
.field input:hover, .field select:hover, .field textarea:hover { background: var(--color-paper); }
.field textarea { min-height: 9rem; resize: vertical; line-height: 1.5; }
.field input:disabled, .field select:disabled, .field textarea:disabled { cursor: not-allowed; opacity: 0.6; background: var(--color-paper-2); color: var(--color-ink); }
.field [aria-invalid="true"] { border-color: var(--color-error); background: var(--color-red-wash); }
.field-error { color: var(--color-error); font-size: var(--text-sm); font-weight: 500; display: flex; gap: var(--space-xs); align-items: flex-start; line-height: 1.45; }
.field .check, .check { font-weight: 400; display: flex; gap: var(--space-sm); align-items: flex-start; font-size: var(--text-md); color: var(--color-ink-2); }
.check a { color: var(--color-ink); text-decoration: underline; text-underline-offset: 0.2em; }
.check input { width: 1.5rem; height: 1.5rem; min-height: 0; margin-top: 0; accent-color: var(--color-accent); flex-shrink: 0; cursor: pointer; }
.hp-field { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
.alert { padding: var(--space-md) var(--space-lg); border-radius: var(--radius-field); font-size: var(--text-md); }
.alert-error { background: var(--color-red-wash); color: var(--color-error); border: var(--rule-hair) solid var(--color-red-rule); }
.alert-ok { background: var(--color-paper-2); color: var(--color-ink); border: var(--rule-hair) solid var(--color-live); }
.form-card { background: var(--color-paper-2); border: var(--rule-hair) solid var(--color-rule); border-radius: var(--radius-card); padding: var(--space-xl); color: var(--color-ink); }
.contact-grid { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: var(--space-2xl); align-items: start; }
.form-card > .alert { margin-bottom: var(--space-lg); }
.form-note { font-size: var(--text-sm); color: var(--color-muted); margin: 0; }

/* Devis : engagements à gauche, formulaire à droite */
.devis-intro { position: sticky; top: calc(var(--header-h) + var(--space-lg)); }
.devis-trust { list-style: none; padding: var(--space-lg) 0 0; margin: 0; border-top: var(--rule-hair) solid var(--color-rule-2); display: grid; gap: var(--space-md); }
.devis-trust li { display: flex; gap: var(--space-sm); margin: 0; font-size: var(--text-md); color: var(--color-ink); }
.devis-trust li::before { content: ""; flex: none; width: 10px; height: var(--rule-hair); margin-top: 0.75em; border-radius: 0; background: var(--color-muted); }
.devis-mail { font-size: var(--text-md); margin: var(--space-xl) 0 0; }
.devis-mail a { color: var(--color-ink); font-weight: 500; }
.contact-aside { position: sticky; top: calc(var(--header-h) + var(--space-lg)); }
.contact-aside ol { margin-top: var(--space-md); }

/* ---------- Voix du thème ---------- */
h1, h2, h3, .main-nav, .menu-toggle, label, th, figcaption, .btn, .console-tab, .price-amount { text-transform: lowercase; }
h2 { max-width: 30ch; font-size: var(--text-display-s); line-height: 0.98; }
.wrap { width: 100%; max-width: var(--container); margin-inline: auto; padding-inline: var(--gutter); }
main p a, .footer-brand a { color: var(--color-ink); text-decoration-line: underline; text-decoration-color: var(--color-rule-2); transition: text-decoration-color var(--dur-micro) var(--ease-out), color var(--dur-micro) var(--ease-out); }
main p a:hover, .footer-brand a:hover { text-decoration-color: var(--color-accent); }
main p a:active { color: var(--color-accent); }

.skip-link {
    position: absolute; z-index: var(--z-toast);
    padding: var(--space-sm) var(--space-lg); border-radius: var(--radius-pill);
    background: var(--color-accent); color: var(--color-accent-ink); text-decoration: none;
    transform: translateY(-200%);
    left: max(var(--space-md), env(safe-area-inset-left));
    top: max(var(--space-md), env(safe-area-inset-top));
}
.skip-link:focus-visible { transform: none; outline-offset: 3px; }

/* ---------- Boutons : la paire du thème ---------- */
.btn {
    display: inline-flex; align-items: center; justify-content: center; gap: var(--space-xs);
    min-height: 48px; padding: 0 var(--space-lg); border: 0; border-radius: var(--radius-pill);
    font-family: var(--font-body); font-size: var(--text-md); font-weight: 500; line-height: 1; text-decoration: none; white-space: nowrap; cursor: pointer;
    transition: background-color var(--dur-micro) var(--ease-out), box-shadow var(--dur-micro) var(--ease-out), color var(--dur-micro) var(--ease-out), transform var(--dur-micro) var(--ease-out);
    position: relative;
    isolation: isolate;
    overflow: hidden;
    -webkit-tap-highlight-color: transparent;
}
.btn-primary { background: var(--color-accent); color: var(--color-accent-ink); }
.btn-primary:hover { background: color-mix(in oklch, var(--color-accent) 86%, var(--color-ink)); }
.btn-outline:hover { background: var(--color-paper-2); box-shadow: inset 0 0 0 var(--rule-hair) var(--color-muted); }
.btn:active { transform: translateY(1px); }

/* ---------- En-tête : une pilule posée au-dessus de la page ---------- */
/* Zones de sécurité (encoche, coins arrondis) : sans viewport-fit=cover, env() vaut 0 et le gabarit reste le même. */
.site-header {
    --header-top: max(var(--space-sm), env(safe-area-inset-top));
    position: sticky; top: 0; z-index: var(--z-sticky-nav);
    padding: var(--header-top) max(var(--gutter), env(safe-area-inset-right)) 0 max(var(--gutter), env(safe-area-inset-left));
    transition: transform var(--dur-short) var(--ease-out);
}
.header-inner {
    position: relative; max-width: calc(var(--container) - 2 * var(--gutter)); margin: 0 auto; height: var(--header-h);
    display: flex; align-items: center; gap: var(--space-lg); padding: 0 var(--space-xs) 0 var(--space-lg);
    background: var(--color-paper-2); border: var(--rule-hair) solid var(--color-rule); border-radius: var(--radius-pill);
    transition: box-shadow var(--dur-short) var(--ease-out), border-color var(--dur-short) var(--ease-out);
}
.site-header.is-scrolled .header-inner { border-color: var(--color-rule-2); box-shadow: var(--shadow-card); }
.logo {
    display: inline-flex; align-items: center; min-height: 44px; flex-shrink: 0;
    font-family: var(--font-display); font-size: var(--text-xl); line-height: 1; letter-spacing: var(--tracking-display);
    color: var(--color-ink); text-decoration: none;
}
.logo > span:not(.logo-mark) { color: var(--color-muted); }
.logo-mark { width: 10px; height: 10px; margin-right: var(--space-xs); border-radius: 2px; background: var(--color-accent); }

.main-nav { flex: 1; display: flex; align-items: center; gap: var(--space-3xs); min-width: 0; }
.main-nav a:first-child { margin-left: auto; }
.main-nav a {
    display: inline-flex; align-items: center; min-height: 44px; padding: 0 var(--space-sm); border-radius: var(--radius-pill);
    font-size: var(--text-sm); color: var(--color-muted); text-decoration: none; white-space: nowrap;
    transition: color var(--dur-micro) var(--ease-out), background-color var(--dur-micro) var(--ease-out);
}
.main-nav a:hover { color: var(--color-ink); background: var(--color-paper-3); }
.main-nav a:active { background: var(--color-rule); }
.main-nav a[aria-current] { color: var(--color-ink); }
.main-nav .nav-cta { margin-left: var(--space-sm); min-height: 48px; padding: 0 var(--space-lg); color: var(--color-ink); box-shadow: inset 0 0 0 var(--rule-hair) var(--color-rule-2); }
.main-nav .nav-cta:hover { background: var(--color-paper-3); box-shadow: inset 0 0 0 var(--rule-hair) var(--color-muted); }

.menu-toggle {
    display: none; margin-left: auto; align-items: center; gap: var(--space-xs); min-height: 44px; padding: 0 var(--space-md);
    font-size: var(--text-sm); color: var(--color-ink); background: transparent; border: 0; border-radius: var(--radius-pill);
    box-shadow: inset 0 0 0 var(--rule-hair) var(--color-rule-2); cursor: pointer;
    transition: background-color var(--dur-micro) var(--ease-out);
}
.menu-toggle:hover { background: var(--color-paper-3); }
.menu-toggle:active { background: var(--color-rule); }
.menu-toggle-bars { width: 16px; height: 10px; position: relative; }
.menu-toggle-bars::before, .menu-toggle-bars::after {
    content: ""; position: absolute; left: 0; right: 0; height: 1px; background: currentColor;
    transition: transform var(--dur-short) var(--ease-out);
}
.menu-toggle-bars::before { top: 2px; }
.menu-toggle-bars::after { bottom: 2px; }
.menu-toggle[aria-expanded="true"] .menu-toggle-bars::before { transform: translateY(3px) rotate(45deg); }
.menu-toggle[aria-expanded="true"] .menu-toggle-bars::after { transform: translateY(-3px) rotate(-45deg); }

/* Menu mobile : un panneau plein écran sur le fond, sous la pilule qui reste en place.
   Les liens en Instrument Serif, un filet entre chacun, le devis en pilule filaire au
   pouce. Ouverture en opacity/transform, liens décalés de 30 ms ; fermé, le panneau
   est en visibility: hidden, donc hors de la tabulation et de l'arbre d'accessibilité. */
@media (max-width: 68rem) {
    .js .menu-toggle { display: inline-flex; }
    .js .main-nav {
        position: fixed; inset: 0; z-index: -1; flex-direction: column; align-items: stretch; gap: 0;
        padding: calc(var(--header-top) + var(--header-h) + var(--space-xl)) max(var(--gutter), env(safe-area-inset-right)) max(var(--space-lg), env(safe-area-inset-bottom)) max(var(--gutter), env(safe-area-inset-left));
        background: var(--color-paper); overflow-y: auto; overscroll-behavior: contain;
        visibility: hidden; opacity: 0; transform: translateY(calc(-1 * var(--space-sm)));
        transition: opacity var(--dur-micro) var(--ease-in), transform var(--dur-micro) var(--ease-in), visibility 0s linear var(--dur-micro);
    }
    .js .main-nav.is-open {
        visibility: visible; opacity: 1; transform: none;
        transition: opacity var(--dur-short) var(--ease-out), transform var(--dur-long) var(--ease-out), visibility 0s;
    }
    .js .main-nav a {
        --i: 0; flex-shrink: 0; margin: 0; min-height: 64px; padding: 0; border-radius: 0; border-bottom: var(--rule-hair) solid var(--color-rule);
        font-family: var(--font-display); font-size: clamp(2rem, 5vw + 1rem, 2.75rem); line-height: 1; letter-spacing: var(--tracking-display);
        color: var(--color-ink-2); text-decoration: underline; text-decoration-color: transparent; text-decoration-thickness: var(--rule-hair); text-underline-offset: 0.16em;
        opacity: 0; transform: translateY(var(--space-sm));
        transition: opacity var(--dur-micro) var(--ease-in), transform var(--dur-micro) var(--ease-in), color var(--dur-micro) var(--ease-out), text-decoration-color var(--dur-micro) var(--ease-out);
    }
    .js .main-nav a:first-child { border-top: var(--rule-hair) solid var(--color-rule); }
    .js .main-nav a:not(.nav-cta) { position: relative; padding-right: 7rem; }
    /* Chaque rangée porte son chemin en relevé mono, comme une ligne de console ; texte de remplacement vide, le nom du lien ne change pas. */
    .js .main-nav a:not(.nav-cta)::after {
        content: attr(href) / ""; position: absolute; right: 0; top: 50%; transform: translateY(-50%);
        font: 400 var(--text-xs)/1 var(--font-outlier); letter-spacing: 0; text-transform: lowercase; color: var(--color-muted);
        transition: color var(--dur-micro) var(--ease-out);
    }
    .js .main-nav a:is(:hover, [aria-current])::after { color: var(--color-ink-2); }
    .js .main-nav a:nth-child(2) { --i: 1; } .js .main-nav a:nth-child(3) { --i: 2; } .js .main-nav a:nth-child(4) { --i: 3; }
    .js .main-nav a:nth-child(5) { --i: 4; } .js .main-nav a:nth-child(6) { --i: 5; } .js .main-nav a:nth-child(7) { --i: 6; }
    .js .main-nav.is-open a {
        opacity: 1; transform: none;
        transition: opacity var(--dur-long) var(--ease-out) calc(60ms + var(--i) * 30ms), transform var(--dur-long) var(--ease-out) calc(60ms + var(--i) * 30ms), color var(--dur-micro) var(--ease-out), text-decoration-color var(--dur-micro) var(--ease-out);
    }
    .js .main-nav a:hover { background: none; color: var(--color-ink); text-decoration-color: var(--color-rule-2); }
    .js .main-nav a:active { background: none; color: var(--color-accent); }
    .js .main-nav a[aria-current] { color: var(--color-ink); text-decoration-color: var(--color-accent); }
    .js .main-nav a:focus-visible { outline-offset: -2px; }
    .js .main-nav .nav-cta {
        margin: auto 0 0; min-height: 52px; justify-content: center; border: 0; border-radius: var(--radius-pill);
        font-family: var(--font-body); font-size: var(--text-md); font-weight: 500; letter-spacing: 0; text-decoration: none;
        background: var(--color-paper-2); color: var(--color-ink); box-shadow: inset 0 0 0 var(--rule-hair) var(--color-rule-2);
    }
    .js .main-nav .nav-cta:hover { background: var(--color-paper-3); color: var(--color-ink); box-shadow: inset 0 0 0 var(--rule-hair) var(--color-muted); }
    .js .main-nav .nav-cta:active { color: var(--color-ink); transform: translateY(1px); }
    .js .main-nav .nav-cta:focus-visible { outline-offset: 3px; }
    .js .main-nav a:nth-last-child(2) { margin-bottom: var(--space-xl); }
    .site-header.is-menu-open .header-inner { border-color: var(--color-rule-2); box-shadow: none; }
    /* Sans JavaScript : le logo, puis les liens à la ligne, dans un en-tête qui défile avec la page. */
    html:not(.js) .site-header { position: relative; }
    html:not(.js) .header-inner { height: auto; flex-wrap: wrap; padding: var(--space-xs) var(--space-sm) var(--space-sm); border-radius: var(--radius-card); }
    html:not(.js) .logo { padding-inline: var(--space-sm); }
    html:not(.js) .main-nav { flex: 1 1 100%; flex-wrap: wrap; }
    html:not(.js) .main-nav a:first-child { margin-left: 0; }
    html:not(.js) .main-nav .nav-cta { margin: var(--space-xs) 0 0; }
}
/* Paysage bas (667 × 375) : les liens sur deux colonnes pour tenir sans défiler (a11y9 : pas avec un texte agrandi, où les colonnes deviennent trop étroites pour les liens). */
@media (max-width: 68rem) and (max-height: 30rem) and (min-width: 34rem) {
    .js .main-nav { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); grid-auto-rows: min-content; column-gap: var(--gap-columns); align-content: start; padding-top: calc(var(--header-top) + var(--header-h) + var(--space-md)); }
    .js .main-nav a { min-height: 48px; font-size: var(--text-2xl); }
    .js .main-nav a:nth-child(2) { border-top: var(--rule-hair) solid var(--color-rule); }
    .js .main-nav a:nth-last-child(2) { margin-bottom: 0; }
    .js .main-nav .nav-cta { grid-column: 1 / -1; margin-top: var(--space-md); }
}
/* Écran tactile plus large qu'un téléphone (tablette, paysage) : les liens du pied passent aussi à 44 px. */
@media (pointer: coarse) {
    .footer-col:not(.footer-brand) a, .footer-inner a { min-height: 44px; }
}
@media (max-width: 68rem) and (prefers-reduced-motion: reduce) {
    .js .main-nav, .js .main-nav a, .js .main-nav.is-open a { transform: none; transition-delay: 0s; }
}

/* ---------- Hero : le texte à gauche, la console en scène ---------- */
.hero { padding: var(--space-xl) 0 var(--section-gap-s); }
.hero-news { margin-bottom: var(--space-2xl); }
.hero-news p { padding-bottom: var(--space-sm); border-bottom: var(--rule-hair) solid var(--color-rule); font-size: var(--text-sm); color: var(--color-muted); max-width: none; }
.hero-news strong { font-weight: 500; color: var(--color-ink-2); }
.hero-grid { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: var(--space-2xl); align-items: center; }
.hero-text { display: flex; flex-direction: column; align-items: flex-start; min-width: 0; }
.hero h1 { max-width: none; font-size: clamp(2.75rem, 3vw + 1.6rem, 4.75rem); line-height: 0.96; }
.hero-lead { margin-top: var(--space-lg); font-size: var(--text-lead); line-height: 1.5; color: var(--color-ink-2); max-width: 46ch; }
.hero-actions { margin-top: var(--space-xl); display: flex; flex-wrap: wrap; gap: var(--space-sm); }
.hero-facts {
    margin: var(--space-xl) 0 0; padding: var(--space-md) 0 0; list-style: none; align-self: stretch;
    display: grid; gap: var(--space-2xs); border-top: var(--rule-hair) solid var(--color-rule);
    font: 400 var(--text-sm)/1.5 var(--font-body); color: var(--color-muted); text-transform: lowercase;
}
.hero-visual { margin: 0; min-width: 0; }

@keyframes settle { from { opacity: 0; transform: translateY(8px); } }
@media (prefers-reduced-motion: no-preference) {
    /* Une seule entrée, d'un bloc, sur la grille du hero : pas de cascade. */
    .hero-grid { animation: settle 640ms var(--ease-out) both; }
    /* ---------- Apparition au défilement (un seul motif, visible sans JavaScript) ---------- */
    .js [data-reveal] { opacity: 0; transform: translateY(16px); transition: opacity var(--dur-long) var(--ease-out), transform var(--dur-long) var(--ease-out); }
    .js [data-reveal].is-in { opacity: 1; transform: none; }
}

/* ---------- Console d'intervention (signature) ---------- */
.console {
    background: var(--color-paper-2); border: var(--rule-hair) solid var(--color-rule); border-radius: var(--radius-card);
    overflow: hidden; container-type: inline-size;
    font: 400 var(--text-xs)/1.7 var(--font-outlier); color: var(--color-ink-2);
}
.console-bar { display: flex; align-items: center; padding: var(--space-xs); border-bottom: var(--rule-hair) solid var(--color-rule); }
/* Onglets : un scénario par onglet. Sans JavaScript, seul le premier s'affiche. */
.console-tabs { display: flex; flex-wrap: wrap; gap: var(--space-2xs); min-width: 0; }
html:not(.js) .console-tabs { display: none; }
.console-tab {
    display: inline-flex; align-items: center; min-height: 44px; padding: 0 var(--space-md);
    font: 400 var(--text-sm)/1 var(--font-body); color: var(--color-muted);
    background: transparent; border: 0; border-radius: var(--radius-pill); cursor: pointer;
    transition: color var(--dur-micro) var(--ease-out), background-color var(--dur-micro) var(--ease-out);
}
.console-tab:hover { color: var(--color-ink); background: var(--color-paper-3); }
.console-tab:active { background: var(--color-rule); }
.console-tab[aria-selected="true"] { color: var(--color-ink); background: var(--color-paper-3); box-shadow: inset 0 0 0 var(--rule-hair) var(--color-rule-2); }
.console-tab:focus-visible, .console-panel:focus-visible { outline: 2px solid var(--color-focus); outline-offset: -2px; }
.js .console-panels { display: grid; grid-template-columns: minmax(0, 1fr); }
/* Panneaux superposés : la console garde la hauteur du plus long, rien ne saute au changement d'onglet. */
.js .console-panel { grid-area: 1 / 1; min-width: 0; display: flex; flex-direction: column; }
.js .console-panel[hidden] { display: flex !important; visibility: hidden; }
.js .console-body { flex: 1; }
@container (max-width: 440px) {
    .console-tabs { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); width: 100%; }
}
.console-head { display: flex; align-items: center; gap: var(--space-sm); padding: var(--space-md) var(--space-lg) 0; color: var(--color-muted); }
.console-url { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.status-pill {
    display: inline-flex; align-items: center; padding: var(--space-3xs) var(--space-sm); border-radius: var(--radius-pill); white-space: nowrap;
    color: var(--color-error); box-shadow: inset 0 0 0 var(--rule-hair) color-mix(in oklch, var(--color-error) 50%, transparent);
    transition: color var(--dur-long) var(--ease-out), box-shadow var(--dur-long) var(--ease-out);
}
.console-panel.is-fixed .status-pill { color: var(--color-live); box-shadow: inset 0 0 0 var(--rule-hair) color-mix(in oklch, var(--color-live) 50%, transparent); }
/* La grille bleue du thème, sous les lignes du journal seulement. */
.console-body {
    padding: var(--space-lg); margin-top: var(--space-md);
    background-image: linear-gradient(var(--rule-blueprint) 1px, transparent 1px), linear-gradient(90deg, var(--rule-blueprint) 1px, transparent 1px);
    background-size: 48px 48px; background-position: -1px -1px;
    border-block: var(--rule-hair) solid var(--color-rule);
}
.console-line { display: flex; gap: var(--space-sm); white-space: pre-wrap; word-break: break-word; }
.console-line .t { color: var(--color-muted); flex-shrink: 0; min-width: 5ch; }
.console-line .ok { color: var(--color-live); }
.console-line .err { color: var(--color-error); }
.console-line .warn { color: var(--color-accent); }
.console-line .dim { color: var(--color-muted); }
.js .console-line { opacity: 0; transform: translateY(4px); transition: opacity var(--dur-long) var(--ease-out), transform var(--dur-long) var(--ease-out); }
.js .console-line.is-shown { opacity: 1; transform: none; }
.console-foot { display: flex; justify-content: space-between; gap: var(--space-md); flex-wrap: wrap; padding: var(--space-md) var(--space-lg); color: var(--color-muted); }
.console-caption { margin-top: var(--space-sm); font-size: var(--text-sm); color: var(--color-muted); }

/* ---------- Sections ---------- */
.section { padding-block: var(--section-gap-s); }
.section-head { margin-bottom: var(--space-2xl); }
.section-head.is-split { display: grid; grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); gap: var(--gap-columns); align-items: end; }
.section-head p { color: var(--color-ink-2); max-width: 46ch; }

/* ---------- Engagements : une rangée à filets, l'énoncé en tête puis les trois engagements ---------- */
.pledges-section { padding-bottom: var(--section-gap-s); }
.pledges { display: grid; grid-template-columns: minmax(0, 1.25fr) repeat(3, minmax(0, 1fr)); margin: 0; padding: 0; list-style: none; border-top: var(--rule-hair) solid var(--color-rule); }
.pledges li { min-width: 0; padding: var(--space-xl) var(--space-lg) 0; }
.pledges li:first-child { padding-left: 0; }
.pledges li:last-child { padding-right: 0; }
.pledges li + li { border-left: var(--rule-hair) solid var(--color-rule); }
.pledges h3 { font-size: var(--text-xl); line-height: 1.08; margin: 0 0 var(--space-sm); }
.pledges li:first-child h3 { max-width: 14ch; font-size: var(--text-2xl); line-height: 1.02; }
.pledges p { font-size: var(--text-sm); color: var(--color-ink-2); }

/* ---------- Services : un index en rangées ---------- */
.service-index { border-top: var(--rule-hair) solid var(--color-rule); }
.service-row {
    position: relative; display: grid; grid-template-columns: minmax(0, 3fr) minmax(0, 4fr) minmax(0, 4fr) minmax(0, 1fr);
    gap: var(--gap-columns); align-items: baseline; padding: var(--space-lg) var(--space-md);
    border-bottom: var(--rule-hair) solid var(--color-rule);
    transition: background-color var(--dur-short) var(--ease-out);
}
.service-code { font: 400 var(--text-xs)/1.5 var(--font-outlier); color: var(--color-muted); white-space: nowrap; transition: color var(--dur-short) var(--ease-out); }
.service-row h3 { font-size: var(--text-2xl); line-height: 1.02; }
/* Le titre glisse par son span : un h3 transformé deviendrait le bloc conteneur du a::after et la rangée ne serait plus cliquable. */
.service-row h3 a > span { display: inline-block; transition: transform var(--dur-short) var(--ease-out); }
.service-row h3 a, .wp-tile h3 a { color: var(--color-ink); text-decoration: none; }
/* Toute la rangée (ou la tuile) est cliquable, le lien reste le titre. */
.service-row h3 a::after, .wp-tile h3 a::after { content: ""; position: absolute; inset: 0; border-radius: inherit; }
.service-row h3 a:focus-visible, .wp-tile h3 a:focus-visible { outline: none; }
.service-row:has(a:focus-visible), .wp-tile:has(a:focus-visible) { outline: 2px solid var(--color-focus); outline-offset: -2px; }
.service-row p { font-size: var(--text-sm); color: var(--color-ink-2); }
.service-more { justify-self: end; font-size: var(--text-sm); color: var(--color-muted); white-space: nowrap; transition: color var(--dur-short) var(--ease-out); }
.service-row:hover { background: var(--color-paper-2); }
.service-row:hover h3 a > span { transform: translateX(var(--space-xs)); }
.service-row:hover .service-code, .wp-tile:hover .service-code { color: var(--color-accent); }
.service-row:hover .service-more, .wp-tile:hover .service-more { color: var(--color-ink); }
.service-row:active { background: var(--color-paper-3); }

/* ---------- WordPress : une mosaïque, les symptômes en grand ---------- */
.services-sub { margin-top: var(--section-gap-s); }
.wp-bento { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); gap: var(--gap-columns); }
.wp-tile {
    position: relative; grid-column: span 3; min-width: 0;
    display: grid; grid-template-columns: minmax(0, 1fr) auto; grid-template-rows: auto auto 1fr; align-items: end; gap: var(--space-sm) var(--space-md);
    padding: var(--space-lg); background: var(--color-paper-2); border: var(--rule-hair) solid var(--color-rule); border-radius: var(--radius-card);
    transition: border-color var(--dur-short) var(--ease-out), transform var(--dur-short) var(--ease-out);
}
.wp-tile > h3, .wp-tile > p { grid-column: 1 / -1; align-self: start; }
.wp-tile h3 { font-size: var(--text-2xl); line-height: 1.02; }
.wp-tile p { font-size: var(--text-sm); color: var(--color-ink-2); }
.wp-tile .service-code { font-size: var(--text-md); line-height: 1.25; color: var(--color-ink-2); }
.wp-tile.is-lead { grid-column: span 7; }
.wp-tile.is-lead h3 { font-size: var(--text-3xl); }
.wp-tile.is-lead p { font-size: var(--text-md); max-width: 46ch; }
/* Les agences : à côté de la grande tuile, sur toute sa hauteur, un puits ouvert sur le fond. */
.wp-tile.is-agency { grid-column: span 5; background: var(--color-paper); }
.wp-tile:hover { border-color: var(--color-rule-2); transform: translateY(-2px); }
.wp-tile:active { transform: none; }

/* ---------- Pourquoi : bande, titre fixe à gauche ---------- */
.band { background: var(--color-paper-2); color: var(--color-ink); border-block: var(--rule-hair) solid var(--color-rule); }
.faq-split { display: grid; grid-template-columns: minmax(0, 4fr) minmax(0, 8fr); gap: var(--gap-columns); align-items: start; }
.pane-sticky { position: sticky; top: calc(var(--header-h) + var(--space-2xl)); margin-bottom: 0; }
.proofs { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-2xl) var(--gap-columns); }
.proof { padding-top: var(--space-lg); border-top: var(--rule-hair) solid var(--color-rule-2); min-width: 0; }
.proof h3 { font-size: var(--text-2xl); line-height: 1.02; margin-bottom: var(--space-sm); }
.proof p { color: var(--color-ink-2); }

/* ---------- Tarifs : la fiche de prix, un puits à filet, une colonne par formule ----------
   Les filets entre colonnes et entre rangées sont l'espace de 1 px laissé entre les cellules :
   le fond du puits (couleur de filet) y paraît. Ni ombre, ni carte soulevée. */
.pricing {
    display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--rule-hair); align-items: stretch;
    background: var(--color-rule); border: var(--rule-hair) solid var(--color-rule); border-radius: var(--radius-card); overflow: clip;
}
.price-card {
    position: relative; min-width: 0; display: flex; flex-direction: column; align-items: flex-start; gap: var(--space-sm);
    padding: var(--space-xl); background: var(--color-paper-2); color: var(--color-ink);
}
/* La formule mise en avant : un filet laiton de 1 px en tête de colonne, rien d'autre. */
.price-card.is-featured { box-shadow: inset 0 var(--rule-hair) 0 var(--color-accent); }
.price-card h3 { font-size: var(--text-2xl); }
/* Le drapeau est une étiquette : Geist, un cran sous le texte, minuscules, encre atténuée, posé avec le nom. */
.price-flag { font: 400 var(--text-sm)/1.5 var(--font-body); color: var(--color-muted); text-transform: lowercase; white-space: nowrap; }
.price-amount { margin-top: var(--space-lg); font-family: var(--font-display); font-size: var(--text-display); line-height: 0.9; letter-spacing: var(--tracking-display); color: var(--color-ink); }
.price-amount small { font: 400 var(--text-xl)/1 var(--font-outlier); color: var(--color-muted); }
/* « sur devis » au corps des montants : une seule rangée de chiffres, une seule ligne de base. */
.pricing .price-amount:not(:has(small)) { text-wrap: balance; }
.price-unit { font: 400 var(--text-xs)/1.5 var(--font-outlier); color: var(--color-muted); }
.price-card p { margin-top: var(--space-sm); font-size: var(--text-md); color: var(--color-ink-2); }
/* Le détail en rangées à filet, sans marque devant la ligne. */
.price-card ul { margin: var(--space-sm) 0 var(--space-lg); padding: 0; list-style: none; display: grid; align-self: stretch; border-top: var(--rule-hair) solid var(--color-rule); font-size: var(--text-sm); color: var(--color-ink-2); }
.price-card li { padding: var(--space-xs) 0; line-height: 1.45; }
.price-card li + li { border-top: var(--rule-hair) solid var(--color-rule); }
.price-card .btn { margin-top: auto; }
.pricing-note { margin-top: var(--space-xl); max-width: 80ch; font-size: var(--text-sm); color: var(--color-muted); }
.pricing-note strong { font-weight: 500; color: var(--color-ink-2); }

/* ---------- Méthode : un chemin en quatre étapes ---------- */
.path { padding: var(--space-2xl) var(--space-xl); background: var(--color-paper-2); border: var(--rule-hair) solid var(--color-rule); border-radius: var(--radius-card); }
.steps { position: relative; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--gap-columns); margin: 0; padding: 0; list-style: none; counter-reset: step; }
/* Le chemin : un filet gris, puis le trajet suivi, en laiton. */
.steps::before, .steps::after { content: ""; position: absolute; left: 24px; right: 24px; top: 24px; height: 1px; background: var(--color-rule-2); }
.steps::after { background: var(--color-accent); transform-origin: left; }
.steps li { position: relative; min-width: 0; counter-increment: step; padding-top: calc(48px + var(--space-lg)); }
.steps li::before {
    content: counter(step, decimal-leading-zero); position: absolute; top: 0; left: 0; z-index: var(--z-base);
    display: grid; place-items: center; width: 48px; height: 48px; border-radius: 50%;
    background: var(--color-paper-2); box-shadow: inset 0 0 0 var(--rule-hair) var(--color-accent);
    font: 400 var(--text-xs)/1 var(--font-body); font-variant-numeric: tabular-nums; color: var(--color-muted);
}
.steps h3 { font-size: var(--text-2xl); line-height: 1.02; margin-bottom: var(--space-sm); }
.steps p { font-size: var(--text-sm); color: var(--color-ink-2); }

/* Le chemin de la méthode se trace une fois, pendant que le chapitre monte dans l'écran, sans épinglage :
   il commence quand le chapitre est entier à l'écran et finit quand il approche du haut.
   Sans support, en mouvement réduit ou sur écran étroit : l'état final ci-dessus. */
@keyframes path-draw { from { transform: scaleX(0); } }
@keyframes node-light { from { opacity: 0.35; transform: scale(0.7); } }
@supports (animation-timeline: view()) {
    @media (prefers-reduced-motion: no-preference) and (min-width: 60rem) {
        .method { view-timeline: --chapter block; }
        .method .steps::after { animation: path-draw linear both; animation-timeline: --chapter; animation-range: contain 0% contain 65%; }
        .method .steps li::before { animation: node-light linear both; animation-timeline: --chapter; }
        .method .steps li:nth-child(1)::before { animation-range: contain 0% contain 8%; }
        .method .steps li:nth-child(2)::before { animation-range: contain 19% contain 27%; }
        .method .steps li:nth-child(3)::before { animation-range: contain 38% contain 46%; }
        .method .steps li:nth-child(4)::before { animation-range: contain 57% contain 65%; }
    }
}

/* ---------- Réalisations : quatre tuiles ---------- */
.proof-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--gap-columns); }
.proof-tile { min-width: 0; display: flex; flex-direction: column; gap: var(--space-sm); padding: var(--space-xl); border-radius: var(--radius-card); box-shadow: inset 0 0 0 var(--rule-hair) var(--color-rule); }
.proof-tile h3 { font-size: var(--text-2xl); line-height: 1.02; }
.proof-tile p { color: var(--color-ink-2); }
.proof-kicker { margin-top: auto; padding-top: var(--space-md); border-top: var(--rule-hair) solid var(--color-rule); font: 400 var(--text-xs)/1.5 var(--font-body); font-variant-numeric: tabular-nums; color: var(--color-muted); }

/* ---------- Questions fréquentes ---------- */
.faq { border-top: var(--rule-hair) solid var(--color-rule); }
.faq details { border-bottom: var(--rule-hair) solid var(--color-rule); }
.faq summary {
    display: flex; justify-content: space-between; align-items: center; gap: var(--space-lg); min-height: 64px; padding: var(--space-md) 0;
    font-size: var(--text-lg); line-height: 1.35; color: var(--color-ink); cursor: pointer; list-style: none;
    transition: color var(--dur-micro) var(--ease-out);
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
    content: ""; flex-shrink: 0; width: 10px; height: 10px; margin-right: var(--space-2xs);
    border-right: var(--rule-hair) solid currentColor; border-bottom: var(--rule-hair) solid currentColor;
    transform: translateY(-3px) rotate(45deg); transition: transform var(--dur-short) var(--ease-out);
}
.faq details[open] summary::after { transform: translateY(2px) rotate(-135deg); }
.faq summary:hover { color: var(--color-accent); }
.faq summary:focus-visible { outline: 2px solid var(--color-focus); outline-offset: 4px; }
.faq details p { padding-bottom: var(--space-lg); color: var(--color-ink-2); }
.guide-links { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--gap-columns); }
.guide-link {
    min-width: 0; min-height: 180px; display: flex; flex-direction: column; justify-content: space-between; gap: var(--space-lg);
    padding: var(--space-lg); border-radius: var(--radius-card); box-shadow: inset 0 0 0 var(--rule-hair) var(--color-rule); text-decoration: none;
    transition: background-color var(--dur-short) var(--ease-out), box-shadow var(--dur-short) var(--ease-out);
}
.guide-link strong { font-size: var(--text-lg); font-weight: 500; line-height: 1.3; color: var(--color-ink); }
.guide-link span { font: 400 var(--text-sm)/1.5 var(--font-body); color: var(--color-muted); text-transform: lowercase; }
.guide-link:hover { background: var(--color-paper-2); box-shadow: inset 0 0 0 var(--rule-hair) var(--color-rule-2); }
.guide-link:active { background: var(--color-paper-3); }

/* ---------- Appel final : sans puits, la question, sa réponse, puis le bouton, juste au-dessus du mât ---------- */
.cta-band { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-xl) var(--gap-columns); align-items: start; justify-items: start; color: var(--color-ink); }
.cta-band > div:first-child { min-width: 0; }
.cta-band h2 { margin: 0; font-size: var(--text-display-s); line-height: 0.96; max-width: 18ch; text-wrap: balance; overflow-wrap: break-word; }
.cta-band p { margin-top: var(--space-lg); font-size: var(--text-lead); line-height: 1.5; color: var(--color-ink-2); max-width: 52ch; }
.cta-band-actions { justify-self: start; }
.cta-band-foot { justify-self: stretch; }

/* ---------- Pied de page : le nom en grand, puis le plan du site ---------- */
.site-footer { border-top: var(--rule-hair) solid var(--color-rule); padding-top: var(--space-3xl); }
.footer-cols { max-width: var(--container); margin: 0 auto; padding: 0 var(--gutter); display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-2xl) var(--gap-columns); }
.footer-brand { grid-column: 1 / -1; display: grid; grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); gap: var(--space-lg) var(--gap-columns); align-items: end; padding-bottom: var(--space-2xl); border-bottom: var(--rule-hair) solid var(--color-rule); }
.footer-brand .logo { grid-column: 1 / -1; font-size: clamp(4.5rem, 17vw, 15rem); line-height: 0.8; min-height: 0; padding-bottom: 0.16em; }
.footer-brand .logo-mark { width: 0.12em; height: 0.12em; margin-right: 0.08em; border-radius: 0.02em; }
.footer-brand p { color: var(--color-ink-2); max-width: 56ch; }
.footer-feed { justify-self: start; display: inline-flex; align-items: center; min-height: 44px; font-size: var(--text-sm); }
.footer-col h2 { max-width: none; margin-bottom: var(--space-md); font-family: var(--font-body); font-size: var(--text-sm); font-weight: 400; letter-spacing: 0; line-height: 1.4; color: var(--color-muted); }
.footer-col:not(.footer-brand) { display: flex; flex-direction: column; align-items: flex-start; }
.footer-col:not(.footer-brand) a { display: inline-flex; align-items: center; min-height: 32px; color: var(--color-ink-2); text-decoration: none; transition: color var(--dur-micro) var(--ease-out); }
.footer-col:not(.footer-brand) a:hover { color: var(--color-accent); }
.site-footer a:focus-visible { color: var(--color-ink); outline-offset: 2px; border-radius: 2px; }
.footer-col:not(.footer-brand) a:active { color: var(--color-ink); }
.footer-inner {
    max-width: var(--container); margin: var(--space-3xl) auto 0; padding: var(--space-lg) var(--gutter) max(var(--space-lg), env(safe-area-inset-bottom));
    display: flex; justify-content: space-between; flex-wrap: wrap; gap: var(--space-sm) var(--space-lg);
    border-top: var(--rule-hair) solid var(--color-rule); font-size: var(--text-xs); color: var(--color-muted);
}
.footer-inner span:last-child { display: flex; flex-wrap: wrap; gap: var(--space-md); }
.footer-inner a { color: var(--color-muted); text-decoration: none; display: inline-flex; align-items: center; min-height: 32px; transition: color var(--dur-micro) var(--ease-out); }
.footer-inner a:hover { color: var(--color-ink); }

/* ---------- Écrans intermédiaires : les titres des rangées et des tuiles restent sur une ligne ---------- */
@media (max-width: 75rem) {
    .service-row h3, .wp-tile h3 { font-size: var(--text-xl); }
    .wp-tile.is-lead h3 { font-size: var(--text-2xl); }
    /* Adaptatif des pages intérieures (repris de site.css, sans le chrome). */
    .pricing.is-four, .proofs.is-four, .proofs.is-three, .gh-cards, .guide-cards, .about-proofs { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* ---------- Écrans moyens ---------- */
@media (max-width: 60rem) {
    .hero-grid { grid-template-columns: minmax(0, 1fr); gap: var(--space-2xl); }
    .section-head.is-split { grid-template-columns: minmax(0, 1fr); gap: var(--space-md); }
    .service-row { grid-template-columns: minmax(0, 1fr) auto; gap: var(--space-xs) var(--space-md); padding-inline: 0; }
    .service-row h3, .service-row p { grid-column: 1 / -1; }
    .service-row .service-more { grid-row: 1; grid-column: 2; }
    .service-row:hover { background: none; }
    .wp-bento { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .wp-tile.is-lead, .wp-tile.is-agency { grid-column: 1 / -1; }
    .faq-split { grid-template-columns: minmax(0, 1fr); }
    .pane-sticky { position: static; margin-bottom: var(--space-xl); }
    .pricing { grid-template-columns: minmax(0, 1fr); }
    .path { padding: var(--space-xl) var(--space-lg); }
    .steps { grid-template-columns: minmax(0, 1fr); gap: var(--space-xl); }
    .steps::before, .steps::after { left: 24px; right: auto; top: 24px; bottom: 24px; width: 1px; height: auto; }
    .steps li { padding: var(--space-sm) 0 0 calc(48px + var(--space-lg)); }
    .guide-links { grid-template-columns: minmax(0, 1fr); }
    .guide-link { min-height: 0; }
    /* Pied : les trois groupes côte à côte ; sur deux colonnes, le dernier restait seul sur sa rangée. */
    .footer-cols { grid-template-columns: repeat(3, minmax(0, 1fr)); }
    .footer-brand { grid-template-columns: minmax(0, 1fr); }
  .vp-layout, .cases-intro, .author-scope, .article-layout { grid-template-columns: minmax(0, 1fr); }
  .article-section { padding-top: var(--space-2xl); }
  .article-rail > :last-child { position: static; max-height: none; overflow: visible; }
  .glo-side { position: static; }
  .about-statement { grid-template-columns: minmax(0, 1fr); }
  .about-statement .prose-body { grid-column: 1; }
  .page-content.is-doc { display: block; }
  .tool-row { grid-template-columns: minmax(0, 1fr); }
  .page-content.is-doc > h2 { position: static; max-width: none; }
  .page-content.is-doc > h2 + * { margin-top: var(--space-md); padding-top: 0; border-top: 0; }
  .page-content.is-doc > h2 + :is(p, ul, ol) { padding-right: 0; }
  .service-hero-grid, .contact-grid, .wrap.is-split { grid-template-columns: minmax(0, 1fr); }
  .devis-intro, .contact-aside { position: static; }
  .is-index .proof { grid-template-columns: minmax(0, 1fr); grid-template-areas: "title" "kicker" "text"; }
  .pricing.is-four { grid-template-columns: minmax(0, 1fr); max-width: 34rem; }
  .maint, .scope-notes, .ink-pledge, .maint-list { grid-template-columns: minmax(0, 1fr); }
}

/* ---------- Mobiles ---------- */
@media (max-width: 40rem) {
    .hero { padding-top: var(--space-lg); }
    .hero-news { margin-bottom: var(--space-xl); }
    .hero h1 { font-size: clamp(2.5rem, 9vw + 0.5rem, 3.25rem); }
    .proofs, .proof-grid, .wp-bento { grid-template-columns: minmax(0, 1fr); }
    .proof-tile { padding: var(--space-lg); }
    .faq summary { font-size: var(--text-md); }
    /* Pied : chaque rubrique sur deux colonnes de liens, cibles de 44 px, la page reste courte. */
    .site-footer { padding-top: var(--space-2xl); }
    .footer-cols { grid-template-columns: minmax(0, 1fr); row-gap: var(--space-xl); }
    .footer-brand { padding-bottom: var(--space-xl); }
    .footer-col:not(.footer-brand) { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: var(--space-md); align-items: stretch; }
    .footer-col h2 { grid-column: 1 / -1; margin-bottom: var(--space-xs); padding-bottom: var(--space-xs); border-bottom: var(--rule-hair) solid var(--color-rule); }
    .footer-col:not(.footer-brand) a { min-height: 44px; padding-block: var(--space-2xs); line-height: 1.3; }
    .footer-inner { flex-direction: column; margin-top: var(--space-2xl); }
    .footer-inner span:last-child { gap: 0 var(--space-lg); }
    .footer-inner a { min-height: 44px; }
}

/* ==========================================================================
   Pages intérieures dans la voix Lumen : en-têtes sans aplat, une bande
   paper-2 au plus par page (section-ink), filets à la place des fonds,
   intertitres des textes longs en casse normale pour la lecture.
   ========================================================================== */

/* En-têtes de page : le titre en grand, sur le fond, un filet dessous. */
.page-hero, .service-hero { background: none; border-bottom: var(--rule-hair) solid var(--color-rule); }
:is(.page-hero, .service-hero) + .section { padding-top: var(--space-2xl); }
main > :is(.page-hero, .service-hero):last-child { padding-bottom: var(--space-xl); }
/* La marge haute du premier titre traversait la section : le rythme vient du padding seul. */
.section > .wrap > :first-child, .section-head > :first-child { margin-top: 0; }
:is(.page-hero, .service-hero) + .section-paper { border-top: 0; }
.page-hero h1, .service-hero h1 { font-size: var(--text-display); line-height: 0.98; letter-spacing: var(--tracking-display); max-width: 18ch; }
.page-hero.article-hero h1 { font-size: var(--text-display-s); max-width: 24ch; }
.page-content > h1, .page-content header h1, .page-content.is-doc > h1 { font-size: var(--text-display); line-height: 0.98; }
/* Fil d'Ariane : une étiquette (Geist, un cran sous le texte, minuscules), les étapes en muted soulignées d'un filet, la page courante en ink-2. */
.breadcrumb a:hover { color: var(--color-ink); text-decoration-color: var(--color-accent); }
.breadcrumb a:focus-visible { color: var(--color-ink); border-radius: 2px; }
.breadcrumb > span:last-child:not(:has(a)) { color: var(--color-ink-2); }
/* Une seule entrée : le hero arrive d'un bloc, titre, chapô et fiche ensemble, sans cascade. */
.service-hero-grid, .page-content > h1, .page-content > h1 + p { animation: none; }
@media (prefers-reduced-motion: no-preference) {
  .service-hero-grid, .page-content > h1, .page-content > h1 + p { animation: settle 640ms var(--ease-out) both; }
}

/* Sections : le papier devient un filet, l'encre devient la bande. */
.section-paper { color: var(--color-ink); background: none; border-top: var(--rule-hair) solid var(--color-rule); }
.section-ink h2, .section-ink h3, .section-ink strong { color: var(--color-ink); }
.section-ink p { color: var(--color-ink-2); }
.section-ink { background: var(--color-paper-2); color: var(--color-ink); border-block: var(--rule-hair) solid var(--color-rule); }
.section-ink :where(p, li) > a:not(.btn) { color: var(--color-ink); }
.section-head.is-split h2, .wrap.is-split .section-head h2 { margin-top: 0; }

/* Liens courants : encre soulignée d'un filet, laiton au survol. */
:is(.page-content, .prose-body, .case-body, .faq-item, .changelog, .glo-related, .about-services, .about-note, .about-proofs, .about-links, .article-meta, .case-meta, .res-item) a:not(.btn, .article-cat),
.contact-email, .vp-more {
  color: var(--color-ink); text-decoration-line: underline; text-decoration-color: var(--color-rule-2);
  text-underline-offset: 0.2em; font-weight: 500;
  transition: color var(--dur-micro) var(--ease-out), text-decoration-color var(--dur-micro) var(--ease-out);
}
:is(.page-content, .prose-body, .case-body, .faq-item, .changelog, .glo-related, .about-services, .about-note, .about-proofs, .about-links, .article-meta, .case-meta, .res-item) a:not(.btn, .article-cat):hover,
.contact-email:hover, .vp-more:hover, .gh-entry a:hover, .gh-card h2 a:hover, .glo-anchor:hover { color: var(--color-accent); text-decoration-color: var(--color-accent); }
.res-item h3 a, .about-services li > a:first-child { font-weight: inherit; }

/* Relevés : en mono, en gris, jamais en couleur. */
.changelog time { font-family: var(--font-outlier); font-weight: 400; color: var(--color-muted); }
.changelog time { font-family: var(--font-body); font-size: inherit; }
/* « À lire en premier… » est une phrase, pas une mesure : Geist atténué. */
.res-when { display: block; font-size: var(--text-xs); color: var(--color-muted); }

/* Textes longs : intertitres en casse normale, en serif, pour la lecture. */
:is(.article-body, .page-content.is-doc, .prose-body, .case-body) :is(h2, h3, h4),
.faq-item h3, .glo-term h2, .article-body th, .article-figure figcaption, .vp-table th, .takeaways :is(h2, h3) { text-transform: none; }
.article-body h2 { font-size: var(--text-2xl); line-height: 1.1; letter-spacing: var(--tracking-display); position: relative; max-width: var(--measure); margin: var(--space-3xl) 0 var(--space-lg); padding-top: var(--space-lg); border-top: var(--rule-hair) solid var(--color-rule); text-wrap: balance; scroll-margin-top: calc(var(--header-h) + var(--space-xl)); }
.article-body h3 { font-size: var(--text-xl); margin: var(--space-2xl) 0 var(--space-sm); line-height: 1.2; text-wrap: balance; scroll-margin-top: calc(var(--header-h) + var(--space-xl)); }

/* Schémas des articles (config/portal_articles.php), dessinés avec l'ancienne palette claire :
   chaque couleur d'origine est ramenée à un jeton, sans toucher au contenu. */
.article-figure svg [fill="#fff"], .article-figure svg [fill="#ffffff"], .article-figure svg [fill="#fbfdfc"], .article-figure svg [fill="#eef2f0"], .article-figure svg [fill="#e8f5ee"] { fill: var(--color-paper-2); }
.article-figure svg [fill="#fff8e6"] { fill: var(--color-paper-3); }
.article-figure svg [fill="#1a2b22"], .article-figure svg [fill="#12241b"] { fill: var(--color-paper); }
.article-figure svg [fill="#1a1a1a"] { fill: var(--color-ink); }
.article-figure svg [fill="#555"], .article-figure svg [fill="#555555"], .article-figure svg [fill="#777"], .article-figure svg [fill="#999"] { fill: var(--color-muted); }
.article-figure svg [stroke="#555"] { stroke: var(--color-muted); }
.article-figure svg [fill="#dde4e0"] { fill: var(--color-rule); }
.article-figure svg [stroke="#dde4e0"], .article-figure svg [stroke="#c9d6cf"] { stroke: var(--color-rule); }
.article-figure svg [fill="#d9d9d9"] { fill: var(--color-rule-2); }
.article-figure svg [stroke="#b8dcc8"], .article-figure svg [stroke="#9bb3a8"] { stroke: var(--color-rule-2); }
.article-figure svg [fill="#1a7a4a"] { fill: var(--color-live); }
.article-figure svg [stroke="#1a7a4a"] { stroke: var(--color-live); }
.article-figure svg [fill="#e0912f"], .article-figure svg [fill="#8a6508"], .article-figure svg [fill="#b8860b"] { fill: var(--color-accent); }
.article-figure svg [stroke="#b8860b"] { stroke: var(--color-accent); }
.article-figure svg [fill="#c0392b"] { fill: var(--color-error); }
.article-figure svg [stroke="#c0392b"] { stroke: var(--color-error); }
.article-figure svg [fill="#fdecea"] { fill: var(--color-red-wash); }
.article-figure svg [stroke="#e5b5ae"] { stroke: var(--color-red-rule); }
/* Texte des schémas : blanc sur aplat vert, clair ou vert sur panneau de code sombre. */
.article-figure svg text:is([fill="#fff"], [fill="#ffffff"], [fill="#cde9d9"]) { fill: var(--color-accent-ink); }
.article-figure svg text[fill="#e8f5ee"] { fill: var(--color-ink-2); }
.article-figure svg text[fill="#9ad3b0"] { fill: var(--color-live); }

/* Séparateur de métadonnées : un filet vertical, pas une pastille. */
.article-meta .dot { width: var(--rule-hair); height: 1em; border-radius: 0; background: var(--color-rule-2); }

/* Pastilles et puces. */
.cat-nav a.is-active { color: var(--color-ink); background: var(--color-paper-2); border-color: var(--color-muted); }
.offer-box li::before, .split-card.is-yes li::before {
  content: ""; position: absolute; left: var(--space-3xs); width: 0.6em; height: 0.32em;
  border-left: 2px solid var(--color-ink-2); border-bottom: 2px solid var(--color-ink-2); transform: rotate(-45deg);
}

/* Boutons des pages intérieures, dans les deux styles de l'accueil. */
.btn-dark:hover { background: var(--color-paper-3); color: var(--color-ink); box-shadow: inset 0 0 0 var(--rule-hair) var(--color-muted); }
.btn-light:hover, .section-ink .btn-outline:hover { background: var(--color-paper-3); color: var(--color-ink); box-shadow: inset 0 0 0 var(--rule-hair) var(--color-muted); }

/* Champs de formulaire sur fond sombre. */
.field :is(input, select, textarea) { background: var(--color-paper); color: var(--color-ink); border-color: var(--color-muted); }
.field .check, .field .label { text-transform: none; }
.field :is(input, select, textarea):hover { background: var(--color-paper); border-color: var(--color-ink-2); }
.field ::placeholder { color: var(--color-muted); }

@media (max-width: 40rem) {
  .page-hero, .service-hero { padding: var(--space-2xl) 0 var(--space-xl); }
  .page-hero h1, .service-hero h1, .page-content > h1, .page-content.is-doc > h1 { font-size: var(--text-display-s); }
  .split, .proofs.is-four, .proofs.is-three, .symptoms, .form-row, .page-content :is(.topic-grid, .tools-list), .gh-cards, .gh-letter, .guide-cards, .about-proofs { grid-template-columns: minmax(0, 1fr); }
  .dataset dl, .changelog li, .guide-nav { grid-template-columns: minmax(0, 1fr); }
  .dataset dl { gap: var(--space-2xs); }
  .dataset dd { margin-bottom: var(--space-xs); }
  .guide-nav .gn-next { text-align: left; }
  .glo-row { grid-template-columns: minmax(0, 1fr); gap: var(--space-3xs); }
  .page-content { padding: var(--space-xl) var(--gutter) var(--space-2xl); }
  .split-card, .offer-box, .form-card { padding: var(--space-lg); }
  .page-content .cta-block { padding: var(--space-lg); }
  .article-body code { overflow-wrap: anywhere; }
}

/* Très petits écrans : les libellés des boutons restent sur une ligne. */
@media (max-width: 24rem) {
  .btn { font-size: var(--text-sm); padding-inline: var(--space-md); }
}

/* Textes longs : le paragraphe porte lui-même la mesure. */
.page-content.is-doc > h2 + :is(p, ul, ol) { max-width: var(--measure); padding-right: 0; }

/* ==========================================================================
   Passe visuelle : les pages intérieures prennent la tenue de l'accueil.
   Mêmes compositions (index en rangées, diptyque à titre fixe, chemin dans
   un puits, bande paper-2), même relevé en mono, même révélation.
   ========================================================================== */

/* ---------- Pages service : l'offre en carte de tarif, sur la grille ---------- */
.offer-box { border-radius: var(--radius-card); color: var(--color-ink); background: var(--color-paper-2); border: var(--rule-hair) solid var(--color-rule); box-shadow: none; padding: var(--space-xl); }
.offer-figure {
    margin: calc(-1 * var(--space-xl)) calc(-1 * var(--space-xl)) var(--space-lg); padding: var(--space-xl);
    border-bottom: var(--rule-hair) solid var(--color-rule); border-radius: var(--radius-card) var(--radius-card) 0 0; background: var(--color-paper-3);
}
.offer-figure .price-amount { margin-top: var(--space-md); font-size: var(--text-display); line-height: 0.9; }
.offer-figure .price-unit { display: block; margin-top: var(--space-xs); }
.offer-box li::before { top: calc(var(--space-sm) + 0.45em); border-color: var(--color-ink-2); }
.offer-box li strong { color: var(--color-ink); font-weight: 500; text-transform: lowercase; }

/* Cas réel : la bande de la page, resserrée ; titre (5 colonnes) et récit (7) sur la même rangée,
   le chapeau du cas en grand sur toute la largeur du récit, la suite en deux colonnes dessous. */
@media (max-width: 40rem) {
    .offer-figure { margin: calc(-1 * var(--space-lg)) calc(-1 * var(--space-lg)) var(--space-lg); padding: var(--space-lg); }
    .symptoms li { padding: var(--space-md) 0; font-size: var(--text-lg); }
    .offer-box { padding: var(--space-lg); }
}

/* Autres services : Geist 500, la casse du nom comme au pied de page (la serif reste aux titres, elle maigrit à ce corps). */
main .link-grid a { font-family: var(--font-body); font-size: var(--text-lg); font-weight: 500; line-height: 1.25; text-decoration: none; color: var(--color-ink-2); }
main .link-grid a:hover { color: var(--color-ink); }
main .link-grid li { transition: border-color var(--dur-short) var(--ease-out); }
main .link-grid li:hover { border-bottom-color: var(--color-accent); }

/* ---------- Bandeau des pages : le titre au bord, le chapeau décalé sous un filet ---------- */
/* Le titre prend dix colonnes à la taille du hero ; ce qui le suit part de la septième
   colonne, ouvert par un filet : la page s'annonce comme une fiche, pas comme un texte centré. */
@media (min-width: 60.0625rem) {
    .page-hero:not(.article-hero, .thanks-hero) > .wrap:not(.author-hero) { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: var(--gap-columns); }
    .page-hero:not(.article-hero, .thanks-hero) > .wrap:not(.author-hero) > * { grid-column: 7 / -1; min-width: 0; }
    .page-hero:not(.article-hero, .thanks-hero) > .wrap:not(.author-hero) > .breadcrumb { grid-column: 1 / -1; }
    .page-hero:not(.article-hero, .thanks-hero) > .wrap:not(.author-hero) > h1 { grid-column: 1 / span 11; max-width: 22ch; margin-bottom: var(--space-xl); }
    .page-hero:not(.article-hero, .thanks-hero) > .wrap:not(.author-hero) > .lead { padding-top: var(--space-lg); border-top: var(--rule-hair) solid var(--color-rule-2); max-width: 52ch; }
    /* Grand écran : le chapô monte sur la rangée du titre, aligné en haut avec lui, sous son filet,
       pour que la première section commence dans le premier écran (waive 44c) sans quadrant vide.
       Titre et chapô partent du même haut, comme sur /auteur et les articles. */
    @media (min-width: 75.0625rem) {
        .page-hero:not(.article-hero, .thanks-hero, .is-product) > .wrap:not(.author-hero) > h1:has(+ .lead) { grid-column: 1 / span 6; margin-bottom: 0; align-self: start; }
        .page-hero:not(.article-hero, .thanks-hero, .is-product) > .wrap:not(.author-hero) > h1 + .lead { grid-column: 7 / -1; align-self: start; }
        .page-hero:not(.article-hero, .thanks-hero, .is-product) > .wrap:not(.author-hero) > h1 + .lead ~ * { grid-column: 7 / -1; margin-top: var(--space-lg); }
        .page-hero:not(.article-hero, .thanks-hero, .is-product) > .wrap:not(.author-hero) > h1:has(+ .lead + *) { grid-row: span 2; }
        .page-hero:not(.article-hero, .thanks-hero, .is-product) + .section { padding-top: var(--space-xl); }
    }
    /* En-tête de section : comme à l'accueil, le titre à gauche, son chapeau à droite, alignés en pied. */
    .section > .wrap:not(.is-split, .faq-split) > .section-head:not(.is-stacked):has(> h2 + p) {
        display: grid; grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); gap: var(--gap-columns); align-items: end;
    }
    .section > .wrap:not(.is-split, .faq-split) > .section-head:not(.is-stacked):has(> h2 + p) > p { margin: 0; }
    /* Pages documentaires (contact, projets, textes légaux) : le chapeau descend d'un cran, sous un filet. */
    .page-content.is-doc > h1 { margin-bottom: var(--space-xl); }
    .page-content.is-doc > h1 + p { grid-column: 2; max-width: 52ch; padding-top: var(--space-lg); border-top: var(--rule-hair) solid var(--color-rule-2); }
    /* La lettre reste en marge, sous la barre, tant que sa rangée défile. */
    .gh-letter h3 { position: sticky; top: calc(var(--header-h) + var(--space-sm) + var(--space-2xl) + var(--space-md)); align-self: start; }
    /* Schéma (MCT, Atari) : texte sur les cinq premières colonnes, le schéma sur les six dernières, à hauteur du titre. */
    .page-hero.is-product:not(.article-hero) > .wrap:not(.author-hero) { grid-template-rows: auto auto auto 1fr; align-items: start; }
    .page-hero.is-product:not(.article-hero) > .wrap:not(.author-hero) > :is(h1, .lead, .hero-actions) { grid-column: 1 / span 5; }
    .page-hero.is-product:not(.article-hero) > .wrap:not(.author-hero) > h1 { font-size: var(--text-display); max-width: 12ch; }
    .page-hero.is-product:not(.article-hero) > .wrap:not(.author-hero) > .product-visual { grid-column: 7 / -1; grid-row: 2 / -1; align-self: center; margin: 0; }
    /* Capture (Suite) : le titre à gauche, chapeau et boutons à droite, la capture en grand sur toute la largeur. */
    .page-hero.is-product.is-shot:not(.article-hero) > .wrap:not(.author-hero) { grid-template-rows: auto auto auto auto; }
    .page-hero.is-product.is-shot:not(.article-hero) > .wrap:not(.author-hero) > h1 { grid-column: 1 / span 6; grid-row: 2 / span 2; max-width: 14ch; font-size: var(--text-display); }
    .page-hero.is-product.is-shot:not(.article-hero) > .wrap:not(.author-hero) > .lead { grid-column: 7 / -1; grid-row: 2; }
    .page-hero.is-product.is-shot:not(.article-hero) > .wrap:not(.author-hero) > .hero-actions { grid-column: 7 / -1; grid-row: 3; }
    .page-hero.is-product.is-shot:not(.article-hero) > .wrap:not(.author-hero) > .product-visual { grid-column: 1 / -1; grid-row: 4; margin-top: var(--space-2xl); }
    /* Tarifs en trois colonnes de largeurs inégales (l'intervention en tête, le projet le plus étroit) :
       noms, montants, unités et boutons alignés d'une colonne à l'autre, le bouton sous l'unité pour
       rester dans le premier écran ; le drapeau, une étiquette, se pose à droite du nom. */
    .pricing:not(.is-four):not(.is-pay) { grid-template-columns: minmax(0, 6fr) minmax(0, 5fr) minmax(0, 4fr); container-type: inline-size; }
    /* Les trois montants au même corps, borné par la colonne la plus étroite : « sur devis » y tient sur une ligne. */
    .pricing:not(.is-four):not(.is-pay) .price-amount { font-size: min(var(--text-display), calc(8.6cqi - 26px)); }
    .pricing:not(.is-four):not(.is-pay) .price-card {
        display: grid; grid-template-rows: subgrid; grid-row: span 6; grid-template-columns: auto minmax(0, 1fr);
        column-gap: var(--space-md); row-gap: var(--space-sm); justify-items: start; align-content: start;
    }
    .pricing:not(.is-four):not(.is-pay) .price-card > * { grid-column: 1 / -1; }
    .pricing:not(.is-four):not(.is-pay) .price-card > :is(h2, h3) { grid-row: 1; align-self: baseline; margin: 0; }
    .pricing:not(.is-four):not(.is-pay) .price-card > .price-amount { grid-row: 2; align-self: end; margin-top: var(--space-sm); }
    .pricing:not(.is-four):not(.is-pay) .price-card > .price-flag { grid-column: 2; grid-row: 1; justify-self: end; align-self: baseline; }
    .pricing:not(.is-four):not(.is-pay) .price-card > .price-unit { grid-row: 3; }
    .pricing:not(.is-four):not(.is-pay) .price-card > .btn { grid-row: 4; align-self: start; margin-top: var(--space-xs); }
    .pricing:not(.is-four):not(.is-pay) .price-card > p { grid-row: 5; margin-top: var(--space-xs); }
    .pricing:not(.is-four):not(.is-pay) .price-card > :is(ul, p ~ p) { grid-row: 6; align-content: start; }
    .thanks-hero .wrap { display: grid; grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); column-gap: var(--space-2xl); align-items: start; }
    .thanks-hero .wrap > * { grid-column: 1; min-width: 0; }
    .thanks-hero .wrap > .journey-panel { grid-column: 2; grid-row: 1 / span 8; align-self: center; margin-top: 0; padding: var(--space-xl); }
}

/* Colonnes oui / non et périmètres : deux listes sous un filet, rangées comme un index. */
.split-card, .split-card.is-no { padding: var(--space-lg) 0 0; border: 0; border-top: var(--rule-hair) solid var(--color-rule-2); border-radius: 0; background: none; }
.split-card li::before { top: calc(var(--space-sm) + 0.72em); }
.split-card.is-yes li::before { top: calc(var(--space-sm) + 0.5em); }
@media (max-width: 40rem) { .split-card, .split-card.is-no { padding: var(--space-lg) 0 0; } }

/* Guides, liste de lecture : un puits à filet, une rangée par guide ; titre et extrait à gauche, relevé à droite
   (durée en mono, date dans la police du texte). Un seul signal de survol : le fond de toute la rangée. */
.guide-cards.is-index { display: block; color: var(--color-ink); background: var(--color-paper-2); border: var(--rule-hair) solid var(--color-rule); border-radius: var(--radius-card); overflow: clip; }
.guide-cards.is-index .guide-card {
    display: grid; grid-template-columns: minmax(0, 1fr) 6.5rem; grid-template-areas: "title dur" "text date";
    align-items: baseline; gap: var(--space-xs) var(--space-lg);
    padding: var(--space-lg) var(--space-xl); border-top: var(--rule-hair) solid var(--color-rule);
    transition: background-color var(--dur-short) var(--ease-out);
}
.guide-cards.is-index .guide-card:first-child { border-top: 0; }
.guide-cards.is-index .guide-card :is(h2, h3) { grid-area: title; font-size: var(--text-2xl); line-height: 1.05; max-width: none; text-wrap: balance; }
.guide-cards.is-index .guide-card p { grid-area: text; font-size: var(--text-sm); }
.guide-cards.is-index .guide-card-foot { display: contents; }
.guide-cards.is-index .guide-card-foot > time { grid-area: date; justify-self: end; }
.guide-cards.is-index .guide-card-time { grid-area: dur; justify-self: end; font-size: var(--text-sm); color: var(--color-ink-2); }
.guide-cards.is-index .guide-card :is(h2, h3) a:focus-visible { outline: none; }
.guide-cards.is-index .guide-card:has(:is(h2, h3) a:focus-visible) { outline: 2px solid var(--color-focus); outline-offset: -2px; }
.guide-cards.is-index .guide-card:hover { background: var(--color-paper-3); }
@media (max-width: 40rem) {
    .guide-cards.is-index .guide-card { grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "title title" "text text" "date dur"; padding: var(--space-md); }
    .guide-cards.is-index .guide-card-foot > time { justify-self: start; }
    .guide-cards.is-index .guide-card:hover { background: none; }
  .article-body table { min-width: 100%; }
  .article-body :is(thead th, tbody td) { min-width: 9rem; }
  .article-body :is(thead th, tbody td):first-child { min-width: 7rem; }
  /* Trois colonnes et plus : chaque ligne devient une fiche, l'intitulé de colonne en marge. */
  .article-body table.is-stacked { width: 100%; min-width: 0; overflow: visible; background: none; }
  .article-body table.is-stacked thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
  .article-body table.is-stacked :is(tbody, tr, td) { display: block; min-width: 0; }
  .article-body table.is-stacked tr { padding: var(--space-sm) 0; border-bottom: var(--rule-hair) solid var(--color-rule); }
  .article-body table.is-stacked tr:first-child { border-top: var(--rule-hair) solid var(--color-rule-2); }
  .article-body table.is-stacked tbody td { display: grid; grid-template-columns: 7.5rem minmax(0, 1fr); gap: var(--space-sm); padding: var(--space-2xs) 0; border: 0; white-space: normal; }
  .article-body table.is-stacked tbody td::before { content: attr(data-label); font-size: var(--text-xs); line-height: 1.9; color: var(--color-muted); }
  .article-body table.is-stacked tbody td:first-child { display: block; padding-bottom: var(--space-xs); font-size: var(--text-md); }
  .article-body table.is-stacked tbody td:first-child::before { content: none; }
  .article-body table.is-stacked tbody tr:hover { background: none; }
  .article-body table.is-stacked tbody td[data-empty] { display: none; }
}

/* Outils : titres de fiche à l'échelle de l'accueil, catégories en relevé mono, un seul bouton laiton. */
.tool-row .tag, .tool-row .tag.is-wp { padding: 0; background: none; border-radius: 0; font: 400 var(--text-xs)/1.5 var(--font-outlier); color: var(--color-muted); }
.tool-row :is(h2, h3) { font-size: var(--text-2xl); line-height: 1.05; }
.tool-row h3 a:hover { color: var(--color-ink); transform: translateX(var(--space-xs)); }
.tools-grid > .tool-row:first-child { padding-top: var(--space-lg); border-top-color: var(--color-rule-2); }

/* Passe technique : accessibilité et performance */
/* Polices de repli aux métriques des polices du thème : tant que la police web
   n'est pas chargée (font-display: swap), le texte occupe déjà la même place,
   sans saut de mise en page à l'échange. Valeurs mesurées sur un texte français. */
@font-face { font-family: "Instrument Serif Fallback"; src: local("Times New Roman"), local("TimesNewRomanPSMT"), local("Liberation Serif"), local("Tinos"); size-adjust: 83%; ascent-override: 119%; descent-override: 37%; line-gap-override: 0%; }
@font-face { font-family: "Geist Fallback"; src: local("Arial"), local("ArialMT"), local("Liberation Sans"), local("Arimo"); size-adjust: 101.5%; ascent-override: 99%; descent-override: 29%; line-gap-override: 0%; }
@font-face { font-family: "Geist Mono Fallback"; src: local("Courier New"), local("CourierNewPSMT"), local("Liberation Mono"), local("Cousine"); size-adjust: 100%; ascent-override: 100.5%; descent-override: 29.5%; line-gap-override: 0%; }

/* ==========================================================================
   En-tête mobile et transition entre pages
   ========================================================================== */
/* En-tête au téléphone : la pilule s'efface quand on descend et revient dès qu'on remonte
   (site.js pose .is-hidden). Jamais pendant que le focus est dedans ni menu ouvert. */
@media (max-width: 40rem), (max-height: 30rem) {
    .site-header.is-hidden:not(:focus-within) { transform: translateY(calc(-100% - var(--space-xl))); transition: transform var(--dur-micro) var(--ease-in); }
}
/* Paysage bas : la pilule perd 8 px, le premier écran garde sa place. */
@media (max-height: 30rem) {
    .site-header { --header-top: max(var(--space-xs), env(safe-area-inset-top)); }
    .header-inner { height: 56px; }
}

/* Transition entre pages : un fondu court du document, l'en-tête reste en place.
   Navigateurs sans prise en charge : navigation ordinaire. Coupée sous mouvement réduit. */
@media (prefers-reduced-motion: no-preference) {
    @view-transition { navigation: auto; }
    .site-header { view-transition-name: site-header; }
    ::view-transition-old(root) { animation: lumen-page-out var(--dur-micro) var(--ease-in) both; }
    ::view-transition-new(root) { animation: lumen-page-in var(--dur-short) var(--ease-out) both; }
    ::view-transition-group(site-header) { animation-duration: var(--dur-short); }
    /* Les barres partent de zéro et prennent leur valeur quand le dossier entre à l'écran. */
    .js .case-file:not(.is-in) .case-figures li::after { transform: scaleX(0); }
    .product-visual { animation: settle 640ms var(--ease-out) 200ms both; }
    .vp-panel > .vp-box { animation: settle 420ms var(--ease-out) both; }
}
@keyframes lumen-page-out { to { opacity: 0; } }
@keyframes lumen-page-in { from { opacity: 0; transform: translateY(var(--space-xs)); } }
/* ==========================================================================
   Lecture longue
   Gabarits de lecture longue : guides, études de cas, glossaire, pages
   légales. Un corps à 17 px sur une mesure de 56 ch, des intertitres ouverts
   par un filet, un sommaire collant qui suit la lecture, une progression en
   haut d'écran, des blocs de code copiables et une feuille d'impression.
   ========================================================================== */

/* ---------- Corps : mesure, rythme vertical, intertitres ---------- */
.article-body { font-size: var(--text-body); line-height: 1.7; }
.article-body p { margin: 0 0 1.15em; }
.article-body :is(ul, ol) { margin: 0 0 1.15em; padding-left: 1.4em; }
.article-body li { margin-bottom: 0.45em; padding-left: 0.2em; }
.article-body li::marker { color: var(--color-muted); }
.article-body ol > li::marker { font-size: 0.85em; }
.article-body :is(p, li) strong { color: var(--color-ink); font-weight: 500; }
.article-body h2 + h3 { margin-top: var(--space-lg); }
.article-body :is(h2, h3) + :is(p, ul, ol) { margin-top: 0; }
.article-body blockquote p:last-child { margin-bottom: 0; }
.article-body hr { margin: var(--space-2xl) 0; border: 0; border-top: var(--rule-hair) solid var(--color-rule); }

/* Ancres de titres : un « # » en mono, visible au survol de l'intertitre et au focus. */
.h-anchor {
  display: inline-block; min-width: 24px; min-height: 24px; margin-left: var(--space-2xs); text-align: center; vertical-align: 0.1em;
  font: 400 var(--text-sm)/24px var(--font-outlier); color: var(--color-muted); text-decoration: none; opacity: 0;
  transition: opacity var(--dur-micro) var(--ease-out), color var(--dur-micro) var(--ease-out);
}
:is(h2, h3):hover > .h-anchor { opacity: 1; }
.h-anchor:hover { color: var(--color-accent); }
.h-anchor:focus-visible { opacity: 1; transition: none; }

/* ---------- Progression de lecture : un filet laiton en haut d'écran ---------- */
.read-progress {
  position: fixed; inset: 0 0 auto; z-index: calc(var(--z-sticky-nav) + 1); height: 2px; pointer-events: none;
  background: var(--color-accent); transform-origin: 0 50%; transform: scaleX(0);
}
@supports (animation-timeline: scroll()) {
  @media (prefers-reduced-motion: no-preference) {
    .read-progress { animation: read-progress linear both; animation-timeline: scroll(root block); }
  }
}
@keyframes read-progress { to { transform: scaleX(1); } }

/* ---------- Sommaire : collant en bureau, repliable en mobile, section courante ---------- */
.article-toc summary {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-md); min-height: 44px; margin-bottom: var(--space-sm);
  list-style: none; cursor: pointer;
}
.article-toc summary::-webkit-details-marker { display: none; }
.article-toc summary h2 { margin: 0; }
.article-toc summary::after {
  content: ""; flex: none; width: 8px; height: 8px; margin-right: var(--space-2xs);
  border-right: var(--rule-hair) solid var(--color-muted); border-bottom: var(--rule-hair) solid var(--color-muted);
  transform: translateY(-2px) rotate(45deg); transition: transform var(--dur-short) var(--ease-out);
}
.article-toc details[open] > summary::after { transform: translateY(2px) rotate(225deg); }
.article-toc summary:hover::after { border-color: var(--color-ink); }
.article-toc summary:focus-visible { outline: 2px solid var(--color-focus); outline-offset: 2px; transition: none; }
.article-toc li > a { display: block; padding: var(--space-xs) 0; text-decoration-line: none; line-height: 1.4; color: var(--color-ink-2); text-decoration: none; transition: color var(--dur-short) var(--ease-out); }
.article-toc li > a:hover { color: var(--color-ink); text-decoration-line: underline; text-decoration-color: var(--color-rule-2); }
.article-toc li:has(> a[aria-current]) { border-left-color: var(--color-accent); }
.article-toc li:has(> a[aria-current]) span { color: var(--color-ink-2); }
.article-toc a[aria-current] { color: var(--color-ink); font-weight: 500; }
@media (max-width: 60rem) {
  .article-toc { padding-top: var(--space-2xs); border-bottom: var(--rule-hair) solid var(--color-rule-2); }
  .article-toc summary { margin-bottom: 0; }
  .article-toc details[open] > summary { margin-bottom: var(--space-sm); }
  .article-toc ol { padding-bottom: var(--space-md); }
}
@media (prefers-reduced-motion: reduce) {
  .article-toc summary::after, .article-toc li, .article-toc li span, .article-toc a { transition: none; }
}

/* ---------- Blocs de code : Geist Mono, un bandeau pour le bouton « Copier » ---------- */
/* Le fond est porté par le bandeau et par le code : le bloc lui-même n'est qu'un filet (le code défile dedans). */
.code-block { margin: var(--space-xl) 0; overflow: hidden; border: var(--rule-hair) solid var(--color-rule); border-radius: var(--radius-card); background: none; color: var(--color-ink); }
.code-bar { display: flex; justify-content: flex-end; padding: 0 var(--space-2xs); border-bottom: var(--rule-hair) solid var(--color-rule); background: var(--color-paper-2); }
.article-body .code-block > pre {
  margin: 0; padding: var(--space-md) var(--space-lg) var(--space-lg); border: 0; border-radius: 0;
  background: var(--color-paper-2); color: var(--color-ink); font-size: var(--text-xs); line-height: 1.75; tab-size: 4;
}
.article-body pre:focus-visible { outline: 2px solid var(--color-focus); outline-offset: -2px; }
.code-copy {
  display: inline-flex; align-items: center; gap: var(--space-xs); min-height: 44px; padding: 0 var(--space-sm);
  border: 0; border-radius: var(--radius-pill); background: none; color: var(--color-muted);
  font: 400 var(--text-xs)/1 var(--font-outlier); text-transform: lowercase; cursor: pointer;
  transition: color var(--dur-micro) var(--ease-out), background-color var(--dur-micro) var(--ease-out);
}
.code-copy::before {
  content: ""; width: 9px; height: 9px; border: var(--rule-hair) solid currentColor; border-radius: 2px;
  box-shadow: 3px -3px 0 -1px var(--color-paper-2), 3px -3px 0 0 currentColor;
}
.code-copy:hover { background: var(--color-paper-3); color: var(--color-ink); }
.code-copy:active { background: var(--color-rule); }
.code-copy:focus-visible { outline: 2px solid var(--color-focus); outline-offset: 0; transition: none; }
.code-copy[data-state="done"] { color: var(--color-success); }
.code-copy[data-state="error"] { color: var(--color-error); }
.code-copy[data-state]::before { border-radius: 50%; box-shadow: none; }

/* ---------- Tableaux : défilement latéral signalé par un fondu au bord ---------- */
.article-body tbody td:first-child { color: var(--color-ink); font-weight: 500; }
.article-body tbody tr { transition: background-color var(--dur-micro) var(--ease-out); }
.article-body tbody tr:hover { background-color: var(--color-paper-3); }
.article-body table:focus-visible { outline: 2px solid var(--color-focus); outline-offset: 4px; }

/* ---------- Fin d'article : questions, sources, auteur, navigation ---------- */
.article-faq .faq-item { padding: var(--space-lg) 0; }
.article-faq .faq-item h3 { margin-bottom: var(--space-sm); font-size: var(--h3-size); line-height: 1.15; }
.article-faq .faq-item p { line-height: 1.7; }
.article-main > :is(.article-faq, .sources, .changelog, .glo-related) { padding-top: var(--space-md); }

.author-box h2 a:hover { text-decoration: underline; text-decoration-color: var(--color-accent); text-underline-offset: 0.15em; }
.author-links a:hover { color: var(--color-accent); text-decoration-color: var(--color-accent); }

:is(.article-annex, .glo-foot) .guide-nav { gap: 0; border-top: var(--rule-hair) solid var(--color-rule); border-bottom: var(--rule-hair) solid var(--color-rule); }
:is(.article-annex, .glo-foot) .guide-nav a {
  gap: var(--space-xs); padding: var(--space-lg) var(--space-md); border: 0; border-radius: 0;
  transition: background-color var(--dur-short) var(--ease-out);
}
:is(.article-annex, .glo-foot) .guide-nav a + a { border-left: var(--rule-hair) solid var(--color-rule); }
:is(.article-annex, .glo-foot) .guide-nav a:hover { background: var(--color-paper-2); }
:is(.article-annex, .glo-foot) .guide-nav .gn-title { font-family: var(--font-display); font-size: var(--text-xl); font-weight: var(--display-weight); line-height: 1.15; text-transform: lowercase; color: var(--color-ink); }
:is(.article-annex, .glo-foot) .guide-nav a:focus-visible { outline-offset: -2px; }
@media (max-width: 40rem) {
  :is(.article-annex, .glo-foot) .guide-nav a + a { border-left: 0; border-top: var(--rule-hair) solid var(--color-rule); }
  .author-box { padding: var(--space-lg) 0 0; }
  /* Cellules de tableau : de la donnée à lire, pas une légende ; 16 px sur téléphone (les figcaption restent à 14 px). */
  .article-body tbody td { font-size: var(--text-md); }
}

/* ---------- Glossaire : index des termes, terme ciblé, ancres ---------- */
.glo-toc { display: flex; flex-wrap: wrap; gap: 0 var(--space-lg); padding: 0 0 var(--space-sm); }
.glo-toc a {
  display: inline-flex; align-items: center; min-height: 44px; padding: 0; border: 0; border-radius: 0; background: none;
  font-size: var(--text-sm); font-weight: 400; color: var(--color-ink-2); text-decoration: underline; text-decoration-color: var(--color-rule-2); text-underline-offset: 0.3em;
  transition: color var(--dur-micro) var(--ease-out), text-decoration-color var(--dur-micro) var(--ease-out);
  min-width: 24px;
  text-align: center;
}
.glo-toc a:hover { color: var(--color-accent); text-decoration-color: var(--color-accent); background: none; }
.glo-term:target { border-top-color: var(--color-accent); }
.glo-term h2:hover > .glo-anchor { opacity: 1; }
.glo-anchor:focus-visible { opacity: 1; transition: none; }
@media (prefers-reduced-motion: reduce) { .glo-term, .glo-anchor, .h-anchor, .code-copy, .article-body tbody tr { transition: none; } }

/* ---------- Pages légales : sobres, même typographie de lecture ---------- */
.page-content.is-doc > :is(p, ul, ol) { font-size: var(--text-body); line-height: 1.7; color: var(--color-ink-2); }
.page-content.is-doc > p { margin: 0 0 1.15em; }
.page-content.is-doc > :is(ul, ol) { margin: 0 0 1.15em; padding-left: 1.4em; }
.page-content.is-doc > :is(ul, ol) li::marker { color: var(--color-muted); }
.page-content.is-doc > :is(p, ul, ol) strong { color: var(--color-ink); font-weight: 500; }
.page-content.is-doc a, .article-body a { overflow-wrap: anywhere; }
.page-content.is-doc > h3 {
  margin: var(--space-xl) 0 var(--space-xs); font-family: var(--font-body); font-size: var(--text-md); font-weight: 500;
  letter-spacing: 0; line-height: 1.4; color: var(--color-ink);
}
.page-content.is-doc > h2 + h3 { margin-top: var(--space-2xl); }
.page-content.is-doc code { padding: 0.1em 0.35em; border-radius: var(--radius-chip); background: var(--color-paper-3); color: var(--color-ink); font-family: var(--font-outlier); font-size: 0.85em; }

/* ---------- Impression des guides : du texte noir sur blanc, sans le chrome ---------- */
@media print {
  :root:has(.article-body) {
    color-scheme: light; --color-paper: Canvas; --color-paper-2: Canvas; --color-paper-3: Canvas;
    --color-ink: CanvasText; --color-ink-2: CanvasText; --color-muted: GrayText; --color-rule: GrayText; --color-rule-2: GrayText;
    --color-accent: CanvasText; 
  }
  @page { margin: 18mm 16mm; }
  html:has(.article-body) body { background: var(--color-paper); color: var(--color-ink); font-size: 10.5pt; }
  html:has(.article-body) :is(.site-header, .site-footer, .skip-link, .read-progress, .article-toc, .code-bar, .h-anchor, .article-related, .guide-nav, .author-links, .breadcrumb, .cta-band) { display: none !important; }
  html:has(.article-body) :is(.page-hero, .article-section) { padding: 0; background: none; }
  html:has(.article-body) .article-layout { display: block; }
  html:has(.article-body) .article-rail > * { position: static; max-height: none; overflow: visible; }
  html:has(.article-body) .takeaways { margin-bottom: 8mm; }
  .article-body { font-size: 10.5pt; line-height: 1.55; }
  .article-body :is(h2, h3) { break-after: avoid; }
  .article-body :is(pre, table, figure, blockquote), .code-block, .faq-item { break-inside: avoid; }
  .article-body p { orphans: 3; widows: 3; }
  .article-body pre { white-space: pre-wrap; overflow-wrap: anywhere; }
  .article-body table { width: 100%; display: table; background: none; }
  .article-body a[href^="http"]::after { content: " (" attr(href) ")"; font-weight: 400; font-size: 0.85em; overflow-wrap: anywhere; }
  [data-reveal] { opacity: 1 !important; transform: none !important; }
}

/* ---------- Cibles de lien isolées : 24 px de zone de frappe au moins (padding en ligne, sans effet sur la mise en page) ---------- */
.article-related .guide-links-all a, .page-content.is-doc > p > a:only-child,
.article-main :is(p, li) > a:only-child, .article-meta a { padding-block: var(--space-2xs); }
/* ==========================================================================
   Pages d'index, de projet et d'outil : chaque index se parcourt comme un instrument.
   Rangées réactives au survol et au focus, navigation interne, relevés chiffrés en puits.
   Mouvement en transform/opacity seulement ; sans JavaScript ou en mouvement réduit, tout reste visible. */
@keyframes ix-draw-y { from { transform: scaleY(0); } }
@keyframes ix-scan { from { transform: translateX(-100%); } to { transform: translateX(340%); } }

/* Rangées d'index (outils, ressources) : la rangée entière répond au survol, le focus du lien l'entoure. */
.tools-grid > .tool-row { padding-inline: var(--space-md); transition: background-color var(--dur-short) var(--ease-out); }
.tools-grid > .tool-row h2 { transition: transform var(--dur-short) var(--ease-out); }
.tools-grid > .tool-row:hover { background: var(--color-paper-2); }
.tools-grid > .tool-row:hover h2 { transform: translateX(var(--space-xs)); }
.tools-grid > .tool-row:has(a:focus-visible) { background: var(--color-paper-2); }


/* ---------- Études de cas : un dossier par étude, contexte, relevé chiffré, issue ---------- */
.case-files { margin-top: var(--space-3xl); border-top: var(--rule-hair) solid var(--color-rule-2); }
.case-file { display: grid; gap: var(--space-xl); padding: var(--space-2xl) 0 var(--space-3xl); border-bottom: var(--rule-hair) solid var(--color-rule-2); }
.case-file-head { display: grid; grid-template-columns: minmax(0, 1fr); align-items: baseline; gap: var(--space-sm) var(--space-md); }
.case-file h2 { margin: 0; max-width: 30ch; font-size: var(--text-3xl); line-height: 1.02; }
.case-file h2 a { color: inherit; text-decoration: underline; text-decoration-color: transparent; text-decoration-thickness: var(--rule-hair); text-underline-offset: 0.14em; transition: text-decoration-color var(--dur-micro) var(--ease-out); }
.case-file h2 a:is(:hover, :focus-visible) { text-decoration-color: var(--color-accent); }
.case-file .case-meta { align-items: baseline; }
.case-file .case-meta .tag { padding: 0; background: none; font: inherit; color: var(--color-muted); text-transform: lowercase; }
.case-dossier { display: grid; grid-template-columns: minmax(0, 4fr) minmax(0, 5fr) minmax(0, 3fr); gap: var(--space-lg) var(--gap-columns); margin: 0; }
.case-part { min-width: 0; padding-top: var(--space-md); border-top: var(--rule-hair) solid var(--color-rule); }
.case-part dt { margin: 0 0 var(--space-sm); font-size: var(--text-xs); line-height: 1.4; color: var(--color-muted); }
.case-part dd { margin: 0; color: var(--color-ink-2); }
.case-part dd p { margin: 0 0 var(--space-sm); }
.case-part .case-source { font-size: var(--text-sm); color: var(--color-muted); }
.case-part.is-readout { padding: var(--space-md) var(--space-lg) var(--space-lg); background: var(--color-paper-2); border: var(--rule-hair) solid var(--color-rule); border-radius: var(--radius-lg); }
.case-part.is-outcome dd { color: var(--color-ink); }
.case-figures { display: grid; gap: var(--space-md); margin: 0; padding: 0; list-style: none; }
.case-figures li { position: relative; display: grid; gap: var(--space-3xs); padding-bottom: var(--space-sm); }
.case-figures li::before, .case-figures li::after { content: ""; position: absolute; inset: auto 0 0; height: 3px; }
.case-figures li::before { background: var(--color-rule); }
/* La variable en ink-2 à mi-force ; le stock tenu fixe (.is-fixed, une par dossier au plus) n'est pas une mesure mais la référence
   de l'échelle : un filet de laiton, pas une barre. Même sens, même trait d'un dossier à l'autre. */
.case-figures li::after { background: var(--color-ink-2); opacity: 0.5; transform-origin: left center; transform: scaleX(var(--v, 1)); transition: transform var(--dur-long) var(--ease-out); }
.case-fig { font-family: var(--font-display); font-size: var(--text-2xl); line-height: 1; color: var(--color-ink); font-variant-numeric: tabular-nums; }
.case-fig-label { font-size: var(--text-sm); color: var(--color-muted); }
@media (max-width: 60rem) {
    .case-dossier { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
    .case-part.is-context { grid-column: 1 / -1; }
    .case-file h2 { font-size: var(--text-2xl); }
}
@media (max-width: 40rem) {
    .case-dossier { grid-template-columns: minmax(0, 1fr); }
}

/* ---------- Glossaire : barre des lettres collante, lettre courante, filtre ---------- */
.gh-tools {
    position: sticky; top: calc(var(--header-h) + var(--space-sm)); z-index: var(--z-sticky);
    display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-xs) var(--gap-columns);
    margin: 0 0 var(--space-xl); padding: var(--space-xs) 0; background: var(--color-paper-2); border-bottom: var(--rule-hair) solid var(--color-rule);
    /* Le fond de la barre déborde jusqu'aux bords de l'écran, sans élargir la page. */
    box-shadow: 0 0 0 100vmax var(--color-paper-2); clip-path: inset(0 -100vmax);
}
.gh-tools .gh-azbar { flex: 0 1 auto; min-width: 0; flex-wrap: nowrap; gap: var(--space-3xs); margin: 0; overflow-x: auto; scrollbar-width: none; }
.gh-tools .gh-azbar::-webkit-scrollbar { display: none; }
.gh-tools .gh-azbar a { flex: none; min-width: 36px; transition: background-color var(--dur-micro) var(--ease-out), border-color var(--dur-micro) var(--ease-out), color var(--dur-micro) var(--ease-out), opacity var(--dur-short) var(--ease-out); }
.gh-tools .gh-azbar a:hover { color: var(--color-ink); background: var(--color-paper-3); border-color: var(--color-muted); }
/* Lettre courante : un filet laiton, pas un aplat. */
.gh-tools .gh-azbar a[aria-current] { border-color: var(--color-accent); color: var(--color-ink); background: var(--color-paper-3); }
.gh-tools .gh-azbar a.is-empty { opacity: 0.3; }
.gh-filter { display: flex; align-items: center; gap: var(--space-xs) var(--space-sm); }
.gh-filter[hidden] { display: none; }
.gh-filter label { font-size: var(--text-xs); line-height: 1.4; color: var(--color-muted); white-space: nowrap; }
.gh-filter input {
    width: 11rem; min-height: 44px; padding: 0 var(--space-sm); font: inherit; color: var(--color-ink);
    background: var(--color-paper); border: var(--rule-hair) solid var(--color-muted); border-radius: var(--radius-chip);
    transition: border-color var(--dur-micro) var(--ease-out);
}
.gh-filter input:hover { border-color: var(--color-ink-2); }
.gh-filter input:focus-visible { outline: 2px solid var(--color-focus); outline-offset: 2px; border-color: var(--color-accent); }
.gh-count-live { min-width: 9ch; font: 400 var(--text-xs)/1.4 var(--font-outlier); color: var(--color-muted); font-variant-numeric: tabular-nums; }
.gh-letter[hidden] { display: none; }
.gh-card:hover, .gh-card:has(a:focus-visible) { background: var(--color-paper-2); }
.gh-card:is(:hover, :has(a:focus-visible)) h2 a { text-decoration-color: var(--color-accent); }
@media (max-width: 40rem) {
    /* Au téléphone, les 21 lettres sur deux rangées de onze, sans défilement latéral. */
    .gh-tools .gh-azbar { flex-basis: 100%; display: grid; grid-template-columns: repeat(11, minmax(0, 1fr)); overflow: visible; }
    .gh-tools .gh-azbar a { min-width: 0; height: 36px; }
    .gh-filter { flex: 1 1 100%; flex-wrap: wrap; }
    .gh-count-live { flex-basis: 100%; min-width: 0; }
    .gh-count-live:empty { flex-basis: 0; }
    .gh-filter input { flex: 1 1 auto; width: auto; min-width: 0; }
    .gh-letter { scroll-margin-top: calc(var(--header-h) + var(--space-sm) + var(--space-4xl) + var(--space-lg)); }
}

/* ---------- Pages projet : le bandeau montre le produit ---------- */
.product-visual { margin: var(--space-xl) 0 0; min-width: 0; }
/* Le produit fait l'image : une vraie capture, un seul cadre (filet et rayon du thème), sans puits autour.
   La console de la Suite porte déjà son propre cadre dans l'image. */
.product-shot { padding: 0; }
.product-shot picture { display: block; }
.product-shot img { display: block; width: 100%; height: auto; border: var(--rule-hair) solid var(--color-rule-2); border-radius: var(--radius-card); background: var(--color-paper-2); }
.product-shot.is-console img { border: 0; }

/* ---------- Outil version PHP : états du formulaire et du verdict ---------- */
.vp-progress { position: relative; flex: 1 1 100%; height: 2px; overflow: hidden; background: var(--color-rule); opacity: 0; transition: opacity var(--dur-short) var(--ease-out); }
.vp-progress::after { content: ""; position: absolute; top: 0; bottom: 0; left: 0; width: 30%; background: var(--color-accent); transform: translateX(-100%); }
.vp-form[data-sent] .vp-progress { opacity: 1; }
.vp-form[data-sent] .vp-progress::after { animation: ix-scan 1100ms var(--ease-in-out) infinite; }
.vp-panel .vp-box { transition: opacity var(--dur-short) var(--ease-out); }
.vp-panel[aria-busy="true"] .vp-box { opacity: 0.4; }
.vp-box > h2 { display: flex; align-items: center; gap: var(--space-sm); }
.vp-box > h2::before { content: ""; flex: none; width: var(--space-sm); height: var(--space-sm); border-radius: 50%; background: var(--color-rule-2); }
.vp-verdict-warn > h2::before { background: var(--color-accent); }
.vp-verdict-ok > h2::before { background: var(--color-live); }
.vp-verdict-neutral { border-color: var(--color-rule-2); background: var(--color-paper-2); }
@media (prefers-reduced-motion: reduce) {
    /* Sans balayage : la barre de chargement reste pleine. */
    .vp-progress::after { width: 100%; transform: none; }
}

/* Pages projet : la page commence juste sous le bandeau, sans l'ancien filet d'ouverture. */
.page-hero.is-product + .page-content.is-doc { padding-top: var(--space-lg); }
/* Lisibilité et cibles (relevé de l'agent mobile) : les textes courants des index passent au corps,
   les liens de catégorie et de méta gagnent une cible de 24 px. Restent en 14 px : la méta de signature
   (.hero-byline) et la légende de source du tableau des versions, qui ne sont pas du texte courant. */
.vp-panel > .vp-hint { font-size: var(--text-body); }
.guide-card-cat, .case-meta a { display: inline-flex; align-items: center; min-height: 24px; }
/* ==========================================================================
   Conversion : boutons, champs, appel final et grille tarifaire. Les huit états de
   chaque contrôle (repos, survol, focus, actif, désactivé, erreur, succès, chargement)
   sont tous ici. Sur un bouton, l'erreur et le succès appartiennent au formulaire :
   le résumé d'erreurs au-dessus, la page merci après l'envoi. */

/* Boutons : un seul primaire (laiton plein), un seul secondaire (filet). btn-dark et
   btn-light ne sont plus que des alias du secondaire. Survol : le primaire fonce d'un
   cran, le secondaire se remplit depuis le bas ; appui : 1px plus bas ; le focus est
   immédiat et n'est jamais animé. */
.btn-outline, .btn-dark, .btn-light, .section-ink .btn-outline { background: none; color: var(--color-ink); box-shadow: inset 0 0 0 var(--rule-hair) var(--color-rule-2); }
.btn-outline::before, .btn-dark::before, .btn-light::before {
    content: ""; position: absolute; inset: 0; z-index: -1; border-radius: inherit; background: var(--color-paper-3);
    transform: scaleY(0); transform-origin: bottom; transition: transform var(--dur-short) var(--ease-out);
}
@media (hover: hover) {
    .btn-outline:hover, .btn-dark:hover, .btn-light:hover, .section-ink .btn-outline:hover { background: none; color: var(--color-ink); box-shadow: inset 0 0 0 var(--rule-hair) var(--color-muted); }
    .btn-outline:hover::before, .btn-dark:hover::before, .btn-light:hover::before { transform: scaleY(1); }
    .field :is(input:not([type="checkbox"]), select, textarea):hover { background: var(--color-paper); border-color: var(--color-ink-2); }
 .check:hover { color: var(--color-ink); }
}
.btn-primary:active { background: color-mix(in oklch, var(--color-accent) 76%, var(--color-ink)); }
.btn-outline:active::before, .btn-dark:active::before, .btn-light:active::before { transform: scaleY(1); background: var(--color-rule); }
.btn:focus-visible { outline: 2px solid var(--color-focus); outline-offset: 3px; }
.btn:disabled, .btn[aria-disabled="true"]:not([aria-busy="true"]) { opacity: 0.55; cursor: not-allowed; background: var(--color-paper-3); color: var(--color-muted); box-shadow: none; transform: none; }
.btn:disabled::before, .btn[aria-disabled="true"]::before { transform: scaleY(0); }
/* Chargement : le libellé reste lisible, la largeur est figée par le script, un anneau tourne. */
.btn[aria-busy="true"] { cursor: progress; transform: none; }
.btn[aria-busy="true"]::after {
    content: ""; order: -1; flex: none; width: 1em; height: 1em; border-radius: 50%;
    border: 2px solid currentColor; border-right-color: transparent; animation: btn-spin 0.8s linear infinite;
}
@keyframes btn-spin { to { transform: rotate(1turn); } }
@keyframes btn-breathe { from { opacity: 1; } to { opacity: 0.35; } }

/* Champs : la bordure garde sa largeur ; l'anneau de focus est réservé (transparent)
   au repos et se dessine à 2 px du bord, sans décalage. La seule règle de focus des champs, case comprise. */
.field :is(input:not([type="checkbox"]), select, textarea) {
    outline: 2px solid transparent; outline-offset: 2px;
    transition: background-color var(--dur-micro) var(--ease-out), border-color var(--dur-micro) var(--ease-out);
}
.field :is(input, select, textarea):focus-visible { outline: 2px solid var(--color-focus); outline-offset: 2px; border-color: var(--color-ink-2); }
.field select:active { background: var(--color-paper-2); }
.field :is(input, select, textarea):disabled { opacity: 0.55; cursor: not-allowed; }
.field :is(input, select, textarea):disabled::placeholder { color: var(--color-rule-2); }
.field select { cursor: pointer; }
.field label > span[aria-hidden="true"] { color: var(--color-ink-2); }
/* Erreur : bordure, fond, message relié au champ et signe « ! » ; jamais la couleur seule. */
.field :is(input, select, textarea)[aria-invalid="true"] { border-color: var(--color-error); background: var(--color-red-wash); }
.field-error:not(:empty)::before {
    content: "!"; flex: none; display: grid; place-items: center; width: 1.15em; height: 1.15em; margin-top: 0.1em;
    border: 1.5px solid currentColor; border-radius: 50%; font: 500 0.75em/1 var(--font-body);
}
.form.is-enhanced, .form.is-enhanced .form-row { gap: var(--space-sm) var(--space-lg); }
.form.is-enhanced .field-error { min-height: 1lh; }
/* Succès : seulement pour un champ corrigé après une erreur ; une coche suit le libellé. */
.field.is-valid :is(input, select, textarea) { border-color: var(--color-success); }
.field.is-valid > label::after {
    content: ""; display: inline-block; width: 0.6em; height: 0.32em; margin: 0 0 0.2em var(--space-xs);
    border-left: 2px solid var(--color-success); border-bottom: 2px solid var(--color-success); transform: rotate(-45deg);
}
/* Case à cocher : native, anneau extérieur, cible = toute la phrase. */
.check { cursor: pointer; padding-block: var(--space-2xs); }
.check input[aria-invalid="true"] { box-shadow: 0 0 0 2px var(--color-error); border-radius: 3px; }
.field.is-valid .check input { box-shadow: 0 0 0 2px var(--color-success); border-radius: 3px; }
/* Chargement du formulaire : les champs restent lisibles, le pointeur dit d'attendre. */
.form[aria-busy="true"] :is(input, select, textarea) { cursor: progress; }
.form .btn-submit { width: 100%; }
#form-errors[hidden] { display: none; }
.alert-error strong { color: var(--color-ink); }

/* Pages merci : la suite du parcours, l'étape en cours repérée. */
.journey-title { margin: var(--space-xl) 0 var(--space-md); font-size: var(--text-xl); }
.journey { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-md); max-width: var(--measure); counter-reset: jstep; }
.journey li {
    position: relative; counter-increment: jstep; padding-left: calc(32px + var(--space-md)); min-height: 32px;
    font-size: var(--text-body); line-height: 1.5; color: var(--color-muted);
}
.journey li::before {
    content: counter(jstep, decimal-leading-zero); position: absolute; left: 0; top: -0.1em; width: 32px; height: 32px; display: grid; place-items: center;
    border-radius: 50%; box-shadow: inset 0 0 0 var(--rule-hair) var(--color-rule-2); font: 400 var(--text-xs)/1 var(--font-body); font-variant-numeric: tabular-nums; color: var(--color-muted);
}
.journey li:not(:last-child)::after { content: ""; position: absolute; left: 15.5px; top: calc(32px + 2px); bottom: calc(-1 * var(--space-md) + 2px); width: 1px; background: var(--color-rule-2); }
.journey li.is-done { color: var(--color-ink-2); }
.journey li.is-done::before { content: "✓"; font: 500 var(--text-sm)/1 var(--font-body); color: var(--color-accent); box-shadow: inset 0 0 0 var(--rule-hair) var(--color-accent); }
.journey li.is-done::after { background: var(--color-accent); }
.journey li.is-current { color: var(--color-ink); }
.journey li.is-current::before { background: var(--color-accent); color: var(--color-accent-ink); box-shadow: 0 0 0 4px color-mix(in oklch, var(--color-accent) 22%, transparent); }
.thanks-hero .hero-actions { margin-top: var(--space-xl); }

@media (prefers-reduced-motion: reduce) {
    .btn, .field :is(input, select, textarea) { transition: background-color var(--dur-short) linear, border-color var(--dur-short) linear; }
    .btn-outline::before, .btn-dark::before, .btn-light::before { transform: none; opacity: 0; transition: opacity var(--dur-short) linear; }
    .btn-outline:hover::before, .btn-dark:hover::before, .btn-light:hover::before, .btn-outline:active::before { opacity: 1; }
    .btn:active { transform: none; }
    .btn[aria-busy="true"]::after { animation: btn-breathe 0.9s ease-in-out infinite alternate; }
}
/* Le champ ou le résumé qui reçoit le focus ne passe pas sous l'en-tête collant. */
.form :is(input, select, textarea), #form-errors { scroll-margin-top: calc(var(--header-h) + var(--space-2xl)); }
.journey-panel { margin-top: var(--space-xl); padding: var(--space-lg); border-radius: var(--radius-card); background: var(--color-paper-2); color: var(--color-ink); box-shadow: inset 0 0 0 var(--rule-hair) var(--color-rule); }
.journey-panel .journey-title { margin-top: 0; }

/* Vague 3 · communs3 */
/* Le verbe du titre : le seul mot accentué de la page, posé par un <span class="verb"> sans toucher au texte.
   Trait fixe : le titre entre déjà avec son hero, un seul mouvement d'entrée par écran. */
.verb { display: inline-block; color: var(--color-accent-2); }
.verb::after { content: ""; display: block; height: var(--rule-hair); margin-top: 0.02em; background: currentColor; transform-origin: left; }

/* Vague 3 · services3 */
/* Pages de service (services/show.blade.php) : schéma de la méthode, grille de tarifs en rangées,
   offre du hero en rangées, relevés en code. Tout est limité aux classes de ces pages : l'accueil
   et /devis gardent leurs .path et .steps. Le verbe du h1 est posé dans la vue (span .verb),
   son rendu vient du composant de communs3. */

/* Méthode : un chemin dessiné. Bande du rail sur la trame (48 px) en haut du puits, nœuds à filet
   avec l'étape en mono, liaison laiton ; les textes des étapes sous le rail, hors de la trame.
   La trame couvre aussi cette bande de rail (47c, tampon). */
.service-method .path { padding: 0; overflow: hidden; }
.service-method .steps {
    grid-template-columns: none; grid-template-rows: auto auto; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr);
    column-gap: var(--gap-columns); row-gap: 0; padding: 0 var(--space-xl);
}
.service-method .steps::before {
    grid-row: 1 / 2; inset: 0; width: auto; height: auto; z-index: 0;
    background-color: transparent;
    background-image: linear-gradient(var(--rule-blueprint) 1px, transparent 1px), linear-gradient(90deg, var(--rule-blueprint) 1px, transparent 1px);
    background-size: 48px 48px; background-position: -1px -1px;
    border-bottom: var(--rule-hair) solid var(--color-rule);
}
.service-method .steps::after { grid-row: 1 / 2; top: 50%; bottom: auto; left: var(--space-xl); right: var(--space-xl); width: auto; height: var(--rule-hair); z-index: 0; transform: none; animation: none; }
.service-method .steps li { display: grid; grid-row: 1 / span 2; grid-template-rows: subgrid; padding: 0; z-index: var(--z-base); }
.service-method .steps li::before { content: none; }
.service-method .steps h3 {
    margin: var(--space-xl) 0; padding: var(--space-md); align-self: stretch;
    background: var(--color-paper-2); border: var(--rule-hair) solid var(--color-rule-2); border-radius: var(--radius-card);
    font-size: var(--text-xl); line-height: 1.05;
}
.service-method .steps h3::before {
    content: counter(step, decimal-leading-zero); display: block; margin-bottom: var(--space-xs);
    font: 400 var(--text-xs)/1.5 var(--font-body); letter-spacing: 0; text-transform: none; color: var(--color-muted); font-variant-numeric: tabular-nums;
}
.service-method .steps p { margin: 0; padding: var(--space-lg) 0 var(--space-xl); font-size: var(--text-md); line-height: 1.55; color: var(--color-ink-2); }
@media (max-width: 60rem) {
    /* Sous 60rem, le rail passe à gauche, en marge : la liaison ne passe jamais sous le texte. */
    .service-method .steps { grid-template-columns: minmax(0, 1fr); grid-template-rows: none; grid-auto-flow: row; padding: var(--space-lg) var(--space-lg) var(--space-lg) calc(2 * var(--space-lg)); }
    .service-method .steps::before { content: none; }
    .service-method .steps::after { grid-row: auto; top: var(--space-xl); bottom: var(--space-xl); left: var(--space-lg); right: auto; width: var(--rule-hair); height: auto; }
    .service-method .steps li { display: block; grid-row: auto; }
    .service-method .steps li + li { margin-top: var(--space-lg); }
    .service-method .steps h3 { margin: 0; }
    .service-method .steps p { padding: var(--space-sm) 0 0; }
}

/* Offre du hero en formules (sécurité PHP) : rangées sous filet, nom à gauche, montant à droite
   en chiffres tabulaires, l'unité dessous ; pas de coches (le motif reste à « concerné »). */
.offer-box .offer-rate, .offer-box .offer-unit { font-variant-numeric: tabular-nums; }
.offer-box li:has(> .offer-unit) { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 0 var(--space-md); align-items: baseline; padding-left: 0; }
.offer-box li:has(> .offer-unit)::before { content: none; }
.offer-box li > .offer-rate { grid-column: 2; grid-row: 1; color: var(--color-ink); font-size: var(--text-md); white-space: nowrap; }
.offer-box li > .offer-unit { grid-column: 1 / -1; color: var(--color-muted); }

/* Les formules : une grille de tarifs en rangées pleine largeur, nom, montant et unité, détail à droite. */
.rate-rows { border-top: var(--rule-hair) solid var(--color-rule-2); }
.rate-row {
    display: grid; grid-template-columns: minmax(0, 4fr) minmax(0, 3fr) minmax(0, 5fr); gap: var(--space-md) var(--gap-columns);
    align-items: baseline; padding: var(--space-lg) 0; border-bottom: var(--rule-hair) solid var(--color-rule);
}
.rate-row > * { min-width: 0; }
.rate-row h3 { margin: 0; font-size: var(--text-2xl); line-height: 1.02; }
.rate-amount { font-family: var(--font-display); font-size: var(--text-3xl); line-height: 1; letter-spacing: var(--tracking-display); text-transform: lowercase; color: var(--color-ink); white-space: nowrap; }
.rate-amount small { font: 400 var(--text-md)/1 var(--font-body); color: var(--color-muted); }
.rate-unit { display: block; margin-top: var(--space-xs); font-size: var(--text-sm); line-height: 1.45; color: var(--color-muted); }
.rate-text p { margin: 0; color: var(--color-ink-2); }
.rate-text p + p { margin-top: var(--space-xs); }
.rate-text .btn { margin-top: var(--space-md); }
@media (max-width: 60rem) {
    .rate-row { grid-template-columns: minmax(0, 1fr) auto; }
    .rate-row h3 { font-size: var(--text-xl); }
    .rate-figure { display: contents; }
    .rate-amount { grid-column: 2; grid-row: 1; font-size: var(--text-2xl); text-align: right; }
    .rate-unit { grid-column: 1 / -1; margin-top: 0; }
    .rate-text { grid-column: 1 / -1; }
}

/* Sections propres à une page (sécurité PHP) : la liste en rangées sous filet sur toute la largeur du corps,
   versions, CVE et commandes en code. */
.service-section .prose-body { max-width: none; }
.service-list { list-style: none; margin: var(--space-lg) 0 0; padding: 0; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: var(--gap-columns); border-top: var(--rule-hair) solid var(--color-rule-2); }
.service-list li { margin: 0; padding: var(--space-md) 0; border-bottom: var(--rule-hair) solid var(--color-rule); color: var(--color-ink-2); }
.service-list li:last-child:nth-child(odd) { grid-column: 1 / -1; }
.service-section code { padding: 0.05em 0.25em; border-radius: var(--radius-chip); font-family: var(--font-outlier); font-size: 0.88em; background: var(--color-paper-3); color: var(--color-ink); overflow-wrap: anywhere; }
@media (max-width: 60rem) { .service-list { grid-template-columns: minmax(0, 1fr); } }

/* Vague 3 · apropos3 */
/* À propos, auteur, charte et pages projet : sous le bandeau, la matière Lumen (puits, relevés, rangées)
   prend le relais ; titres en un seul registre, bords gauches sur la grille de 12 colonnes. */

/* Auteur : la fonction ouvre la colonne du chapeau sous le filet, le chapeau suit sans second filet. */
@media (min-width: 60.0625rem) {
    .page-hero:not(.article-hero) > .wrap:not(.author-hero) > .author-role { margin: 0 0 var(--space-sm); padding-top: var(--space-lg); border-top: var(--rule-hair) solid var(--color-rule-2); }
    .page-hero:not(.article-hero) > .wrap:not(.author-hero) > .author-role + .lead { padding-top: 0; border-top: 0; }
    /* En-tête d'à propos « à niveau » : le chapeau en colonne 7, sur la ligne de base du titre. */
    .section-head.about-head.is-level { display: grid; grid-template-columns: minmax(0, 6fr) minmax(0, 6fr); column-gap: var(--gap-columns); align-items: baseline; }
    .section-head.about-head.is-level > p { margin: 0; }
}

/* Projets d'à propos : rangées basses, tête et texte sur la même ligne de base, toute la rangée cliquable par le lien du titre. */
.tools-grid.is-links > .tool-row { position: relative; align-items: baseline; padding-block: var(--space-lg); margin-inline: calc(-1 * var(--space-md)); }
.tools-grid.is-links .tool-row-head { align-items: baseline; }
.tools-grid.is-links .tool-row h3 a { transition: none; }
.tools-grid.is-links .tool-row h3 a::after { content: ""; position: absolute; inset: 0; }
.tools-grid.is-links .tool-row h3 a:hover { transform: none; }
.tools-grid.is-links .tool-row h3 a:focus-visible { outline: 0; }
.tools-grid.is-links > .tool-row:has(a:focus-visible) { outline: 2px solid var(--color-focus); outline-offset: -2px; }
.tools-grid.is-links .tool-row-body p { margin: 0; color: var(--color-ink-2); }
.tools-grid.is-links > .tool-row:hover h3 a { text-decoration: underline; text-decoration-thickness: var(--rule-hair); text-decoration-color: var(--color-accent); text-underline-offset: 0.18em; }

/* Clôture d'à propos et périmètre de l'auteur : des h2 au corps des sections, pas au corps courant. */
.author-scope.is-close .author-scope-col h2 { font-size: var(--text-display-s); line-height: 0.98; letter-spacing: var(--tracking-display); margin-bottom: var(--space-lg); }

/* Auteur, « spécialités, terrain, méthode » : une fiche en puits, trois colonnes séparées par des filets. */
.section > .wrap > .proofs.author-facts:first-child { margin-top: var(--space-2xl); }
.proofs.author-facts { gap: 0; padding: var(--space-lg) 0; background: var(--color-paper-2); border: var(--rule-hair) solid var(--color-rule); border-radius: var(--radius-card); }
.proofs.author-facts .proof { padding: var(--space-sm) var(--space-lg); border-top: 0; }
.proofs.author-facts .proof + .proof { border-left: var(--rule-hair) solid var(--color-rule); }
.proofs.author-facts .proof p { margin: 0; }
/* Réalisations vérifiables : rangées sous filet, le titre large, toute la rangée suit le lien. */
.proofs.author-proofs { grid-template-columns: minmax(0, 1fr); gap: 0; border-bottom: var(--rule-hair) solid var(--color-rule-2); }
.proofs.author-proofs .proof { position: relative; display: grid; grid-template-columns: minmax(0, 6fr) minmax(0, 6fr); gap: var(--space-sm) var(--gap-columns); align-items: baseline; margin-inline: 0; padding: var(--space-lg) 0; transition: background-color var(--dur-short) var(--ease-out), box-shadow var(--dur-short) var(--ease-out); }
.proofs.author-proofs .proof h3 { margin: 0; font-size: var(--text-2xl); }
.proofs.author-proofs .proof h3 a { color: var(--color-ink); text-decoration: none; }
.proofs.author-proofs .proof h3 a::after { content: ""; position: absolute; inset: 0; }
.proofs.author-proofs .proof h3 a:focus-visible { outline: 0; }
.proofs.author-proofs .proof p { margin: 0; }
.proofs.author-proofs .proof:hover, .proofs.author-proofs .proof:has(a:focus-visible) { background: var(--color-paper-2); }
.proofs.author-proofs .proof:hover { box-shadow: calc(-1 * var(--space-md)) 0 0 var(--color-paper-2), var(--space-md) 0 0 var(--color-paper-2); }
.proofs.author-proofs .proof:has(a:focus-visible) { outline: 2px solid var(--color-focus); outline-offset: 2px; }
.proofs.author-proofs .proof:hover h3 a { text-decoration: underline; text-decoration-thickness: var(--rule-hair); text-decoration-color: var(--color-accent); text-underline-offset: 0.18em; }

/* Charte : le chapeau en Geist au corps du chapô, pas en relevé mono. */
.page-content.is-doc.is-charter > h1 + p { font-family: var(--font-body); font-size: var(--text-lead); color: var(--color-ink-2); }

@media (max-width: 60rem) {
    .proofs.author-facts { grid-template-columns: minmax(0, 1fr); padding: var(--space-xs) var(--space-lg); }
    .proofs.author-facts .proof { padding: var(--space-md) 0; }
    .proofs.author-facts .proof + .proof { border-left: 0; border-top: var(--rule-hair) solid var(--color-rule); }
    .proofs.author-proofs .proof { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 40rem) {
    .about-note { padding-inline: var(--space-md); }
}
/* Grand écran : la capture de la Suite passe à droite du titre pour que le hero tienne dans l'écran. */
@media (min-width: 90rem) {
    .page-hero.is-product.is-shot:not(.article-hero) > .wrap:not(.author-hero) > h1 { grid-column: 1 / span 5; grid-row: 2; }
    .page-hero.is-product.is-shot:not(.article-hero) > .wrap:not(.author-hero) > .lead { grid-column: 1 / span 5; grid-row: 3; }
    .page-hero.is-product.is-shot:not(.article-hero) > .wrap:not(.author-hero) > .hero-actions { grid-column: 1 / span 5; grid-row: 4; }
    .page-hero.is-product.is-shot:not(.article-hero) > .wrap:not(.author-hero) > .product-visual { grid-column: 6 / -1; grid-row: 2 / span 3; align-self: start; margin-top: 0; }
}

/* Vague 3 · conversion3 */
/* Fiche de prix sur écran moyen et mobile : le nom et son drapeau sur une ligne, le montant
   sur la sienne au corps display, l'unité dessous ; le reste suit dans l'ordre du code, sans
   rangée imposée, pour qu'un lien « en savoir plus » n'empiète jamais sur la description. */
@media (max-width: 60rem) {
    .pricing:not(.is-four) .price-card {
        display: grid; grid-template-columns: minmax(0, 1fr) auto; column-gap: var(--space-md); row-gap: var(--space-xs); align-items: baseline;
        padding: var(--space-lg);
    }
    .pricing:not(.is-four) .price-card > * { grid-column: 1 / -1; min-width: 0; }
    .pricing:not(.is-four) .price-card > :is(h2, h3) { grid-column: 1; grid-row: 1; font-size: var(--text-xl); }
    .pricing:not(.is-four) .price-card > .price-flag { grid-column: 2; grid-row: 1; justify-self: end; }
    .pricing:not(.is-four) .price-card > .price-amount { margin: var(--space-xs) 0 0; font-size: var(--text-display-s); font-variant-numeric: tabular-nums; }
    .pricing:not(.is-four) .price-card > .btn { margin-top: var(--space-sm); }
    .pricing:not(.is-four) .price-card > p { margin-top: var(--space-xs); }
    .pricing:not(.is-four) .price-card > p ~ p { margin-top: 0; }
    .pricing:not(.is-four) .price-card > ul { margin: var(--space-xs) 0 var(--space-md); }
    .pricing.is-four .price-card { padding: var(--space-lg); }
}
@media (max-width: 40rem) {
    .pricing:not(.is-four) .price-card > .btn { width: 100%; }
}

/* Listes de périmètre sans coche ni croix : pas de gouttière vide devant la ligne. */
.split-card:not(.is-yes, .is-no) li { padding-left: 0; }

/* Parcours (devis, pages merci) : numéros en Geist, étapes faites en encre atténuée,
   étape en cours en aplat laiton seul, sans halo. */
.journey li::before { font: 400 var(--text-xs)/1 var(--font-body); font-variant-numeric: tabular-nums; }
.journey li.is-done::before { color: var(--color-ink-2); box-shadow: inset 0 0 0 var(--rule-hair) var(--color-rule-2); }
.journey li.is-done::after { background: var(--color-rule-2); }
.journey li.is-current::before { box-shadow: none; }

/* ==========================================================================
   Vague 3 · lecture3
   Lecture longue (guides, études de cas, glossaire, pages légales) : un seul
   registre de titres, des filets calés sur une seule mesure, le schéma dans
   un puits sur la trame de plans, les vraies mesures en relevés mono.
   ========================================================================== */

/* ---------- Titres : un seul registre, minuscules, du corps aux annexes ---------- */
:is(.article-body, .article-main, .article-rail, .page-content.is-legal, .glo-main) :is(h2, h3),
.glo-term h2, .faq-item h3 { text-transform: lowercase; }
.article-body h2,
.article-main > :is(.article-faq, .sources, .changelog, .glo-related) > h2 {
  max-width: none; margin: var(--space-3xl) 0 var(--space-lg); padding-top: var(--space-lg);
  border-top: var(--rule-hair) solid var(--color-rule-2);
  font-size: var(--text-section); line-height: 0.98; letter-spacing: var(--tracking-display);
}
.article-main > :is(.article-faq, .sources, .changelog, .glo-related) { padding-top: 0; }
.article-main > :is(.article-faq, .sources, .changelog, .glo-related) > h2 { margin-top: 0; }
/* h3 au corps --text-2xl, ramené à --text-xl au téléphone pour rester sous les h2 (32 px à 375). */
.article-main { --h3-size: clamp(var(--text-xl), 1.2vw + 1.1rem, var(--text-2xl)); }
.article-body h3 { font-size: var(--h3-size); line-height: 1.15; letter-spacing: var(--tracking-display); }
.article-body > :first-child:is(h2) { margin-top: 0; }
.article-rail :is(.takeaways, .article-toc) h2 { font-size: var(--text-2xl); line-height: 1.05; }
.author-box h2, .tool-note h2 { font-size: var(--text-2xl); line-height: 1.1; }

/* Intertitre numéroté (« Étape 1 — », « 1. ») : le numéro reste dans la ligne du titre, en Geist à chiffres
   tabulaires et en muted (le « 1 » d'Instrument Serif se lit « l » en minuscules) ;
   les étapes qui se suivent forment un chemin (bloc « Vague 4 · lecture4 »). */
.h-num { display: inline; font-family: var(--font-body); font-weight: 400; font-size: 0.8em; font-variant-numeric: tabular-nums; letter-spacing: 0; color: var(--color-muted); }

/* L'énoncé à retenir : une phrase en serif, à l'échelle d'un titre de rangée. */
.article-body blockquote {
  max-width: none; margin: var(--space-2xl) 0; padding: var(--space-lg) 0 0; border: 0; border-top: var(--rule-hair) solid var(--color-rule-2);
  font-family: var(--font-display); font-size: var(--text-2xl); line-height: 1.2; letter-spacing: var(--tracking-display); color: var(--color-ink);
}
.article-body blockquote :is(strong, p) { font-weight: var(--display-weight); color: var(--color-ink); font-size: inherit; line-height: inherit; }
.article-body blockquote code { font-size: 0.6em; }

/* Objectif chiffré d'un indicateur : un relevé, sur sa ligne. */
.article-body strong.reading { display: block; margin-top: var(--space-sm); font: 400 var(--text-xs)/1.5 var(--font-outlier); color: var(--color-ink); }

/* Trois indicateurs : un registre en colonnes, ouvert par un filet, titres et relevés alignés. */
.body-trio { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-xl) var(--gap-columns); margin: 0 0 var(--space-xl); }
.trio-item { padding-top: var(--space-md); border-top: var(--rule-hair) solid var(--color-rule); min-width: 0; }
.trio-item h3 { margin: 0 0 var(--space-sm); font-size: var(--text-title); overflow-wrap: break-word; }
.trio-item p { margin: 0; }
@media (min-width: 75rem) {
  .body-trio { grid-template-columns: repeat(3, minmax(0, 1fr)); grid-template-rows: auto auto; }
  .trio-item { display: grid; grid-template-rows: subgrid; grid-row: span 2; row-gap: var(--space-sm); }
  .trio-item h3 { margin: 0; }
  .trio-item p { font-size: var(--text-md); line-height: 1.6; }
}

/* ---------- Filets : tous calés sur la colonne de l'article ---------- */
.faq-item, .article-faq .faq-item { max-width: none; }
.faq-item :is(h3, p) { max-width: var(--measure); }
.changelog > p, .sources ul, .glo-related ul { max-width: var(--measure); }

/* Puces : un tiret fin atténué, comme « À retenir » ; le laiton reste au seuil « bon » et aux signaux. */
:is(.article-body, .sources, .glo-related) ul, .page-content.is-legal > ul:not([class]) { list-style: none; padding-left: 0; }
:is(.article-body, .sources, .glo-related) ul > li, .page-content.is-legal > ul:not([class]) > li { position: relative; padding-left: var(--space-lg); }
:is(.article-body, .sources, .glo-related) ul > li::before, .page-content.is-legal > ul:not([class]) > li::before {
  content: ""; position: absolute; left: 0; top: 0.85em; top: round(nearest, 0.85em, 1px); width: var(--space-sm); height: var(--rule-hair); background: var(--color-muted);
}

/* ---------- Sommaire : numéros en Geist, section courante en laiton ---------- */
.article-toc li span { font-family: var(--font-body); font-weight: 400; color: var(--color-muted); }
.article-toc li:has(> a[aria-current]) span { color: var(--color-accent); }

/* ---------- Ligne de méta : la catégorie en pastille à filet, minuscule ---------- */
.article-cat {
  min-height: 32px; padding: 0 var(--space-md); border-radius: var(--radius-pill); background: none;
  border: var(--rule-hair) solid var(--color-rule-2); font-size: var(--text-sm); font-weight: 500; text-transform: lowercase;
  transition: background-color var(--dur-micro) var(--ease-out), border-color var(--dur-micro) var(--ease-out);
}
.article-cat:hover { background: var(--color-paper-2); border-color: var(--color-muted); }
@media (max-width: 40rem) {
  .article-meta { flex-direction: column; align-items: flex-start; gap: var(--space-2xs); }
  .article-meta .dot { display: none; }
  .article-meta .article-cat { margin-bottom: var(--space-xs); }
}

/* ---------- Schéma : un puits à filet sur la trame de plans ---------- */
.article-figure {
  padding: var(--space-lg); border: var(--rule-hair) solid var(--color-rule); border-radius: var(--radius-card);
  background-color: var(--color-paper-2);
  background-image: linear-gradient(var(--rule-blueprint) 1px, transparent 1px), linear-gradient(90deg, var(--rule-blueprint) 1px, transparent 1px);
  background-size: 48px 48px; background-position: -1px -1px;
}
/* Légende : le filet court sur toute la largeur du puits, seul le texte s'arrête à la mesure. */
.article-figure figcaption { margin-top: var(--space-md); padding-top: var(--space-sm); padding-inline-end: max(0px, 100% - var(--measure)); border-top: var(--rule-hair) solid var(--color-rule); text-align: left; max-width: none; }
.figure-scroll { overflow-x: auto; overscroll-behavior-x: contain; scrollbar-width: thin; }
.figure-scroll:focus-visible { outline: 2px solid var(--color-focus); outline-offset: 2px; }
/* Le schéma du bandeau tient dans l'écran ; seul un schéma du corps garde un plancher de 28rem et défile. */
@media (max-width: 40rem) { .article-main .figure-scroll svg { min-width: 28rem; } }

/* Textes du SVG : Geist Mono, une seule graisse, plus de corps sous 11,5 unités ; le titre en minuscules. */
.article-figure svg text { font-family: var(--font-outlier); font-weight: 400; }
.article-figure svg text:is([font-size="9"], [font-size="9.5"], [font-size="10"], [font-size="10.5"], [font-size="11"]) { font-size: 11.5px; }
.article-figure svg text[font-size="13"][font-weight="700"] { font-family: var(--font-body); text-transform: lowercase; fill: var(--color-ink-2); }
/* Couleurs : la variable en ink-2, les cadres en filet, un seul repère laiton (le déclencheur), plus de vert ni de rouge. */
.article-figure svg :is(rect, circle)[fill="#1a7a4a"] { fill: var(--color-paper-3); }
.article-figure svg :is(rect, circle)[fill="#1a7a4a"][stroke] { stroke: var(--color-ink-2); }
.article-figure svg :is(rect, circle)[stroke="#1a7a4a"]:not([fill="#1a7a4a"]) { stroke: var(--color-rule-2); }
.article-figure svg :is(path, line, g)[stroke="#1a7a4a"] { stroke: var(--color-ink-2); }
.article-figure svg :is(path, g)[fill="#1a7a4a"], .article-figure svg circle[fill="#1a7a4a"]:not([stroke]) { fill: var(--color-ink-2); }
.article-figure svg path[fill="#1a7a4a"][fill-opacity] { fill: var(--color-ink); }
.article-figure svg text:is([fill="#1a7a4a"], [fill="#fff"], [fill="#ffffff"], [fill="#cde9d9"], [fill="#1a1a1a"]) { fill: var(--color-ink); }
.article-figure svg text[fill="#1a4fd0"] { fill: var(--color-ink-2); }
.article-figure svg text[fill="#9ad3b0"] { fill: var(--color-ink); }
.article-figure svg line[stroke="#c0392b"] { stroke: var(--color-accent); }
.article-figure svg :is(rect, path, g)[stroke="#c0392b"] { stroke: var(--color-muted); }
.article-figure svg :is(rect, path, g, circle)[fill="#c0392b"] { fill: var(--color-ink-2); }
.article-figure svg rect[fill="#c0392b"] { fill: var(--color-paper-3); stroke: var(--color-muted); }
.article-figure svg text[fill="#c0392b"], .article-figure svg g[fill="#c0392b"] text { fill: var(--color-ink-2); }
.article-figure svg [fill="#fdecea"] { fill: var(--color-paper-3); }
.article-figure svg [stroke="#e5b5ae"] { stroke: var(--color-rule-2); }
.article-figure svg [fill="#e0912f"] { fill: var(--color-paper-3); }
/* Encadré laiton (un seul par schéma) : le filet et l'intitulé en laiton, les lignes en encre. */
.article-figure svg text[fill="#8a6508"]:not([font-weight="700"]) { fill: var(--color-ink-2); }

/* Schéma de seuils redessiné en HTML : une ligne par indicateur, la plage « bon » seule en laiton. */
.vitals-scale { display: grid; gap: var(--space-lg); margin: 0; }
.vs-row { display: grid; grid-template-columns: minmax(0, 9rem) minmax(0, 1fr); gap: var(--space-xs) var(--space-lg); align-items: end; }
.vs-row dt { display: flex; flex-direction: column; }
.vs-name { font-size: var(--text-md); font-weight: 500; color: var(--color-ink); }
.vs-what { font-size: var(--text-sm); color: var(--color-muted); }
.vs-bands { display: flex; gap: var(--space-2xs); margin: 0; min-width: 0; }
.vs-band {
  flex: 1 1 0; min-width: 0; padding: 0 0 var(--space-xs); border-bottom: 2px solid var(--color-rule-2);
  font: 400 var(--text-xs)/1.4 var(--font-outlier); color: var(--color-muted); text-transform: lowercase; overflow-wrap: anywhere;
}
.vs-band.is-good { border-bottom-color: var(--color-accent); color: var(--color-ink); }
@media (max-width: 40rem) { .vs-row { grid-template-columns: minmax(0, 1fr); } .vs-row dt { flex-direction: row; align-items: baseline; gap: var(--space-xs); } }

/* ---------- Bandeau Stage : le h1 sur toute la largeur, puis la date et le chapô à gauche, le schéma à droite ---------- */
/* Sous 80rem, le schéma passe sous le chapô (48rem au plus) : en demi-colonne, ses libellés tombaient sous 12 px. */
.article-hero.is-stage .article-figure { max-width: 48rem; margin: var(--space-xl) 0 0; }
.article-stage-lead .lead { margin: var(--space-lg) 0 0; max-width: 60ch; color: var(--color-ink-2); }
@media (min-width: 80rem) {
  .article-hero.is-stage > .wrap { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: var(--gap-columns); align-items: start; }
  .article-hero.is-stage > .wrap > * { grid-column: 1 / span 4; min-width: 0; }
  .article-hero.is-stage > .wrap > :is(.breadcrumb, h1) { grid-column: 1 / -1; }
  .article-hero.is-stage > .wrap > .article-figure { grid-column: 5 / -1; grid-row: 3 / span 2; max-width: none; margin: var(--space-md) 0 0; align-self: start; }
}

/* Relevé des données (étude de cas) : des rangées sous filet, pas une boîte. */
.dataset { padding: var(--space-md) 0 0; border-radius: 0; background: none; border-top: var(--rule-hair) solid var(--color-rule-2); }
.dataset h2 { font-size: var(--text-2xl); line-height: 1.05; }
.dataset dl { gap: 0 var(--space-lg); }
.dataset :is(dt, dd) { padding: var(--space-xs) 0; border-top: var(--rule-hair) solid var(--color-rule); }

/* ---------- Fin d'article : navigation sur une colonne quand il n'y a qu'un voisin ---------- */
:is(.article-annex, .glo-foot) .guide-nav.is-single { grid-template-columns: minmax(0, 1fr); }
:is(.article-annex, .glo-foot) .guide-nav .gn-title { font-size: var(--text-title); }

/* « Continuer la lecture » : des rangées à filet, le titre en serif minuscule, comme la navigation. */
/* Le registre porte les filets du haut et du bas ; chaque rangée suivante ouvre par le sien. */
.article-related .guide-links { grid-template-columns: minmax(0, 1fr); gap: 0; border-block: var(--rule-hair) solid var(--color-rule); }
.article-related .guide-link + .guide-link { border-top: var(--rule-hair) solid var(--color-rule); }
.article-related .guide-link {
  min-height: 0; padding: var(--space-md) var(--space-sm); border-radius: 0; box-shadow: none; border-top: 0;
  transition: background-color var(--dur-short) var(--ease-out);
}
.article-related .guide-link:hover { background: var(--color-paper-2); box-shadow: none; }
.article-related .guide-link strong {
  font-family: var(--font-display); font-size: var(--text-title); font-weight: var(--display-weight); line-height: 1.15;
  letter-spacing: var(--tracking-display); text-transform: lowercase; text-wrap: balance;
}
.article-related .guide-link:focus-visible { outline-offset: -2px; }

/* ---------- Pages légales : le même registre, filets et puces du guide ---------- */
.page-content.is-legal > h2 { font-size: var(--text-section); line-height: 0.98; }
.page-content.is-legal .doc-card h2 { font-size: var(--text-2xl); }

/* ---------- Glossaire : le terme au registre des intertitres, les étiquettes en Geist, sans rouge ---------- */
.glo-term h2 { font-size: var(--text-section); line-height: 0.98; letter-spacing: var(--tracking-display); }
.glo-side h2 { font-size: var(--text-2xl); line-height: 1.05; }
/* L'intertitre en marge et le texte qu'il ouvre partent du même filet (la marge haute du texte était
   écrasée par la règle des paragraphes, d'où un intertitre décalé de 64 px). */
@media (min-width: 60.0625rem) {
  .page-content.is-doc.is-legal > h2 + * { margin-top: var(--space-2xl); }
}

/* Vague 3 · index3
   Pages d'index : /guides (et ses rubriques), /outils, /outils/version-php, /ressources, /glossaire, /etudes-de-cas.
   Aucun jeton nouveau ; pas de règle .verb (composant de communs3). */

/* Bandeau d'index : titre à gauche sur sept colonnes, chapô et signature à droite, puces de rubrique sous les deux. */
@media (min-width: 60.0625rem) {
    .page-hero.is-listing:not(.article-hero) > .wrap:not(.author-hero) { align-items: start; }
    .page-hero.is-listing:not(.article-hero) > .wrap:not(.author-hero) > h1 { grid-column: 1 / span 7; grid-row: 2 / span 2; max-width: none; margin-bottom: 0; text-wrap: balance; }
    .page-hero.is-listing:not(.article-hero) > .wrap:not(.author-hero) > .lead { grid-column: 8 / -1; grid-row: 2; }
    .page-hero.is-listing:not(.article-hero) > .wrap:not(.author-hero) > .hero-byline { grid-column: 8 / -1; grid-row: 3; }
    .page-hero.is-listing:not(.article-hero) > .wrap:not(.author-hero) > .cat-nav { grid-column: 1 / -1; grid-row: 4; margin-top: var(--space-2xl); }
}
.page-hero.is-listing .cat-nav { margin: var(--space-xl) 0 0; }
@media (max-width: 40rem) {
    /* Puces plus compactes au téléphone : deux rangées au plus. */
    .page-hero.is-listing .cat-nav { gap: var(--space-2xs); }
    .page-hero.is-listing .cat-nav a { min-height: 36px; padding-inline: var(--space-sm); font-size: var(--text-xs); }
}
/* Tablette : les 21 lettres se partagent la largeur au lieu de défiler hors champ. */
@media (min-width: 40.0625rem) and (max-width: 60rem) {
    .gh-tools .gh-azbar { flex: 1 1 100%; }
    .gh-tools .gh-azbar a { flex: 1 1 0; min-width: 24px; }
}


/* Guides : les deux guides de référence dans un puits paper-2, en grand, avant les rangées par date. */
.guide-refs { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); margin: 0 0 var(--space-3xl); background: var(--color-paper-2); border: var(--rule-hair) solid var(--color-rule-2); border-radius: var(--radius-card); overflow: hidden; }
.guide-ref { position: relative; display: grid; grid-template-rows: auto auto 1fr auto; gap: var(--space-md); padding: var(--space-xl); transition: background-color var(--dur-short) var(--ease-out); }
.guide-ref + .guide-ref { border-left: var(--rule-hair) solid var(--color-rule); }
.guide-ref h2 { margin: 0; font-size: var(--text-display-s); line-height: 0.98; text-wrap: balance; }
.guide-ref h2 a { color: var(--color-ink); text-decoration: underline; text-decoration-color: transparent; text-decoration-thickness: var(--rule-hair); text-underline-offset: 0.12em; transition: text-decoration-color var(--dur-micro) var(--ease-out); }
.guide-ref h2 a::after { content: ""; position: absolute; inset: 0; }
.guide-ref h2 a:focus-visible { outline: none; }
.guide-ref:has(h2 a:focus-visible) { outline: 2px solid var(--color-focus); outline-offset: -2px; }
.guide-ref:is(:hover, :has(h2 a:focus-visible)) { background: var(--color-paper-3); }
.guide-ref:is(:hover, :has(h2 a:focus-visible)) h2 a { text-decoration-color: var(--color-accent); }
.guide-ref p { margin: 0; max-width: var(--measure); font-size: var(--text-sm); color: var(--color-ink-2); }
.guide-ref-foot { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 var(--space-md); font: 400 var(--text-xs)/1.5 var(--font-outlier); color: var(--color-muted); font-variant-numeric: tabular-nums; }
.guide-ref-time { font-size: var(--text-sm); color: var(--color-ink); }
/* Les deux guides vedettes s'empilent jusqu'à 56rem : côte à côte, leur titre en display passait sur cinq lignes de seize signes. */
@media (max-width: 56rem) {
    .guide-refs { grid-template-columns: minmax(0, 1fr); }
    .guide-ref { padding: var(--space-lg); }
    .guide-ref + .guide-ref { border-left: 0; border-top: var(--rule-hair) solid var(--color-rule); }
}

/* Outils : étiquette et numéro en Geist, pas de glissement ; le premier outil (version PHP) en puits. */
.tools-index .tool-row .tag, .tools-index .tool-row .tag.is-wp { font-family: var(--font-body); text-transform: lowercase; }
.tools-index .tools-grid > .tool-row:hover :is(h2, h3), .tools-index .tool-row h3 a:hover { transform: none; }
.tools-index .tools-grid > .tool-row:first-child { padding-block: var(--space-xl); background: var(--color-paper-2); border-radius: var(--radius-field); }
.tools-index .tools-grid > .tool-row:first-child + .tool-row { border-top-color: transparent; }

/* Vérificateur PHP : le résultat n'est plus une carte dans la carte, juste un filet de tête à la couleur du verdict. */
.vp-panel .vp-box:not(.alert) { padding: var(--space-lg) 0 0; background: none; border: 0; border-top: var(--rule-hair) solid var(--color-rule-2); border-radius: 0; }
.vp-panel .vp-verdict-warn:not(.alert) { border-top-color: var(--color-accent); }
.vp-panel .vp-verdict-ok:not(.alert) { border-top-color: var(--color-live); }
.vp-panel .vp-box > h2 { font-size: var(--text-2xl); line-height: 1.05; color: var(--color-ink); }
.vp-panel .vp-box > h2 { align-items: flex-start; }
.vp-panel .vp-box > h2::before { margin-top: 0.42em; }
/* Le résultat reçoit le focus après l'analyse : le cadre se détache du texte maintenant que la boîte n'a plus de marge. */
.vp-panel .vp-box:not(.alert):focus { outline-offset: var(--space-sm); }

/* Vague 4 · services4
   Pages de service : quatre compositions sous le hero au lieu d'une seule grille répétée.
   Le dossier propre à la page (sécurité PHP) tient en une section à parties sous filet ; les
   symptômes passent en grandes lignes sur toute la largeur ; les formules en grille de tarifs
   dans un puits ; FAQ et guides en bande de fin, puis les autres services. Écarts alternés
   entre --section-gap-s et --section-gap-l. */
.service-see-also { margin-top: var(--space-md); font-size: var(--text-sm); }
.service-see-also a { color: var(--color-muted); text-decoration-color: var(--color-rule-2); text-underline-offset: 0.25em; transition: color var(--dur-short) var(--ease-out), text-decoration-color var(--dur-short) var(--ease-out); }
.service-see-also a:hover { color: var(--color-ink); text-decoration-color: var(--color-accent); }

.service-dossier .dossier-part + .dossier-part { margin-top: var(--space-2xl); padding-top: var(--space-2xl); border-top: var(--rule-hair) solid var(--color-rule); }
.service-dossier .dossier-part.is-columns > .section-head { margin-bottom: var(--space-xl); }

.section.service-symptoms { padding-block: var(--section-gap-l); }
.service-symptoms .section-head { margin-bottom: var(--space-xl); }
.service-symptoms .symptoms { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: var(--gap-columns); }
.service-symptoms .symptoms li { padding: var(--space-lg) 0 var(--space-lg) var(--space-lg); font-size: var(--text-xl); font-weight: 400; line-height: 1.35; color: var(--color-ink-2); }
.service-symptoms .symptoms li:last-child:nth-child(odd) { grid-column: 1 / -1; }

.section.service-offers { border-top: 0; }
/* Formules (sécurité PHP) : la grille de tarifs du thème, des rangées sous filet sans cases ;
   nom, montant en chiffres tabulaires et unité, puis une colonne de prose à 16 px. */
.service-offers .rate-row { grid-template-columns: minmax(0, 4fr) minmax(0, 3fr) minmax(0, 5fr); padding: var(--space-xl) 0; }
.service-offers .rate-amount { font-size: var(--text-3xl); font-variant-numeric: tabular-nums; }
.service-offers .rate-amount small { font: 400 var(--text-xs)/1 var(--font-outlier); }
.service-offers .rate-text p { font-size: var(--text-md); line-height: 1.55; }

.section.service-close { padding-block: var(--section-gap-s); }
.service-close-grid { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); gap: var(--space-3xl) var(--gap-columns); align-items: start; }
.service-close-grid > * { min-width: 0; }
.close-faq, .close-guides { grid-column: 1 / -1; }
.service-close-grid:not(:has(> .close-guides)) .close-faq { grid-column: 1 / span 8; }
/* Deux rangées pleines, la tête en colonnes 1 à 4, la FAQ puis les guides en colonnes 5 à 12 : plus de
   colonne gauche vide sous une FAQ plus courte que la liste des guides. */
@media (min-width: 60.0625rem) {
    .service-close-grid:has(> .close-guides) > div { display: grid; grid-template-columns: subgrid; align-items: start; }
    .service-close-grid:has(> .close-guides) > div > .section-head { grid-column: 1 / span 4; margin: 0; }
    .service-close-grid:has(> .close-guides) > div > :is(.faq, .guide-links) { grid-column: 5 / -1; }
}
.service-close .section-head { margin-bottom: var(--space-xl); }
.close-guides .guide-links { grid-template-columns: minmax(0, 1fr); gap: 0; border-top: var(--rule-hair) solid var(--color-rule); }
.close-guides .guide-link { min-height: 0; gap: var(--space-xs); padding: var(--space-md) 0; border-radius: 0; box-shadow: none; border-bottom: var(--rule-hair) solid var(--color-rule); }
.close-guides .guide-link:hover, .close-guides .guide-link:active { background: none; box-shadow: none; }
.close-guides .guide-link strong { text-decoration: underline; text-decoration-color: transparent; text-underline-offset: 0.25em; transition: text-decoration-color var(--dur-short) var(--ease-out); }
.close-guides .guide-link:hover strong { text-decoration-color: var(--color-accent); }

@media (max-width: 60rem) {
    .service-symptoms .symptoms { grid-template-columns: minmax(0, 1fr); }
    .service-symptoms .symptoms li { font-size: var(--text-lg); }
    .service-offers .rate-row { grid-template-columns: minmax(0, 1fr) auto; padding: var(--space-lg) 0; }
    .service-offers .rate-amount { font-size: var(--text-2xl); }
    .close-faq, .close-guides, .service-close-grid:not(:has(> .close-guides)) .close-faq { grid-column: 1 / -1; }
    .service-close-grid { gap: var(--space-2xl) var(--gap-columns); }
}
@media (max-width: 40rem) {
    /* Sur téléphone, le h1 du hero reste au-dessus des h2 (--text-display-s) et le bas du hero égale au moins le haut. */
    .service-hero { padding: var(--space-xl) 0 var(--space-2xl); }
    .service-hero h1 { font-size: var(--text-display); }
}

/* ============================================================


   Vague 4 · lecture4
   Lecture longue : le schéma en scène dans le bandeau de tout article qui en a
   un, les étapes numérotées en chemin, l'annexe (sources, historique,
   glossaire, auteur) dans la bande paper-2 de la page, sur deux colonnes.
   ========================================================================== */

/* ---------- Ligne de méta : des filets entre les entrées, jamais en bout de ligne ----------
   Chaque entrée porte son filet à gauche, dans l'espacement ; la marge négative et le clip-path
   rognent celui d'une entrée qui ouvre une ligne. Le contour de focus reste visible. */
@media (min-width: 40.0625rem) {
  .article-meta { column-gap: var(--space-lg); margin-left: calc(-1 * var(--space-lg)); padding-left: var(--space-lg); clip-path: inset(-1em -1em -1em calc(var(--space-lg) - 6px)); }
  .article-meta .dot { display: none; }
  .article-meta > :not(.dot) { position: relative; }
  .article-meta > :not(.dot, :first-child)::before {
    content: ""; position: absolute; left: calc(-0.5 * var(--space-lg)); top: 50%; width: var(--rule-hair); height: 1em; translate: 0 -50%; background: var(--color-rule-2);
  }
}

/* ---------- Bandeau Stage : le schéma à droite tient dans l'écran du téléphone ---------- */
.article-hero.is-stage .article-stage-lead .lead { margin-top: var(--space-lg); }
.article-hero .figure-scroll svg { min-width: 0; }
@media (max-width: 40rem) {
  /* Le puits va jusqu'aux bords de l'écran : le dessin gagne la largeur des gouttières. */
  .article-hero.is-stage .article-figure { margin-inline: calc(-1 * var(--gutter)); padding-inline: var(--space-md); border-inline: 0; border-radius: 0; }
  .article-hero.is-stage .article-figure figcaption { padding-inline: 0; }
}

/* Un texte du schéma que le tracé traverse se détache sur le fond du puits. */
.article-figure svg text { paint-order: stroke; stroke: var(--color-paper-2); stroke-width: 4px; stroke-linejoin: round; }

/* ---------- Étapes numérotées : un chemin, un filet vertical d'un nœud à l'autre ---------- */
.body-path { margin: var(--space-xl) 0 var(--space-2xl); padding-left: var(--space-xl); }
.path-step { position: relative; }
.path-step + .path-step { margin-top: var(--space-xl); }
.path-step > h3 { position: relative; margin: 0 0 var(--space-sm); }
.path-step > h3::before {
  content: ""; position: absolute; left: calc(-1 * var(--space-xl)); top: calc(0.575em - 5px); width: 9px; height: 9px; box-sizing: border-box;
  border: var(--rule-hair) solid var(--color-ink-2); border-radius: 50%; background: var(--color-paper);
}
.path-step:not(:last-child)::before {
  content: ""; position: absolute; left: calc(-1 * var(--space-xl) + 4px); top: calc(var(--h3-size) * 0.575 + 5px); bottom: calc(-1 * var(--space-xl) - var(--h3-size) * 0.575 + 5px);
  width: var(--rule-hair); background: var(--color-rule-2);
}
.path-step > :last-child { margin-bottom: 0; }

/* ---------- Annexe : la bande paper-2 de la page, deux colonnes, titres au corps xl ---------- */
.article-annex { background: var(--color-paper-2); border-block: var(--rule-hair) solid var(--color-rule); }
.article-annex + .article-related { border-top: 0; }
.article-annex-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-2xl) var(--gap-columns); align-items: start; }
.article-annex-grid > * { min-width: 0; margin: 0; }
.article-annex :is(.sources, .changelog, .glo-related) > h2, .article-annex .author-box h2 {
  max-width: none; margin: 0 0 var(--space-md); padding-top: var(--space-md); border-top: var(--rule-hair) solid var(--color-rule-2);
  font-size: var(--text-xl); line-height: 1.1; letter-spacing: var(--tracking-display); text-transform: lowercase;
}
.article-annex .author-box { padding: 0; border-top: 0; }
.article-annex :is(.sources ul, .glo-related ul, .changelog > p) { max-width: none; }
.article-annex .glo-related li span { color: var(--color-ink-2); }
.article-annex .changelog li { border-bottom-color: var(--color-rule-2); }
.article-annex .guide-nav { grid-column: 1 / -1; border-color: var(--color-rule-2); }
.article-annex .guide-nav a + a { border-left-color: var(--color-rule-2); }
.article-annex .guide-nav a:hover { background: var(--color-paper-3); }
@media (max-width: 60rem) { .article-annex-grid { grid-template-columns: minmax(0, 1fr); } }
@media (max-width: 40rem) { .article-annex .guide-nav a + a { border-top-color: var(--color-rule-2); } }
/* Vague 4 · accueil4 */
/* Accueil : tête et chapeau côte à côte (services, tarifs, projets, guides), tête empilée
   (WordPress, méthode), colonne de tête à gauche (pourquoi, FAQ). Projets et guides en puits
   (vague 5, bloc accueil5). */

/* Hero : coupe équilibrée du titre ; le bas du héros resserré (relevé et marge de pied à 24 px) fait entrer
   le filet des engagements dans le pli de 1440 × 900, sans toucher au titre, à la phrase ni au bouton. */
#hero-title { text-wrap: balance; }
@media (min-width: 60.0625rem) {
    .hero { padding-bottom: var(--space-lg); }
    .hero-facts { margin-top: var(--space-lg); }
}

/* Console : le pied est un relevé, en minuscules comme le reste de la mono. */
.console-foot { text-transform: lowercase; }
/* Console étroite : onglets sur une rangée qui défile dans le puits ; les lignes du journal
   passent à la ligne sous leur message, l'heure en retrait suspendu (rangée flex de base). */
@container (max-width: 440px) {
    .console-tabs { display: flex; flex-wrap: nowrap; width: 100%; overflow-x: auto; scrollbar-width: none; }
    .console-tab { flex-shrink: 0; padding: 0 var(--space-sm); }
    .console-head, .console-foot { padding-inline: var(--space-md); }
    .console-body { padding-inline: var(--space-md); }
}

/* Têtes de section propres à l'accueil. */
.section-head.is-stacked > p { margin-top: var(--space-md); }
.section-head.is-posed { margin-bottom: var(--space-xl); }
.section-head.is-posed > p { margin-top: var(--space-sm); }

/* Services : le code et « voir la méthode » passent à la ligne entre eux, jamais au milieu du code. */
@media (max-width: 60rem) {
    .service-row { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--space-xs) var(--space-md); }
    .service-row .service-more { order: 1; margin-left: auto; }
    .service-row > :is(h3, p) { order: 2; flex: 1 1 100%; }
}

/* WordPress : tuiles en colonne, le pied (code, lien) en bas et qui passe à la ligne au besoin. */
.wp-tile { display: flex; flex-direction: column; align-items: stretch; }
.wp-tile-foot { margin-top: auto; display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: var(--space-xs) var(--space-md); padding-top: var(--space-md); }
/* La grande tuile : « 500 » en chiffre display, « http » en unité mono, au milieu de la hauteur. */
.wp-tile .service-code.is-figure { display: flex; align-items: baseline; gap: var(--space-sm); font-size: var(--text-md); line-height: 1; letter-spacing: 0; }
.service-code.is-figure .unit { font: 400 var(--text-md)/1 var(--font-outlier); color: var(--color-muted); text-transform: lowercase; }
.service-code.is-figure .figure { font-family: var(--font-display); font-size: var(--text-display); line-height: 0.9; letter-spacing: var(--tracking-display); color: var(--color-ink); }

/* Méthode, sous la fiche de tarifs : plus de puits, la ligne des étapes suffit. */
#tarifs .method { margin-top: var(--section-gap); }
#tarifs .method .path { padding: 0; background: none; border: 0; border-radius: 0; }
#tarifs .method .steps li::before { background: var(--color-paper); }

/* Bandeau des pages : sur téléphone, le h1 garde la taille display et passe un cran au-dessus
   du titre de l'appel final, qui est lui aussi à --text-display. */
@media (max-width: 40rem) {
    .page-hero:not(.article-hero) h1 { font-size: max(var(--text-display), 3rem); line-height: 0.98; }
}

/* Pied : le flux RSS sous le texte de marque, collé à son paragraphe. */
@media (min-width: 60.0625rem) {
    .footer-brand { grid-template-columns: repeat(3, minmax(0, 1fr)); }
    .footer-brand p, .footer-feed { grid-column: 1 / span 2; }
}
.footer-brand p + .footer-feed { margin-top: calc(-1 * var(--space-sm)); }
/* Vague 4 · index4
   Pages d'index : rubriques collantes et rangées regroupées par rubrique (/guides), dates en texte et
   durées en relevé, glossaire allégé au téléphone, lettres courtes en grille sur grand écran.
   Aucun jeton nouveau ; une seule propriété locale, la hauteur de la barre des rubriques. */

/* Barre des rubriques : collante sous l'en-tête pendant toute la liste (recette de .gh-tools), sur le fond de la page. */
.is-guide-list { --cat-bar-h: calc(44px + 2 * var(--space-xs) + 2 * var(--space-2xs) + var(--rule-hair)); }
.cat-bar {
    position: sticky; top: calc(var(--header-h) + var(--space-sm)); z-index: var(--z-sticky);
    margin: 0 0 var(--space-2xl); padding: var(--space-xs) 0;
    background: var(--color-paper); border-bottom: var(--rule-hair) solid var(--color-rule);
    box-shadow: 0 0 0 100vmax var(--color-paper); clip-path: inset(0 -100vmax);
}
/* Une seule rangée qui défile au besoin ; le retrait garde l'anneau de focus entier. Chrome ne fait pas défiler une pastille
   à moitié visible quand elle prend le focus : la marge de défilement de 40 % la sort toujours de la zone utile, et le
   focus clavier la ramène entière (une marge de 24 px arrêtait le défilement 17 px avant la fin, à 375 px). */
.cat-bar .cat-nav { flex-wrap: nowrap; gap: var(--space-xs); margin: 0 calc(-1 * var(--space-2xs)); padding: var(--space-2xs); overflow-x: auto; scroll-padding-inline: 40%; scrollbar-width: none; }
.cat-bar .cat-nav::-webkit-scrollbar { display: none; }
.cat-bar .cat-nav a { flex: none; }


/* La date dans la police du texte, la durée seule en relevé mono. */
.guide-card-time, .guide-ref-time { font-family: var(--font-outlier); }
.guide-ref-foot { font-family: var(--font-body); }
/* Guides de référence : rubrique, durée et date sur une même ligne en tête du puits. */
.guide-ref { grid-template-columns: minmax(0, 1fr) auto; grid-template-rows: auto auto 1fr; align-items: baseline; }
.guide-ref > .guide-card-cat { grid-column: 1; grid-row: 1; }
.guide-ref > .guide-ref-foot { grid-column: 2; grid-row: 1; }
.guide-ref > :is(h2, p) { grid-column: 1 / -1; }
.guide-ref > p { align-self: start; }


/* Page de rubrique : la phrase de fin sous la liste de lecture. */
.is-guide-list .gh-foot { max-width: none; margin-top: 0; font-size: var(--text-md); line-height: 1.5; }

/* ---------- Glossaire ---------- */
/* Domaines : description entière, coupée à trois lignes par le rendu, jamais au milieu d'un mot dans le DOM. */
.gh-card p { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; line-clamp: 3; overflow: hidden; }
/* Libellés de domaine en minuscules, comme les cartes de domaine et les rubriques des guides. */
.gh-tag { text-transform: lowercase; }
/* Phrase de fin : dans la colonne des listes, au corps du chapô ; moins de vide avant le pied. */
.gh-index > .gh-foot { max-width: var(--measure); font-size: var(--text-lead); line-height: 1.5; }
.section-paper:has(.gh-index) { padding-bottom: var(--space-3xl); }

/* Grand écran : grille de douze colonnes ; une lettre de dix termes et plus occupe la rangée, les autres
   en partagent une à trois. La lettre reste dans la première colonne, les listes partent toutes de la deuxième. */
@media (min-width: 60.0625rem) {
    .gh-index { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: var(--gap-columns); }
    .gh-index > .gh-letter { grid-column: span 4; grid-template-columns: subgrid; }
    .gh-index > .gh-letter > h3 { grid-column: 1; }
    .gh-index > .gh-letter > .gh-list { grid-column: 2 / -1; columns: auto; }
    .gh-index > .gh-letter:has(.gh-entry:nth-child(10)) { grid-column: 1 / -1; }
    /* Trois colonnes calées sur celles des lettres courtes : l'écart vaut une colonne de la grille et deux gouttières. */
    .gh-index > .gh-letter:has(.gh-entry:nth-child(10)) > .gh-list { columns: 3; column-gap: calc((100% - 10 * var(--gap-columns)) / 11 + 2 * var(--gap-columns)); }
    .gh-index > .gh-foot { grid-column: 2 / -1; }
}

/* La barre de lettres défile, donc rogne ce qui dépasse : un jour de 2xs garde le contour de focus entier, et la marge
   de défilement de 40 % fait défiler la lettre qui prend le focus même à moitié visible (voir .cat-bar .cat-nav). */
.gh-tools .gh-azbar { margin: calc(-1 * var(--space-2xs)); padding: var(--space-2xs); scroll-padding-inline: 40%; }

/* Téléphone : une seule rangée de lettres de 44 px qui défile ; le filtre quitte la partie collante et reste dans le flux. */
@media (max-width: 40rem) {
    .gh-tools { display: contents; }
    .gh-tools .gh-azbar {
        position: sticky; top: calc(var(--header-h) + var(--space-sm)); z-index: var(--z-sticky);
        display: flex; flex-wrap: nowrap; gap: var(--space-3xs); margin: 0 calc(-1 * var(--space-2xs)) var(--space-md); padding: var(--space-xs) var(--space-2xs); overflow-x: auto; scroll-padding-inline: 40%;
        background: var(--color-paper-2); border-bottom: var(--rule-hair) solid var(--color-rule);
        box-shadow: 0 0 0 100vmax var(--color-paper-2); clip-path: inset(0 -100vmax);
    }
    .gh-tools .gh-azbar a { flex: none; min-width: 44px; height: 44px; }
    .gh-filter { margin: 0 0 var(--space-xl); }
    .gh-letter { scroll-margin-top: calc(var(--header-h) + var(--space-sm) + 44px + 2 * var(--space-xs) + var(--space-lg)); }
}

/* Téléphone : quand la pilule de l'en-tête s'efface, les barres collantes montent avec elle, sans laisser de jour au-dessus. */
@media (max-width: 40rem), (max-height: 30rem) {
    .cat-bar, .gh-tools, .gh-tools .gh-azbar { transition: transform var(--dur-micro) var(--ease-out); }
    body:has(.site-header.is-hidden:not(:focus-within)) :is(.cat-bar, .gh-tools, .gh-tools .gh-azbar) { transform: translateY(calc(-1 * (var(--header-h) + var(--space-sm)))); transition-timing-function: var(--ease-in); }
}
@media (prefers-reduced-motion: reduce) {
    .cat-bar, .gh-tools, .gh-tools .gh-azbar { transition: none; }
}

/* Outil version PHP : le verbe « annonce » est suivi de « -t-il ». En ligne, le filet posé en absolu sous le mot,
   le trait d'union reste collé au verbe ; le tracé et la couleur restent ceux de .verb. */
.page-hero.is-listing h1 .verb { position: relative; display: inline; }
.page-hero.is-listing h1 .verb::after { position: absolute; left: 0; right: 0; bottom: 0.02em; margin: 0; }
/* Vague 4 · conversion4 */
/* Fiche de prix sur écran moyen : l'écart des largeurs se resserre et le puits gagne de la place,
   pour qu'aucun bouton ne déborde de la colonne la plus étroite. */
@media (min-width: 60.0625rem) and (max-width: 75rem) {
    .pricing:not(.is-four):not(.is-pay) { grid-template-columns: minmax(0, 5fr) minmax(0, 4fr) minmax(0, 4fr); }
    .pricing:not(.is-four):not(.is-pay) .price-card { padding: var(--space-lg); }
}
/* La note de la fiche devient la dernière rangée du puits, sur toute sa largeur, sous un filet. */
@media (min-width: 60.0625rem) {
    .pricing:not(.is-four):not(.is-pay):has(+ .pricing-note) { border-bottom-left-radius: 0; border-bottom-right-radius: 0; }
    .pricing:not(.is-four):not(.is-pay) + .pricing-note {
        max-width: none; margin-top: 0; padding-block: var(--space-md); padding-inline: var(--space-xl) max(var(--space-xl), 100% - 110ch);
        background: var(--color-paper-2); border: var(--rule-hair) solid var(--color-rule); border-top: 0; border-radius: 0 0 var(--radius-card) var(--radius-card);
    }
}

/* Tarifs, « ce qu'une intervention couvre » : les deux listes dans un seul puits, coupé par un filet
   comme la grille de prix au-dessus. À gauche le forfait, le montant en chiffre serif et l'euro en relevé ;
   à droite le reste, même tête et mêmes filets, en encre secondaire. */
.split.is-rates { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0; align-items: stretch; background: var(--color-paper-2); border: var(--rule-hair) solid var(--color-rule); border-radius: var(--radius-card); }
.split.is-rates .split-card, .split.is-rates .split-card.is-rate { padding: var(--space-xl); background: none; border: 0; border-radius: 0; color: var(--color-ink); }
.split.is-rates .split-card.is-aside { border-left: var(--rule-hair) solid var(--color-rule); }
.split.is-rates .split-card h3 { margin-bottom: var(--space-lg); font-size: var(--text-title); line-height: 1.2; }
.scope-figure { font-variant-numeric: tabular-nums; color: var(--color-ink); white-space: nowrap; }
.scope-figure small { font: 400 var(--text-sm)/1 var(--font-outlier); color: var(--color-muted); }
.split.is-rates .is-rate ul { border-top-color: var(--color-rule-2); }
.split.is-rates .is-rate li { color: var(--color-ink); }
.split.is-rates .is-aside h3 { color: var(--color-ink-2); }
.split.is-rates .is-aside li { color: var(--color-ink-2); }
@media (max-width: 60rem) {
    .split.is-rates { grid-template-columns: minmax(0, 1fr); }
    .split.is-rates .split-card, .split.is-rates .split-card.is-rate { padding: var(--space-lg); }
    .split.is-rates .split-card.is-aside { border-left: 0; border-top: var(--rule-hair) solid var(--color-rule); }
}

/* Appel final, partout : la section se pose sur le mât du pied (écart court en bas) ; au-dessus,
   l'écart courant des sections, que plus rien ne replie. Sur grand écran, la grille des rangées scindées :
   la question en colonne 1, à droite (colonne 7, même x que les rangées au-dessus), alignés en haut,
   la réponse, le bouton dessous, puis le pied d'appel d'/agences. */
.section:has(> .wrap > .cta-band:only-child) { padding-bottom: var(--space-2xl); }
@media (min-width: 60.0625rem) {
    .cta-band { grid-template-columns: minmax(0, 6fr) minmax(0, 6fr); grid-template-rows: auto 1fr; }
    .cta-band:has(> .cta-band-foot) { grid-template-rows: auto auto 1fr; }
    .cta-band > div:first-child { grid-column: 1 / -1; grid-row: 1 / -1; display: grid; grid-template-columns: subgrid; grid-template-rows: subgrid; }
    .cta-band > div:first-child > h2 { grid-column: 1; grid-row: 1 / -1; max-width: none; }
    .cta-band > div:first-child > p { grid-column: 2; grid-row: 1; margin-top: 0; }
    .cta-band-actions { grid-column: 2; grid-row: 2; }
    .cta-band > .cta-band-foot { grid-column: 2; grid-row: 3; flex-direction: column; justify-content: flex-start; }
}
/* Téléphone : le titre de l'appel reste un cran sous le h1 de la page (display-s), au corps des sections. */
@media (max-width: 40rem) {
    .cta-band h2 { font-size: var(--text-section); }
}

/* Devis : « ensuite » quitte sa bande et vient sous les engagements, à gauche du formulaire,
   en parcours vertical (nœuds et trait de liaison). Le laiton reste au bouton d'envoi :
   anneaux et trait en filet, numéros en Geist. */
.devis-next { min-width: 0; }
.devis-next h2 { margin-bottom: var(--space-xl); font-size: var(--text-display-s); }
.devis-next .steps { grid-template-columns: minmax(0, 1fr); gap: var(--space-lg); }
.devis-next .steps::before { left: 24px; right: auto; top: 24px; bottom: 24px; width: var(--rule-hair); height: auto; }
.devis-next .steps::after { content: none; }
.devis-next .steps li { padding: var(--space-sm) 0 0 calc(48px + var(--space-lg)); font-size: var(--text-md); line-height: 1.5; color: var(--color-ink-2); }
.devis-next .steps li::before { box-shadow: inset 0 0 0 var(--rule-hair) var(--color-rule-2); font-family: var(--font-body); font-variant-numeric: tabular-nums; color: var(--color-ink-2); }
@media (min-width: 60.0625rem) {
    .devis-grid { grid-template-rows: auto 1fr; row-gap: var(--space-2xl); }
    .devis-grid > .devis-intro { grid-column: 1; grid-row: 1; position: static; }
    .devis-grid > .form-card { grid-column: 2; grid-row: 1 / span 2; }
    .devis-grid > .devis-next { grid-column: 1; grid-row: 2; }
}

/* Formulaires. Le select prend le chevron fin de la FAQ (deux traits de 1 px, en jetons) ;
   la case est dessinée : bord comme les champs (contraste 3:1 sur le fond), coche laiton. */
.field select:not([multiple]) {
    appearance: none; padding-right: var(--space-xl);
    background-image:
        linear-gradient(45deg, transparent calc(50% - 0.6px), var(--color-ink-2) calc(50% - 0.6px), var(--color-ink-2) calc(50% + 0.6px), transparent calc(50% + 0.6px)),
        linear-gradient(-45deg, transparent calc(50% - 0.6px), var(--color-ink-2) calc(50% - 0.6px), var(--color-ink-2) calc(50% + 0.6px), transparent calc(50% + 0.6px));
    background-size: 7px 7px; background-repeat: no-repeat;
    background-position: right calc(var(--space-md) + 7px) center, right var(--space-md) center;
}
.check input[type="checkbox"] {
    appearance: none; display: grid; place-content: center; width: 1.5rem; height: 1.5rem; min-height: 0; padding: 0; margin: 0.05em 0 0;
    border: var(--rule-hair) solid var(--color-muted); border-radius: 4px; background: var(--color-paper);
}
.check input[type="checkbox"]::before {
    content: ""; width: 0.75rem; height: 0.4rem; margin-top: -0.2rem;
    border-left: 2px solid var(--color-accent); border-bottom: 2px solid var(--color-accent);
    transform: rotate(-45deg) scale(0); transition: transform var(--dur-micro) var(--ease-out);
}
.check input[type="checkbox"]:checked { border-color: var(--color-ink-2); }
.check input[type="checkbox"]:checked::before { transform: rotate(-45deg) scale(1); }
.check:hover input[type="checkbox"]:not(:disabled) { border-color: var(--color-ink); }
.check input[type="checkbox"]:disabled { opacity: 0.55; cursor: not-allowed; }
@media (prefers-reduced-motion: reduce) {
    .check input[type="checkbox"]::before { transition: none; }
}

/* Vague 4 · apropos4 */
/* À propos, auteur, Suite, charte et pages projet : une seule ligne de colonne (celle du chapô du bandeau,
   colonne 7 sur 12), texte courant au corps 16 px au moins, intros au corps du chapô, environ 65 caractères
   par ligne ; en Geist, le « 0 » qui définit le ch est large : 48ch font 65 à 70 caractères de texte.
   La charte garde la colonne de lecture des pages de document. */
:is(.page-hero.is-about, .page-hero.is-author, .page-hero.is-shot) ~ .section,
.page-content.is-doc.is-project { --measure: 48ch; }
:is(.page-hero.is-about, .page-hero.is-author, .page-hero.is-shot) ~ .section :is(.section-head, .about-head) > p,
.suite-guides-head > p { font-size: var(--text-lead); line-height: 1.5; color: var(--color-ink-2); max-width: var(--measure); }
@media (min-width: 60.0625rem) {
    :is(.page-hero.is-about, .page-hero.is-author, .page-hero.is-shot) ~ .section :is(.wrap.is-split, .about-statement, .tool-row, .gains-row),
    :is(.page-hero.is-author, .page-hero.is-shot) ~ .section > .wrap > .section-head:not(.is-stacked):has(> h2 + p) { grid-template-columns: minmax(0, 6fr) minmax(0, 6fr); }
}

/* À propos, deuxième écran : la phrase « une seule personne » puis les preuves, en rangées à filet
   comme « mes projets » ; toute la rangée suit son lien. */
.about-real { grid-column: 1 / -1; margin-top: var(--space-2xl); }
.about-real h3 { margin: 0 0 var(--space-md); font-size: var(--text-title); color: var(--color-ink-2); }
.about-real .about-links { border-top: var(--rule-hair) solid var(--color-rule-2); }
.about-real .about-links li { position: relative; padding: var(--space-lg) 0; font-size: var(--text-md); transition: background-color var(--dur-short) var(--ease-out), box-shadow var(--dur-short) var(--ease-out); }
.about-real .about-links li a { font-family: var(--font-display); font-size: var(--text-2xl); font-weight: var(--display-weight); line-height: 1.05; letter-spacing: var(--tracking-display); text-transform: lowercase; text-decoration: none; color: var(--color-ink); }
.about-real .about-links li a::after { content: ""; position: absolute; inset: 0; }
.about-real .about-links li a:focus-visible { outline: 0; }
.about-real .about-links li:has(a:focus-visible) { outline: 2px solid var(--color-focus); outline-offset: -2px; }
.about-real .about-links li:hover a { text-decoration: underline; text-decoration-thickness: var(--rule-hair); text-decoration-color: var(--color-accent); text-underline-offset: 0.18em; }
/* Le fond de survol déborde de la gouttière par une ombre, le texte reste sur la ligne de 64 px. */
:is(.about-real .about-links li, .tools-grid.is-links > .tool-row, .gains-row):hover { background: var(--color-paper-2); box-shadow: calc(-1 * var(--space-md)) 0 0 var(--color-paper-2), var(--space-md) 0 0 var(--color-paper-2); }
.tools-grid.is-links > .tool-row { margin-inline: 0; padding-inline: 0; transition: background-color var(--dur-short) var(--ease-out), box-shadow var(--dur-short) var(--ease-out); }
.tools-grid.is-links .tool-row-head { grid-template-columns: minmax(0, 1fr); }
.tools-grid.is-links .tool-row h3 { grid-column: 1; }
.tools-grid.is-links .tool-row-body p { max-width: var(--measure); }
/* Services : des rangées à filet, sur toute la colonne comme les autres index. */
.about-services { max-width: none; }
.about-contact { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-md) var(--gap-columns); margin-top: var(--space-3xl); padding-top: var(--space-xl); border-top: var(--rule-hair) solid var(--color-rule-2); }
.about-contact h2 { margin: 0; }
.about-contact .prose-body { font-size: var(--text-lead); line-height: 1.5; }
.about-contact .prose-body p { margin: 0; }

/* Suite : les gains en rangées d'index sur toute la largeur, titre à gauche, texte à droite. */
.gains-rows { border-top: var(--rule-hair) solid var(--color-rule-2); }
.gains-row { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-sm) var(--gap-columns); align-items: baseline; padding: var(--space-lg) 0; border-bottom: var(--rule-hair) solid var(--color-rule); transition: background-color var(--dur-short) var(--ease-out), box-shadow var(--dur-short) var(--ease-out); }
.gains-row h3 { margin: 0; font-size: var(--text-2xl); line-height: 1.05; }
.gains-row p { margin: 0; max-width: var(--measure); color: var(--color-ink-2); }
/* Offre : plus de pastille au-dessus du titre ; l'état en légende Geist atténuée à côté du bouton (pas un relevé), coches atténuées. */
.launch-cta { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-sm) var(--space-lg); }
.launch-cta .launch-badge { display: inline; margin: 0; padding: 0; border-radius: 0; box-shadow: none; background: none; font: 400 var(--text-xs)/1.5 var(--font-body); text-transform: lowercase; color: var(--color-muted); }
.launch-list li::before { color: var(--color-muted); }
/* Guides : rangées à filet, sans hauteur minimale. */
.suite-guides { border-top: var(--rule-hair) solid var(--color-rule-2); }
.suite-guide { display: block; padding: var(--space-lg) 0; border-bottom: var(--rule-hair) solid var(--color-rule); color: var(--color-ink); text-decoration: none; transition: background-color var(--dur-short) var(--ease-out), box-shadow var(--dur-short) var(--ease-out); }
.suite-guide strong { font-size: var(--text-lg); font-weight: 400; line-height: 1.35; text-decoration: underline; text-decoration-color: transparent; text-decoration-thickness: var(--rule-hair); text-underline-offset: 0.2em; transition: text-decoration-color var(--dur-micro) var(--ease-out); }
.suite-guide:is(:hover, :focus-visible) { background: var(--color-paper-2); box-shadow: calc(-1 * var(--space-md)) 0 0 var(--color-paper-2), var(--space-md) 0 0 var(--color-paper-2); }
.suite-guide:is(:hover, :focus-visible) strong { text-decoration-color: var(--color-accent); }
.suite-guide:focus-visible { outline: 2px solid var(--color-focus); outline-offset: 2px; }
.suite-guides-all { margin: var(--space-lg) 0 0; }
.suite-guides-all a { color: var(--color-ink); font-weight: 500; }
.suite-guides-head { margin-bottom: var(--space-2xl); }
/* Fin de page : une rangée sous un filet, sans encadré ; titre à gauche, phrase et boutons à droite. */
.suite-end-row { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-md) var(--gap-columns); margin-top: var(--space-3xl); padding-top: var(--space-xl); border-top: var(--rule-hair) solid var(--color-rule-2); }
.suite-end-row h2 { margin: 0; }
.suite-end-row p { margin: 0; max-width: var(--measure); font-size: var(--text-lead); line-height: 1.5; color: var(--color-ink-2); }
.suite-end-body { display: grid; gap: var(--space-lg); justify-items: start; }
.suite-end-actions { display: flex; flex-wrap: wrap; gap: var(--space-sm); }
@media (min-width: 60.0625rem) {
    .suite-end-row { grid-template-columns: minmax(0, 6fr) minmax(0, 6fr); align-items: start; }
}

/* Charte : intertitres en minuscules, comme le reste des titres. */
.page-content.is-doc.is-charter > h2 { text-transform: lowercase; }
/* Pages projet : la capture du site à droite du titre, à hauteur du titre. */
@media (min-width: 60.0625rem) {
    .page-hero.is-product:not(.is-shot) > .wrap > .product-shot.is-site { align-self: start; }
}

/* Vague 5 · lecture5 */
/* Bandeau d'article : le h1 sur une mesure de titre (34ch), coupé en lignes égales, sans cellule vide à côté. */
@media (min-width: 60.0625rem) {
  .page-hero.article-hero h1 { max-width: 34ch; text-wrap: balance; }
}
/* Schéma du bandeau au téléphone : un plancher de 42rem garde les libellés à 12 px, le puits défile,
   le bord droit s'efface pour l'indiquer ; l'anneau de focus passe au puits, que le masque ne coupe pas. */
@media (max-width: 47.9375rem) {
  .article-hero .figure-scroll { padding-right: var(--space-xl); mask-image: linear-gradient(to left, transparent, var(--color-paper) var(--space-xl)); }
  .article-hero .figure-scroll svg { min-width: 42rem; }
  .article-hero .figure-scroll:focus-visible { outline: 0; }
  .article-hero .article-figure:has(.figure-scroll:focus-visible) { outline: 2px solid var(--color-focus); outline-offset: -2px; }
}
/* Code au téléphone : la ligne revient à la ligne plutôt que de défiler. */
@media (max-width: 40rem) {
  .article-body pre { white-space: pre-wrap; overflow-wrap: break-word; }
}
/* Tableaux du corps : un puits à filet ; la dernière rangée n'ajoute pas de filet au cadre. */
.article-body table { padding: var(--space-2xs) var(--space-md) var(--space-xs); border: var(--rule-hair) solid var(--color-rule); border-radius: var(--radius-card); }
.article-body tbody tr:last-child td { border-bottom: 0; }
@media (max-width: 40rem) {
  .article-body table.is-stacked { padding: 0; border: 0; border-radius: 0; }
}
/* Documents : la date sous le h1, à gauche, en Geist au corps, sans filet ; l'introduction en Geist. */
.page-content.is-legal > h1 + p { font-family: var(--font-body); font-size: var(--text-md); }
.page-content.is-doc > h1 + p.doc-date { grid-column: 1 / -1; max-width: none; padding-top: 0; border-top: 0; color: var(--color-muted); }
@media (max-width: 60rem) {
  .page-content.is-doc.is-legal > h2 + * { margin-top: var(--space-md); }
}

/* Vague 5 · apropos5 */
/* Pages projet (MCT, Atari) : sous la capture, des sections dans la grammaire de la Suite, tête à gauche
   et texte en colonne 7 sur la même rangée, une seule bande par page ; les outils et les jeux en grille
   à filets calée sur les mêmes colonnes. */
.page-hero.is-product ~ .section { --measure: 48ch; }
.project-sec:not(.section-ink) + .project-sec:not(.section-ink) { border-top: var(--rule-hair) solid var(--color-rule); }
.project-prose { max-width: none; }
.project-prose > p { margin: 0; max-width: var(--measure); font-size: var(--text-lead); line-height: 1.5; color: var(--color-ink-2); }
/* Rangées d'une même section : chacune sous un filet, avec l'air d'un changement de section. */
.project-row { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-xl) var(--gap-columns); align-items: start; }
.project-row .section-head { display: block; margin: 0; }
.project-row .section-head h2 { margin-top: 0; }
.project-row + :is(.project-row, .section-head) { margin-top: var(--section-gap-s); padding-top: var(--section-gap-s); border-top: var(--rule-hair) solid var(--color-rule); }
.project-list { margin: var(--space-xl) 0 0; padding: 0; list-style: none; border-top: var(--rule-hair) solid var(--color-rule-2); }
.project-list li { margin: 0; padding: var(--space-md) 0; border-bottom: var(--rule-hair) solid var(--color-rule); color: var(--color-ink-2); }
.project-tools, .project-games { display: grid; grid-template-columns: minmax(0, 1fr); column-gap: var(--gap-columns); border-top: var(--rule-hair) solid var(--color-rule-2); }
.project-tool, .project-game { padding-block: var(--space-lg); border-bottom: var(--rule-hair) solid var(--color-rule); }
.project-tool h3, .project-game h3 { margin: 0 0 var(--space-xs); font-size: var(--text-2xl); line-height: 1.05; }
.project-tool p { margin: 0; max-width: var(--measure); color: var(--color-ink-2); }
.project-tool h3 a { color: var(--color-ink); text-decoration: underline; text-decoration-thickness: var(--rule-hair); text-decoration-color: var(--color-rule-2); text-underline-offset: 0.18em; transition: text-decoration-color var(--dur-micro) var(--ease-out); }
.project-tool h3 a:hover { text-decoration-color: var(--color-accent); }
/* Jeux : toute la cellule suit le lien ; l'année en relevé mono, l'éditeur en Geist atténué. */
.project-game { position: relative; display: flex; flex-direction: column; transition: background-color var(--dur-short) var(--ease-out), box-shadow var(--dur-short) var(--ease-out); }
.project-game h3 a { color: var(--color-ink); text-decoration: none; }
.project-game h3 a::after { content: ""; position: absolute; inset: 0; }
.project-game h3 a:focus-visible { outline: 0; }
.project-game:is(:hover, :has(a:focus-visible)) { background: var(--color-paper-2); box-shadow: calc(-1 * var(--space-md)) 0 0 var(--color-paper-2), var(--space-md) 0 0 var(--color-paper-2); }
.project-game:has(a:focus-visible) { outline: 2px solid var(--color-focus); outline-offset: 2px; }
.project-game:hover h3 a { text-decoration: underline; text-decoration-thickness: var(--rule-hair); text-decoration-color: var(--color-accent); text-underline-offset: 0.18em; }
/* Rangée de chiffres : l'année en tête au corps display (l'éditeur en relevé : bloc apropos6). */
.project-game p { display: contents; }
.project-year { order: -1; margin-bottom: var(--space-md); font-family: var(--font-display); font-size: var(--text-display-s); font-weight: var(--display-weight); line-height: 1; letter-spacing: var(--tracking-display); font-variant-numeric: tabular-nums; color: var(--color-ink); }
/* Fin de page : sous un filet, la phrase en énoncé, puis le texte et le bouton (bloc apropos6). */
/* Le premier enfant d'un .wrap perd sa marge haute : le sélecteur reprend la même force. */
.section > .wrap > .project-end { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-md) var(--gap-columns); justify-items: start; margin-top: var(--space-3xl); padding-top: var(--space-xl); border-top: var(--rule-hair) solid var(--color-rule-2); }
.project-end > div { display: contents; }
.project-end strong { max-width: 20ch; font-family: var(--font-display); font-size: var(--text-display-s); font-weight: var(--display-weight); line-height: 0.98; letter-spacing: var(--tracking-display); text-transform: lowercase; text-wrap: balance; color: var(--color-ink); }
.project-end p { margin: 0; max-width: var(--measure); font-size: var(--text-lead); line-height: 1.5; color: var(--color-ink-2); }
@media (min-width: 40.0625rem) {
    .project-tools, .project-games { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (min-width: 60.0625rem) {
    .page-hero.is-product ~ .section :is(.wrap.is-split, .project-row) { grid-template-columns: minmax(0, 6fr) minmax(0, 6fr); }
    .project-games { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/* À propos, deuxième écran : la phrase calée en haut de la rangée de sa tête ; les réalisations
   deviennent une rangée à part, tête au corps des sections (balise h3 gardée), liens en rangées à filet. */
.about-statement { align-items: start; }
.about-real { padding-top: var(--space-xl); border-top: var(--rule-hair) solid var(--color-rule-2); }
.about-real h3 { margin: 0; font-size: var(--text-display-s); line-height: 0.98; color: var(--color-ink); }
@media (min-width: 60.0625rem) {
    .about-statement h2 { grid-column: 1; }
    .about-real { display: grid; grid-template-columns: subgrid; align-items: start; }
    .about-real .about-links { grid-column: 2; }
}
@media (max-width: 60rem) { .about-real h3 { margin-bottom: var(--space-lg); } }
@media (max-width: 40rem) { .about-rate { grid-template-columns: minmax(0, 6.5rem) minmax(0, 1fr); gap: var(--space-md); } }
/* Délai de réponse : dans la face de sa phrase (ce n'est pas un relevé de machine), d'un seul tenant, en encre pleine. */
.about-delay { font-variant-numeric: tabular-nums; white-space: nowrap; color: var(--color-ink); }

/* Auteur et à propos : la prose au corps de celle d'à propos ; la précision qui suit les preuves
   passe en colonne 7, sous les rangées, avec moins de vide. */
:is(.page-hero.is-about, .page-hero.is-author) ~ .section :is(.author-prose p, .author-aside) { font-size: var(--text-lead); line-height: 1.5; }
.author-aside { margin-top: var(--space-xl); }
@media (min-width: 60.0625rem) {
    .section > .wrap > .author-aside { margin-left: calc(50% + var(--gap-columns) / 2); }
}

/* Vague 5 · accueil5 */
/* Projets : un puits à filet, une rangée par projet, lu comme un registre. Le nom en Instrument Serif sur la moitié
   gauche, la preuve à partir du milieu (x 736 à 1440, sous le chapeau), la pile en référence dans la dernière colonne,
   calée sur la ligne de base du nom ; sous 80rem, la référence passe sous la preuve. Ni survol ni carte : un relevé. */
.proof-grid.is-wells { display: block; color: var(--color-ink); background: var(--color-paper-2); border: var(--rule-hair) solid var(--color-rule); border-radius: var(--radius-card); overflow: clip; }
.proof-grid.is-wells .proof-tile {
    display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); gap: var(--space-xs) var(--gap-columns); align-items: baseline;
    padding: var(--space-lg) var(--space-xl); border-radius: 0; box-shadow: none; border-top: var(--rule-hair) solid var(--color-rule);
}
.proof-grid.is-wells .proof-tile:first-child { border-top: 0; }
.proof-grid.is-wells .proof-tile h3 { grid-column: 1 / span 6; max-width: none; text-wrap: balance; }
.proof-grid.is-wells .proof-tile p { grid-column: 7 / -1; max-width: 52ch; }
.proof-grid.is-wells .proof-kicker { grid-column: 7 / -1; margin: 0; padding: 0; border: 0; font: 400 var(--text-xs)/1.5 var(--font-body); font-variant-numeric: tabular-nums; color: var(--color-muted); text-transform: lowercase; }
@media (min-width: 80rem) {
    .proof-grid.is-wells .proof-tile p { grid-column: 7 / span 4; }
    .proof-grid.is-wells .proof-kicker { grid-column: 11 / -1; text-align: right; }
}
@media (max-width: 60rem) {
    .proof-grid.is-wells .proof-tile { grid-template-columns: minmax(0, 1fr); padding: var(--space-lg); }
    .proof-grid.is-wells .proof-tile :is(h3, p, .proof-kicker) { grid-column: 1; }
}

/* Derniers guides : dans la bande de la FAQ, en liste à filets. La rubrique en marge sur la colonne
   de la tête de FAQ, le titre en Instrument Serif sur celle des questions ; au survol, son filet laiton. */
.home-guides .guide-links { display: block; border-top: var(--rule-hair) solid var(--color-rule); }
.home-guides .guide-link {
    display: grid; grid-template-columns: minmax(0, 4fr) minmax(0, 8fr); gap: var(--space-2xs) var(--gap-columns); align-items: baseline;
    min-height: 0; padding: var(--space-lg) 0; border-radius: 0; box-shadow: none; background: none; border-bottom: var(--rule-hair) solid var(--color-rule); text-decoration: none;
}
.home-guides .guide-link:hover, .home-guides .guide-link:active { background: none; box-shadow: none; }
.home-guides .guide-link strong {
    grid-column: 2; grid-row: 1; font-family: var(--font-display); font-size: var(--text-xl); font-weight: var(--display-weight); line-height: 1.1; letter-spacing: var(--tracking-display); text-transform: lowercase;
    color: var(--color-ink); text-decoration: underline; text-decoration-color: transparent; text-decoration-thickness: var(--rule-hair); text-underline-offset: 0.2em; transition: text-decoration-color var(--dur-micro) var(--ease-out);
}
.home-guides .guide-link span { grid-column: 1; grid-row: 1; font: 400 var(--text-sm)/1.5 var(--font-body); color: var(--color-muted); text-transform: lowercase; }
.home-guides .guide-link:hover strong { text-decoration-color: var(--color-accent); }

@media (max-width: 40rem) {
    .home-guides .guide-link { grid-template-columns: minmax(0, 1fr); }
    .home-guides .guide-link :is(strong, span) { grid-column: 1; grid-row: auto; }
}

/* Vague 5 · services5
   Pages de service : un objet par page, tiré de son texte, posé par une classe de variante
   (services/show.blade.php). Piratage, référencement, SEO WordPress : les symptômes en relevé
   d'état, le code ou le message réel en Geist Mono. Lenteur : la méthode en tracé, de la mesure de
   départ à la mesure d'arrivée. Sur mesure seul : la méthode en échéancier de livraisons.
   Avec un cas réel, la méthode devient la bande paper-2 de la page. Sur téléphone, le prix et le
   bouton de la fiche montent sous le chapô. */

/* ---------- Relevé d'état : une ligne par symptôme, la sortie de la machine en mono ---------- */
.service-symptoms.is-states .wrap { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); gap: 0 var(--gap-columns); align-items: start; }
.service-symptoms.is-states .section-head { grid-column: 1 / span 4; position: sticky; top: calc(var(--header-h) + var(--space-xl)); margin: 0; }
.service-symptoms.is-states .symptoms { grid-column: 5 / -1; grid-template-columns: minmax(0, 1fr); }
.service-symptoms.is-states .symptoms li:last-child:nth-child(odd) { grid-column: auto; }
/* Le témoin de la ligne : un anneau à filet, éteint ; pas de couleur d'alerte. */
.service-symptoms .symptoms li::before {
    content: ""; position: absolute; left: 0; top: calc(var(--space-lg) + 0.675em - 4px); width: 9px; height: 9px; box-sizing: border-box;
    border: var(--rule-hair) solid var(--color-muted); border-radius: 50%;
}
.service-symptoms.is-states samp {
    margin-inline: 0.1em; padding: 0.1em 0.45em; white-space: nowrap; border: var(--rule-hair) solid var(--color-rule-2); border-radius: var(--radius-chip);
    font: 400 0.8em/1.3 var(--font-outlier); letter-spacing: 0; color: var(--color-ink); font-variant-numeric: tabular-nums;
}

/* ---------- Tracé départ → arrivée : les étapes descendent d'une borne à l'autre ---------- */
@media (min-width: 60.0625rem) {
    .service-method.is-trace .steps h3 { align-self: start; min-height: 7.5rem; margin-bottom: var(--space-xl); }
    .service-method.is-trace .steps li:nth-child(2) h3 { margin-top: calc(2 * var(--space-xl)); }
    .service-method.is-trace .steps li:nth-child(3) h3 { margin-top: calc(3 * var(--space-xl)); }
    .service-method.is-trace .steps li:nth-child(4) h3 { margin-top: calc(4 * var(--space-xl)); }
    /* La liaison : une diagonale d'un filet, du centre de la première borne au centre de la dernière. */
    .service-method.is-trace .steps::after {
        top: calc(var(--space-xl) + 3.75rem); bottom: calc(var(--space-xl) + 3.75rem);
        left: calc(var(--steps-pad, var(--space-xl)) + (100% - 2 * var(--steps-pad, var(--space-xl)) - 3 * var(--gap-columns)) / 8); right: calc(var(--steps-pad, var(--space-xl)) + (100% - 2 * var(--steps-pad, var(--space-xl)) - 3 * var(--gap-columns)) / 8);
        height: auto; background: linear-gradient(to top right, transparent calc(50% - 0.75px), var(--color-accent) 50%, transparent calc(50% + 0.75px));
    }
}
/* Les deux bornes : mesure de départ et mesure d'arrivée, filet laiton. */
.service-method.is-trace .steps li:is(:first-child, :last-child) h3 { border-color: var(--color-accent); }
.service-method.is-trace .steps li:is(:first-child, :last-child) h3::before { color: var(--color-accent); }

/* ---------- Échéancier : une rangée par étape, une barre par livraison sur quatre périodes ---------- */
.service-method.is-schedule .steps { display: block; padding: 0; }
.service-method.is-schedule .steps::before, .service-method.is-schedule .steps::after { content: none; }
.service-method.is-schedule .steps li {
    display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); grid-template-rows: auto auto; gap: var(--space-xs) var(--gap-columns); align-items: center;
    padding: var(--space-lg) 0; border-top: var(--rule-hair) solid var(--color-rule);
}
.service-method.is-schedule .steps h3 { grid-column: 1; grid-row: 1; margin: 0; padding: 0; background: none; border: 0; border-radius: 0; }
.service-method.is-schedule .steps p { grid-column: 1; grid-row: 2; padding: 0; }
/* La piste : une ligne de base graduée en quatre périodes, sans cases ; la période de l'étape est remplie
   (encre à 18 % sur le papier, filet rule-2 autour, laiton à sa base) et porte le numéro de l'étape, qui quitte le titre. */
.service-method.is-schedule .steps li::before, .service-method.is-schedule .steps li::after { content: ""; grid-column: 2; grid-row: 1 / span 2; height: 2.75rem; }
.service-method.is-schedule .steps li::before {
    position: static; display: block; width: auto; border: 0; border-radius: 0; box-shadow: none;
    background: linear-gradient(90deg, var(--color-rule-2) var(--rule-hair), transparent var(--rule-hair)) 0 100% / 25% var(--space-xs) repeat-x,
        linear-gradient(var(--color-rule-2), var(--color-rule-2)) 100% 100% / var(--rule-hair) var(--space-xs) no-repeat;
    border-bottom: var(--rule-hair) solid var(--color-rule-2);
}
.service-method.is-schedule .steps li::after {
    content: counter(step, decimal-leading-zero); content: counter(step, decimal-leading-zero) / "";
    display: flex; align-items: center; width: 25%; box-sizing: border-box; padding-inline: var(--space-sm);
    background: color-mix(in oklch, var(--color-ink-2) 18%, var(--color-paper-2)); border: var(--rule-hair) solid var(--color-rule-2); border-bottom-color: var(--color-accent);
    font: 400 var(--text-xs)/1 var(--font-body); letter-spacing: 0; color: var(--color-ink); font-variant-numeric: tabular-nums;
}
.service-method.is-schedule .steps h3::before { content: none; }
/* Dans le puits : les rangées s'écartent du bord, sans filet doublé en haut ni en bas. */
.service-method.is-schedule .path { padding: 0 var(--space-xl); }
.service-method.is-schedule .steps li:first-child { border-top: 0; }
.service-method.is-schedule .steps li:last-child { border-bottom: 0; }
.service-method.is-schedule .steps li:nth-child(2)::after { margin-left: 25%; }
.service-method.is-schedule .steps li:nth-child(3)::after { margin-left: 50%; }
.service-method.is-schedule .steps li:nth-child(4)::after { margin-left: 75%; }
@media (max-width: 60rem) {
    .service-method.is-schedule .steps { padding: 0; }
    .service-method.is-schedule .steps li { grid-template-columns: minmax(0, 1fr); grid-template-rows: none; }
    .service-method.is-schedule .steps li + li { margin-top: 0; }
    .service-method.is-schedule .steps li::before, .service-method.is-schedule .steps li::after { grid-column: 1; grid-row: 3; height: 1.75rem; margin-top: var(--space-sm); }
}

/* ---------- Avec cas réel : la méthode est la bande paper-2 de la page, son puits s'efface (le cas devient le puits) ---------- */
.service-page:has(.service-case) .service-method { color: var(--color-ink); background: var(--color-paper-2); border-block: var(--rule-hair) solid var(--color-rule); }
.service-page:has(.service-case) .service-method .path { padding: 0; background: none; border: 0; border-radius: 0; }
@media (min-width: 60.0625rem) {
    .service-page:has(.service-case) .service-method:not(.is-schedule, .is-rail, .is-vertical, .is-diagram) .steps { --steps-pad: 0px; padding-inline: 0; }
    .service-page:has(.service-case) .service-method:not(.is-schedule, .is-rail, .is-vertical, .is-diagram) .steps::before { border-inline: var(--rule-hair) solid var(--color-rule); }
}
@media (max-width: 60rem) {
    .service-page:has(.service-case) .service-method:not(.is-schedule, .is-rail, .is-vertical, .is-diagram) .steps { padding-inline-end: 0; }
}

/* ---------- Prose : 16 px pour tout paragraphe de plus de deux lignes ---------- */
.offer-box li, .service-dossier .pricing-note { font-size: var(--text-md); }

/* ---------- Téléphone : le prix et le bouton sous le chapô, le détail ensuite ---------- */
@media (max-width: 40rem) {
    .service-hero-grid { gap: var(--space-lg); }
    .service-hero .offer-box { display: flex; flex-direction: column; }
    .offer-box > .offer-figure { order: 1; display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: end; gap: 0 var(--space-md); }
    .offer-figure .offer-name { grid-column: 1; grid-row: 1; }
    .offer-figure .price-amount { grid-column: 2; grid-row: 1 / span 2; margin: 0; }
    .offer-figure > .price-unit:last-child { grid-column: 1; grid-row: 2; margin: 0; }
    .offer-box > .btn { order: 2; }
    .offer-box > .pricing-note { order: 3; }
    .offer-box > ul { order: 4; margin: var(--space-lg) 0 0; }
}
@media (max-width: 60rem) {
    .service-symptoms.is-states .wrap { display: block; }
    .service-symptoms.is-states .section-head { position: static; margin-bottom: var(--space-xl); }
}

/* Vague 5 · conversion5 */
/* Fiche de prix à 320 px : le drapeau passe sous le nom plutôt que de le serrer. */
@media (max-width: 22rem) {
    .pricing:not(.is-four) .price-card > .price-flag { grid-column: 1 / -1; grid-row: 2; justify-self: start; }
}


/* Agences : une seule bande paper-2, la maintenance en marque blanche ; le prix y est un puits
   comme une fiche de tarif (montant display, unité en relevé). */
.section.is-maint .maint { border-bottom: 0; }
.section.is-maint .maint-price {
    display: grid; gap: var(--space-sm); align-self: start; padding: var(--space-xl);
    background: var(--color-paper); color: var(--color-ink); border: var(--rule-hair) solid var(--color-rule-2); border-radius: var(--radius-card);
}
.section.is-maint .maint-price .price-amount { margin: 0; }

/* Vague 5 · index5 */
/* Page de rubrique : la liste de lecture monte dans le premier écran, l'introduction de la rubrique à côté, en tête de colonne.
   Plus collée par le bas : au corps courant elle dépasse la hauteur de la fenêtre (950 px à 1280) et son début passait sous l'en-tête. Sous 75rem la liste passe devant la prose (sans lien, elle ne change
   pas l'ordre de tabulation). */
.cat-layout { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-2xl); }
.cat-layout > .cat-main { order: -1; }
@media (min-width: 75.0625rem) {
    .cat-layout { grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); grid-template-rows: auto 1fr; gap: var(--space-xl) var(--gap-columns); align-items: start; }
    .cat-layout > .cat-main { order: 0; grid-column: 2; grid-row: 1; }
    .cat-layout > .cat-body { grid-column: 1; grid-row: 1 / span 2; align-self: start; }
    .cat-layout > .gh-foot { grid-column: 2; grid-row: 2; }
}

/* Bandeaux d'index : le h1 se cale en haut, à hauteur du chapô, au lieu de tomber au bas d'un bandeau étiré par le chapô. */
@media (min-width: 60.0625rem) {
    .page-hero.is-listing:not(.article-hero) > .wrap:not(.author-hero) > h1 { align-self: start; }
}

/* Vague 6 · index6 */

/* Ressources : une composition à part. Ouverture en deux temps (la note au corps du chapô, le sommaire en filets à côté),
   têtes de rubrique sur toute la largeur, entrées en grille de deux puits, le moment de lecture en pied de puits. */
.page-content.is-doc.res-doc { display: block; }
.page-content.is-doc.res-doc > * { max-width: none; }
.res-intro { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); gap: var(--space-xl) var(--gap-columns); align-items: start; }
@media (min-width: 60.0625rem) { .res-note { grid-column: 1 / 8; } .res-toc { grid-column: 8 / -1; } }
.res-note p { max-width: 60ch; margin: 0; font-size: var(--text-lead); line-height: 1.55; color: var(--color-ink-2); text-wrap: pretty; }
.res-note strong { font-weight: 500; color: var(--color-ink); }
.res-toc { display: flex; flex-direction: column; margin: 0; border-top: var(--rule-hair) solid var(--color-rule-2); }
.page-content.res-doc .res-toc a { display: flex; align-items: center; min-height: 44px; font-weight: 400; border-bottom: var(--rule-hair) solid var(--color-rule); font-size: var(--text-sm); text-transform: lowercase; color: var(--color-ink-2); text-decoration: underline; text-decoration-color: transparent; text-decoration-thickness: var(--rule-hair); text-underline-offset: 0.3em; transition: color var(--dur-micro) var(--ease-out), text-decoration-color var(--dur-micro) var(--ease-out); }
.page-content.res-doc .res-toc a:hover { color: var(--color-ink); text-decoration-color: var(--color-accent); }
.page-content.is-doc.res-doc > h2 { position: static; max-width: none; margin: var(--space-3xl) 0 0; padding-top: var(--space-lg); border-top: var(--rule-hair) solid var(--color-rule-2); font-size: var(--text-section); line-height: 0.98; text-transform: lowercase; text-wrap: balance; scroll-margin-top: calc(var(--header-h) + var(--space-lg)); }
.page-content.is-doc.res-doc > h2 + * { margin-top: var(--space-lg); padding-top: 0; border-top: 0; }
.page-content.is-doc.res-doc > p { max-width: var(--measure); }
.res-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-md); margin: var(--space-xl) 0 0; }
.res-item { display: flex; flex-direction: column; gap: var(--space-sm); padding: var(--space-lg); background: var(--color-paper-2); border: var(--rule-hair) solid var(--color-rule); border-radius: var(--radius-card); transition: border-color var(--dur-short) var(--ease-out); }
.res-item:has(h3 a:hover) { border-color: var(--color-rule-2); }
.res-item h3 { margin: 0; font-size: var(--text-2xl); line-height: 1.05; text-wrap: balance; }
.page-content.is-doc .res-item h3 { text-transform: lowercase; }
.res-item h3 a { color: var(--color-ink); text-underline-offset: 0.16em; }
.res-item p { max-width: var(--measure); margin: 0; color: var(--color-ink-2); }
.res-item .res-when { margin-top: auto; padding-top: var(--space-sm); border-top: var(--rule-hair) solid var(--color-rule); }
/* Une entrée seule sur sa rangée garde sa colonne : même puits que les autres, note en bas à gauche. */
/* Méthode : voir le bloc p14b (tête à gauche, règles en rangées à filet à droite). */
@media (max-width: 60rem) {
    .res-intro, .res-grid { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 40rem) {
    .res-item { padding: var(--space-md); }
    .res-item h3 { font-size: var(--text-xl); line-height: 1.1; }
    .page-content.is-doc.res-doc > h2 { margin-top: var(--space-2xl); }
}

/* Études de cas : liens de rubrique en minuscules comme l'étiquette ; le laiton seulement sur le stock tenu fixe, en filet. */
.case-file .case-meta a { text-transform: lowercase; }
.case-figures li.is-fixed::before { content: none; }
.case-figures li.is-fixed::after { height: var(--rule-hair); background: var(--color-accent); opacity: 1; }

/* Rubriques de /guides : chaque groupe a son rang. La tête et le premier guide (rangée large, extrait entier) ouvrent le groupe ;
   les guides suivants passent en rangées compactes sur toute la largeur, le titre sous la tête, l'extrait sous le premier guide. */
.guide-group { padding-top: var(--space-md); }
.guide-group + .guide-group { margin-top: var(--space-2xl); }
.guide-group-title { margin: 0 0 var(--space-lg); padding-top: var(--space-lg); border-top: var(--rule-hair) solid var(--color-rule-2); font-size: var(--text-display-s); line-height: 0.98; text-wrap: balance; }
.guide-group-title a { color: var(--color-ink); text-decoration: underline; text-decoration-color: transparent; text-decoration-thickness: var(--rule-hair); text-underline-offset: 0.14em; transition: text-decoration-color var(--dur-micro) var(--ease-out); }
.guide-group-title a:is(:hover, :focus-visible) { text-decoration-color: var(--color-accent); }
/* Rangées compactes : hors du puits, titre au corps lg, extrait au petit corps. */
.guide-group .guide-cards.is-index { background: none; border: 0; border-radius: 0; overflow: visible; }
.guide-group .guide-cards.is-index .guide-card { grid-template-columns: 6rem minmax(0, 1fr) 3.5rem; grid-template-areas: "date title dur" ". text ."; padding: var(--space-md); }
.guide-group .guide-cards.is-index .guide-card-foot > time { justify-self: start; }
.guide-group .guide-cards.is-index .guide-card :is(h2, h3) { font-size: var(--text-lg); line-height: 1.15; }
.guide-group .guide-cards.is-index .guide-card:hover { background: var(--color-paper-2); }
/* Premier guide : rangée large sous le filet fort, titre au corps xl, extrait entier au corps courant. */
.guide-group .guide-cards.is-index .guide-card:first-child {
    grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "title date" "text dur";
    padding-block: var(--space-lg) var(--space-xl); border-top: var(--rule-hair) solid var(--color-rule-2);
}
.guide-group .guide-cards.is-index .guide-card:first-child :is(h2, h3) { font-size: var(--text-xl); line-height: 1.1; }
.guide-group .guide-cards.is-index .guide-card:first-child p { max-width: 60ch; font-size: var(--text-md); line-height: 1.55; }
.guide-group .guide-cards.is-index .guide-card:first-child .guide-card-foot > time { justify-self: end; }
/* Une seule rubrique sur la bande paper-2 (la troisième) : la page n'en compte pas d'autre. */
.guide-group.is-band { padding-block: var(--space-xl) var(--space-2xl); color: var(--color-ink); background: var(--color-paper-2); box-shadow: 0 0 0 100vmax var(--color-paper-2); clip-path: inset(0 -100vmax); }
.guide-group.is-band .guide-cards.is-index .guide-card:hover { background: var(--color-paper-3); }
@media (min-width: 60.0625rem) {
    /* Grille de douze colonnes partagée par la tête et les rangées (subgrid) : titres alignés sous la tête, extraits sous le premier guide. */
    .guide-group { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); gap: 0 var(--gap-columns); align-items: start; }
    .guide-group-title { grid-column: 1 / span 4; margin: 0; }
    .guide-group .guide-cards.is-index { display: contents; }
    .guide-group .guide-cards.is-index .guide-card { grid-column: 1 / -1; grid-template-columns: subgrid; grid-template-areas: none; column-gap: normal; margin-inline: calc(-1 * var(--space-md)); }
    .guide-group .guide-cards.is-index .guide-card :is(h2, h3) { grid-column: 1 / span 4; grid-row: 1 / span 2; }
    .guide-group .guide-cards.is-index .guide-card p { grid-column: 5 / span 6; grid-row: 1 / span 2; max-width: none; }
    .guide-group .guide-cards.is-index .guide-card-foot > time { grid-column: 11 / -1; grid-row: 1; justify-self: end; }
    .guide-group .guide-cards.is-index .guide-card-time { grid-column: 11 / -1; grid-row: 2; }
    .guide-group .guide-cards.is-index .guide-card:first-child { grid-column: 5 / -1; grid-template-columns: subgrid; grid-template-areas: none; }
    .guide-group .guide-cards.is-index .guide-card:first-child :is(h2, h3) { grid-column: 1 / span 6; grid-row: 1; }
    .guide-group .guide-cards.is-index .guide-card:first-child p { grid-column: 1 / span 6; grid-row: 2; max-width: 60ch; }
    .guide-group .guide-cards.is-index .guide-card:first-child .guide-card-foot > time { grid-column: 7 / -1; grid-row: 1; }
    .guide-group .guide-cards.is-index .guide-card:first-child .guide-card-time { grid-column: 7 / -1; grid-row: 2; }
}

/* Téléphone : rubrique et durée en tête de rangée, extrait des rangées compactes limité à trois lignes (le texte reste entier dans le DOM) ;
   le premier guide de chaque rubrique garde son extrait entier. */
@media (max-width: 40rem) {
    .guide-group .guide-cards.is-index .guide-card, .guide-group .guide-cards.is-index .guide-card:first-child { grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "date dur" "title title" "text text"; padding-inline: 0; }
    .guide-cards.is-index .guide-card :is(h2, h3) { font-size: var(--text-xl); line-height: 1.1; }
    .guide-group .guide-cards.is-index .guide-card :is(h2, h3) { font-size: var(--text-lg); }
    .guide-group .guide-cards.is-index .guide-card:first-child :is(h2, h3) { font-size: var(--text-xl); }
    .guide-cards.is-index .guide-card p { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; line-clamp: 3; overflow: hidden; }
    .guide-group .guide-cards.is-index .guide-card:first-child p { display: block; -webkit-line-clamp: none; line-clamp: none; overflow: visible; }
    .guide-group .guide-cards.is-index .guide-card:first-child .guide-card-foot > time { justify-self: start; }
}

/* Bandeau de rubrique : titre court sur cinq colonnes, chapô sur sept à une mesure plus large (six lignes au lieu de huit à 1280). */
@media (min-width: 60.0625rem) {
    .page-hero.is-listing.cat-hero:not(.article-hero) > .wrap:not(.author-hero) > h1 { grid-column: 1 / span 5; }
    .page-hero.is-listing.cat-hero:not(.article-hero) > .wrap:not(.author-hero) > .lead { grid-column: 6 / -1; max-width: 68ch; }
}

/* /outils, fiche technique : le nom et sa légende à gauche, le texte puis les deux liens côte à côte à droite.
   Un seul corps de titre pour les cinq rangées ; la première garde son puits ; pas de filet sous la dernière (le pied a le sien). */
.tools-index .tools-grid { border-bottom: 0; }
.tools-index .tool-row { grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); align-items: start; gap: var(--space-md) var(--gap-columns); }
.tools-index .tool-row-head { display: flex; flex-direction: column; align-items: flex-start; gap: var(--space-xs); }
.tools-index .tool-row h2 { font-size: var(--text-display-s); line-height: 0.98; text-wrap: balance; }
.tools-index .tool-row-body p { margin: 0 0 var(--space-lg); }
.tools-index .tool-links { align-items: stretch; gap: var(--space-xs); }
@media (max-width: 60rem) {
    .tools-index .tool-row { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 40rem) {
    .tools-index .tool-links { flex-direction: column; }
    .tools-index .tool-links .btn { justify-content: center; }
}

/* perf8 début */
/* Formulaire du devis : site.js ajoute sous chaque champ une ligne de message réservée, puis pose .is-enhanced.
   Sur un réseau lent, le premier rendu précède le script et le formulaire grandissait à son arrivée (CLS 0,005).
   Avec JavaScript actif, la même ligne et les mêmes écarts sont tenus dès le premier rendu ; sans JavaScript, rien ne change. */
.js .form[novalidate]:not(.is-enhanced), .js .form[novalidate]:not(.is-enhanced) .form-row { gap: var(--space-sm) var(--space-lg); }
.js .form[novalidate]:not(.is-enhanced) .field:not(.hp-field)::after { content: ""; min-height: calc(1.45 * var(--text-sm)); }
/* perf8 fin */

/* Vague 6 · apropos6 */
/* Atari : l'éditeur en légende Geist sous le titre du jeu (ce n'est pas un relevé), la date au-dessus en chiffre display. */
.project-pub { font-family: var(--font-body); font-size: var(--text-xs); color: var(--color-muted); }
/* Atari : la phrase d'intention en énoncé Instrument Serif sur dix colonnes, pas une rangée scindée de plus
   (sur huit colonnes en Geist, tête et phrase laissaient vide le tiers droit). */
.project-row.is-statement .project-prose > p { font-family: var(--font-display); font-weight: var(--display-weight); letter-spacing: var(--tracking-display); font-size: var(--text-xl); line-height: 1.3; color: var(--color-ink); }
@media (min-width: 60.0625rem) {
    .page-hero.is-product ~ .section .project-row.is-statement { grid-template-columns: repeat(12, minmax(0, 1fr)); }
    .project-row.is-statement > * { grid-column: 1 / span 10; }
    .project-row.is-statement .project-prose > p { max-width: none; font-size: var(--text-2xl); line-height: 1.25; }
}
/* MCT : le contenu éditorial en aparté sous filet dans la bande des prix, au corps d'un intertitre (pas une rangée de
   plus) ; sur grand écran, dans la colonne de la tête, calé sur le bas de la liste des villes qui occupe la droite. */
.project-aside { max-width: var(--measure); margin-top: 0; padding-top: var(--space-lg); border-top: var(--rule-hair) solid var(--color-rule-2); }
.project-aside h2 { margin: 0 0 var(--space-sm); font-size: var(--text-2xl); line-height: 1.02; }
.project-aside p { margin: 0; max-width: var(--measure); font-size: var(--text-md); line-height: 1.6; color: var(--color-ink-2); }
@media (min-width: 60.0625rem) {
    .wrap.is-split:has(> .project-aside) { grid-template-rows: auto 1fr; }
    .wrap.is-split:has(> .project-aside) > .prose-body { grid-column: 2; grid-row: 1 / span 2; }
    .wrap.is-split > .project-aside { grid-column: 1; grid-row: 2; align-self: end; max-width: 30rem; margin-top: var(--space-2xl); }
}
/* Captures de site au téléphone : recadrées sous le premier bloc utile (le bouton jaune de MCT,
   la première fiche d'Atari) au lieu d'être coupées par le pli. */
@media (max-width: 40rem) {
    .product-shot:is(.is-mct, .is-atari) img { object-fit: cover; object-position: top; }
    .product-shot.is-mct img { aspect-ratio: 780 / 730; }
    .product-shot.is-atari img { aspect-ratio: 780 / 868; }
}
/* À propos, services : la tête pleine largeur, puis la liste et la fiche de prix côte à côte. */
.about-offer .about-body { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-xl) var(--gap-columns); align-items: start; }
.about-offer .about-note { margin-top: 0; }
@media (min-width: 60.0625rem) { .about-offer .about-body { grid-template-columns: minmax(0, 6fr) minmax(0, 6fr); } }
/* Auteur : la précision devient une note sous le dernier filet des réalisations, au corps du texte. */
:is(.page-hero.is-about, .page-hero.is-author) ~ .section .proofs.author-proofs + .author-aside { margin-top: var(--space-lg); font-size: var(--text-md); line-height: 1.6; color: var(--color-muted); }
/* Le périmètre éditorial suit les réalisations sans le trou de deux paddings pleins : 64 + 64. */
@media (min-width: 60.0625rem) {
    .page-hero.is-author ~ .section:has(> .wrap > .author-proofs) { padding-bottom: var(--space-2xl); }
    .page-hero.is-author ~ .section:has(> .wrap > .author-proofs) + .section { padding-top: var(--space-2xl); }
}
/* Fin des pages projet en énoncé : la phrase sur toute la largeur, le texte et le bouton dessous. */
.project-end .project-end-head { justify-self: stretch; max-width: none; font-size: var(--text-display-s); line-height: 0.98; }
.project-end-head strong { display: block; }

/* Vague 6 · services6
   Pages de service. Le hero se centre en hauteur et entre d'un bloc ; la section suivante monte
   sous le pli. Le cas réel devient un puits relevé : le titre en tête, le récit en deux volets
   sous un filet vertical, les chiffres réels en Geist Mono. Les autres services quittent la fin
   de page pour leur propre section, une rangée à filets. */

/* ---------- Sous le hero : la première section monte, sans 176 px de fond nu ---------- */
.service-hero + .section.service-symptoms { padding-top: var(--space-3xl); }

/* ---------- Verbe suivi d'une ponctuation (« manque, ») : en ligne, la virgule ne passe plus seule à la ligne ---------- */
.service-hero h1 .verb { position: relative; display: inline; }
.service-hero h1 .verb::after { position: absolute; left: 0; right: 0; bottom: 0.02em; margin: 0; }

/* ---------- Cas réel : un puits relevé ---------- */
.service-case .case-well {
    display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); gap: var(--space-xl) var(--gap-columns);
    padding: var(--space-2xl); background: var(--color-paper-2); border: var(--rule-hair) solid var(--color-rule); border-radius: var(--radius-card);
}
.service-case .case-well > .section-head { grid-column: 1 / -1; margin: 0; }
.service-case .section-head h2 { max-width: 24ch; font-size: var(--text-display-s); line-height: 0.98; text-wrap: balance; }
.service-case .case-body { grid-column: 1 / -1; display: grid; grid-template-columns: subgrid; align-items: start; }
.service-case .case-lead { grid-column: 1 / span 6; margin: 0; font-size: var(--text-xl); line-height: 1.4; color: var(--color-ink); text-wrap: pretty; }
.service-case .case-rest { grid-column: 7 / -1; padding-left: var(--gap-columns); border-left: var(--rule-hair) solid var(--color-rule-2); }
.service-case .case-rest p { margin: 0 0 var(--space-md); font-size: var(--text-md); line-height: 1.6; color: var(--color-ink-2); }
.service-case .case-rest p:last-child { margin-bottom: 0; }
/* Le relevé : le code, le compteur ou la version que la machine a sortis, mots inchangés. Ce sont des chiffres de
   prose : Geist en chiffres tabulaires et en encre pleine, pas le mono (réservé aux messages cités des relevés d'état). */
.service-case .readout { color: var(--color-ink); font-variant-numeric: tabular-nums; white-space: nowrap; }
@media (max-width: 60rem) {
    .service-case .case-well { padding: var(--space-xl) var(--space-lg); }
    .service-case .case-lead, .service-case .case-rest { grid-column: 1 / -1; }
    .service-case .case-rest { margin-top: var(--space-lg); padding: var(--space-lg) 0 0; border-left: 0; border-top: var(--rule-hair) solid var(--color-rule-2); }
}
@media (max-width: 40rem) {
    .service-case .case-well { padding: var(--space-lg); }
    .service-case .case-lead { font-size: var(--text-lg); }
}

/* ---------- Autres services : leur section, la tête au-dessus de la rangée ---------- */
.service-other .section-head { margin-bottom: var(--space-xl); }
@media (max-width: 60rem) { .link-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } main .link-grid a { font-size: var(--text-md); text-wrap: balance; } }
@media (max-width: 40rem) { .link-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } main .link-grid a { min-height: 56px; } }

/* Vague 6 · accueil6 */
/* Accueil : la seconde moitié change de forme d'une section à l'autre. Têtes : services et tarifs
   côte à côte, WordPress et pourquoi empilées, projets posée sur sa grille, FAQ en colonne, guides
   empilés. Deux bandes : pourquoi, puis FAQ et guides. */

/* Console à 375 : chaque ligne du journal reste entière et le panneau défile en largeur (il est déjà
   focalisable et nommé par son onglet) ; l'adresse et le pied restent en place. Le bord droit s'efface
   sur la largeur de la marge de l'adresse (la pilule d'état reste nette) : on lit un défilement, pas une
   coupure ; le journal finit sur une marge qui sort du fondu. L'anneau de focus passe au cadre, que le masque ne coupe pas. */
.console-body { padding-bottom: var(--space-md); }
@media (max-width: 30rem) {
    .console-panel { overflow-x: auto; overscroll-behavior-x: contain; scrollbar-width: thin; mask-image: linear-gradient(to left, transparent, var(--color-paper) var(--space-md)); }
    .console-panel:focus-visible { outline: 0; }
    .console-panels:has(> .console-panel:focus-visible) { outline: 2px solid var(--color-focus); outline-offset: -2px; }
    .console-head, .console-foot { position: sticky; left: 0; }
    .console-body { width: max-content; min-width: 100%; padding-right: var(--space-xl); }
    .console-line { white-space: pre; word-break: normal; }
}

/* WordPress : les deux tuiles ont la même construction, tête, texte, figure au corps display, lien ;
   « http 500 » passe sous le texte, aligné à gauche, comme « marque blanche » à côté (7 + 5 colonnes) ;
   les quatre symptômes dessous, en rangée à filets. */
.wp-tile.is-lead { display: flex; flex-direction: column; align-items: flex-start; gap: var(--space-sm); }
.wp-tile.is-lead > .service-code.is-figure { margin-block: auto; padding-block: var(--space-lg); }
.wp-tile.is-lead > .service-more { padding-top: 0; }
.wp-figure { margin-block: auto; padding-block: var(--space-lg); font-family: var(--font-display); font-size: var(--text-display); line-height: 0.9; letter-spacing: var(--tracking-display); text-transform: lowercase; color: var(--color-ink); }
.wp-tile.is-agency > .service-more { align-self: flex-end; }
.wp-row { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); margin-top: var(--space-2xl); border-top: var(--rule-hair) solid var(--color-rule); }
.wp-row .wp-tile { grid-column: auto; padding: var(--space-lg) var(--space-lg) 0; background: none; border: 0; border-radius: 0; }
.wp-row .wp-tile:first-child { padding-left: 0; }
.wp-row .wp-tile:last-child { padding-right: 0; }
.wp-row .wp-tile + .wp-tile { border-left: var(--rule-hair) solid var(--color-rule); }
.wp-row .wp-tile:hover { transform: none; }
.wp-row .wp-tile-foot { flex-direction: column; align-items: flex-start; gap: var(--space-2xs); }

/* Pourquoi : la tête pleine largeur, les six raisons en 3 × 2 sur toute la grille. */
.home-why .proofs { grid-template-columns: repeat(3, minmax(0, 1fr)); }

/* Projets : la tête posée sur la grille des preuves, le chapeau sur la seconde colonne. */
.home-projects { padding-bottom: calc(0.75 * var(--section-gap-s)); }
.home-projects .section-head.is-stacked { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: var(--gap-columns); }
.home-projects .section-head.is-stacked > h2 { grid-column: 1 / -1; }
.home-projects .section-head.is-stacked > p { grid-column: 2; }

/* FAQ et guides : la seconde bande, resserrée sur les projets et sur elle-même ; le grand écart
   reste avant l'appel final. */
.faq-section.band { padding-top: calc(0.75 * var(--section-gap-s)); }
.home-guides { margin-top: calc(0.75 * var(--section-gap-s)); }

/* Méthode : le rail s'arrête au nœud de la dernière étape. */
.method .steps::before, .method .steps::after { right: calc((100% - 3 * var(--gap-columns)) / 4 - 24px); }

@media (max-width: 75rem) {
    .pledges { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .pledges li, .pledges li:first-child, .pledges li:last-child { padding: var(--space-lg) var(--space-lg) var(--space-lg) 0; }
    .pledges li:nth-child(even) { padding-right: 0; padding-left: var(--space-lg); }
    .pledges li:nth-child(odd) { border-left: 0; }
    .pledges li:nth-child(n + 3) { border-top: var(--rule-hair) solid var(--color-rule); padding-bottom: 0; }
}
@media (max-width: 60rem) {
    .wp-row { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .wp-row .wp-tile, .wp-row .wp-tile:first-child, .wp-row .wp-tile:last-child { padding: var(--space-lg) 0 var(--space-lg) var(--space-lg); }
    .wp-row .wp-tile:nth-child(odd) { padding-left: 0; padding-right: var(--space-lg); border-left: 0; }
    .wp-row .wp-tile:nth-child(n + 3) { border-top: var(--rule-hair) solid var(--color-rule); padding-bottom: 0; }
    .home-why .proofs { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .home-projects .section-head.is-stacked > p { grid-column: 1 / -1; }
    .method .steps::before, .method .steps::after { right: auto; }
    /* Rail vertical : masqué sous le nœud de la dernière étape. */
    .method .steps li:last-child::after { content: ""; position: absolute; z-index: var(--z-base); top: 48px; bottom: 0; left: 22px; width: 4px; background: var(--color-paper); }
}
@media (max-width: 40rem) {
    .pledges { grid-template-columns: minmax(0, 1fr); }
    .pledges li, .pledges li:nth-child(n) { padding: var(--space-lg) 0; border-left: 0; }
    .pledges li + li { border-top: var(--rule-hair) solid var(--color-rule); }
    .pledges li:last-child { padding-bottom: 0; }
    .wp-tile.is-lead { grid-template-columns: minmax(0, 1fr); grid-template-rows: none; }
    .wp-tile.is-lead > :is(h3, p, .service-code.is-figure, .service-more) { grid-column: 1; grid-row: auto; }
    .wp-tile.is-lead > .service-code.is-figure { align-self: start; padding-top: var(--space-md); }
    .wp-tile.is-lead > .service-more { justify-self: end; padding-top: 0; }
    .wp-row { grid-template-columns: minmax(0, 1fr); }
    .wp-row .wp-tile, .wp-row .wp-tile:nth-child(n) { padding: var(--space-lg) 0; border-left: 0; }
    .wp-row .wp-tile + .wp-tile { border-top: var(--rule-hair) solid var(--color-rule); }
    .wp-row .wp-tile:last-child { padding-bottom: 0; }
    .home-why .proofs { grid-template-columns: minmax(0, 1fr); }
}

/* Vague 6 · lecture6 */
/* Chiffres des têtes : Instrument Serif n'a ni lnum ni variante du « 1 », qui se lit « l » en minuscules.
   Une face « Lumen Chiffres » reprend le fichier Geist déjà chargé (même URL), limitée aux chiffres,
   en graisse 300 et au corps des chiffres du serif ; elle passe en tête du jeton --font-display, donc
   de toutes les têtes en serif (prix, chiffres des services, guides, FAQ, documents). Le texte ne change pas. */
@font-face { font-family: "Lumen Chiffres"; src: url("/fonts/geist-latin-wght-normal.woff2") format("woff2"); font-weight: 300; font-style: normal; font-display: swap; unicode-range: U+30-39; size-adjust: 86%; }

/* Fil d'Ariane au téléphone : une seule ligne, le dernier maillon (le titre, repris dessous par le h1)
   finit en ellipse ; son texte reste entier dans le DOM. */
@media (max-width: 40rem) {
  .breadcrumb { display: flex; flex-wrap: nowrap; align-items: baseline; }
  .breadcrumb > * { flex: none; }
  .breadcrumb > span::before { white-space: pre; }
  .breadcrumb > span:last-child { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
}

/* Étude de cas au téléphone : le schéma s'ouvre sur la fin de la courbe (déclencheur, chute, point final) ;
   le défilement remonte vers le plateau, le bord gauche s'efface. Plancher de 40rem : libellés à 11,5 px. */
@media (max-width: 47.9375rem) {
  .article-hero.is-case .figure-scroll { direction: rtl; padding-right: 0; padding-left: var(--space-xl); mask-image: linear-gradient(to right, transparent, var(--color-paper) var(--space-xl)); }
  .article-hero.is-case .figure-scroll svg { direction: ltr; min-width: 40rem; }
}

/* Annexe : sources et auteur côte à côte ; l'historique en dates alignées et le glossaire sur deux colonnes
   prennent toute la largeur, sans trou face à un bloc plus court. */
@media (min-width: 60.0625rem) {
  .article-annex :is(.changelog, .glo-related) { grid-column: 1 / -1; }
  .article-annex .changelog > p { max-width: var(--measure); }
  .article-annex .changelog ol { display: grid; grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr)); gap: 0 var(--gap-columns); }
  .article-annex .changelog li { grid-template-columns: minmax(0, 1fr); align-content: start; gap: var(--space-2xs); padding: var(--space-sm) 0 0; border-top: var(--rule-hair) solid var(--color-rule-2); border-bottom: 0; }
  .article-annex .glo-related ul { columns: 2; column-gap: var(--gap-columns); }
  .article-annex .glo-related li { break-inside: avoid; }
}

/* Glossaire : « pourquoi » et « erreur fréquente » côte à côte, chacun sous un filet, l'étiquette au-dessus. */
@media (min-width: 60.0625rem) {
  .glo-meta { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-lg) var(--gap-columns); }
  .glo-row { grid-template-columns: minmax(0, 1fr); align-content: start; gap: var(--space-2xs); padding-top: var(--space-sm); border-top: var(--rule-hair) solid var(--color-rule); }
}

/* CGV, formules : une grille tarifaire à filets, la formule en tête minuscule, le prix aligné à droite
   en chiffres tabulaires, ce qu'elle couvre dessous. */
.page-content.is-doc > ul.cgv-rates { margin-bottom: var(--space-xl); padding-left: 0; list-style: none; }
.page-content.is-doc > .cgv-rates > li { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: baseline; gap: var(--space-2xs) var(--space-lg); max-width: none; margin: 0; padding: var(--space-md) 0; border-bottom: var(--rule-hair) solid var(--color-rule); }
.page-content.is-doc > .cgv-rates strong { font-family: var(--font-display); font-size: var(--text-2xl); font-weight: var(--display-weight); line-height: 1.1; letter-spacing: var(--tracking-display); text-transform: lowercase; color: var(--color-ink); }
.cgv-price { font-family: var(--font-body); font-size: var(--text-xl); font-variant-numeric: tabular-nums; line-height: 1.1; text-align: right; white-space: nowrap; color: var(--color-ink); }
.cgv-what { grid-column: 1 / -1; max-width: var(--measure); }

/* Charte, exigences : une grille 2 × 2 à filets, chaque exigence ouverte par sa tête en serif. */
.page-content.is-doc > ul.charter-grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-xl) var(--gap-columns); max-width: none; padding: 0; border-top: 0; list-style: none; }
.page-content.is-doc > .charter-grid > li { max-width: none; margin: 0; padding: var(--space-md) 0 0; border-top: var(--rule-hair) solid var(--color-rule-2); }
.page-content.is-doc > .charter-grid strong { display: block; margin-bottom: var(--space-xs); font-family: var(--font-display); font-size: var(--text-2xl); font-weight: var(--display-weight); line-height: 1.1; letter-spacing: var(--tracking-display); text-transform: lowercase; color: var(--color-ink); }
@media (min-width: 40.0625rem) {
  .page-content.is-doc > ul.charter-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* Vague 6 · conversion6 */
/* Contact : le document se cale sur la deuxième colonne du bandeau (6/6, x 736 à 1440), intertitres au corps
   de section (dérogation 78) ; les deux voies d'entrée deviennent deux puits côte à côte, l'adresse en grand. */
.page-content.is-doc.is-contact h2 { text-transform: lowercase; }
.page-content.is-doc.is-contact > .doc-cards { grid-template-columns: minmax(0, 1fr); gap: var(--space-lg) var(--gap-columns); margin-bottom: var(--space-xl); }
.is-contact .doc-card { gap: var(--space-md); padding: var(--space-xl); color: var(--color-ink); background: var(--color-paper-2); border: var(--rule-hair) solid var(--color-rule); border-radius: var(--radius-card); }
.is-contact .doc-card h2 { font-size: var(--text-2xl); line-height: 1.05; text-wrap: balance; }
.is-contact .doc-card p { margin: 0; }
.is-contact .doc-card > :last-child { margin-top: auto; }
.is-contact .contact-email { font: 400 clamp(var(--text-2xl), 3vw, var(--text-section))/1.1 var(--font-display); letter-spacing: var(--tracking-display); text-decoration-thickness: var(--rule-hair); text-underline-offset: 0.16em; }
.page-content.is-doc.is-contact > h2 { font-size: var(--text-section); line-height: 0.98; text-wrap: balance; }
/* Listes du document : rangées à filet, sans puce. */
.page-content.is-doc.is-contact > ul { list-style: none; padding-left: 0; border-top: var(--rule-hair) solid var(--color-rule-2); }
.page-content.is-doc.is-contact > ul li { max-width: none; margin: 0; padding: var(--space-sm) 0; border-bottom: var(--rule-hair) solid var(--color-rule); }
.page-content.is-doc.is-contact > h2 + ul { padding-top: 0; }
@media (min-width: 60.0625rem) {
    .page-content.is-doc.is-contact { grid-template-columns: minmax(0, 6fr) minmax(0, 6fr); }
    .page-content.is-doc.is-contact > .doc-cards { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .page-content.is-doc.is-contact > h2 { max-width: 13ch; }
    .page-content.is-doc.is-contact > h2 + * { margin-top: var(--space-2xl); }
}

/* Agences : « comment ça se passe » en rail sur la trame (dérogation 47c, la trame seulement sous le rail,
   jamais sous la prose). Numéros en chiffres serif sur des repères, sans anneau : rien de commun avec
   les pastilles du devis. */
.section.is-flow { padding-block: var(--section-gap); }
.section.is-flow .steps {
    padding: calc(var(--space-3xl) + var(--space-lg)) var(--space-xl) var(--space-xl);
    background: var(--color-paper-2); color: var(--color-ink); border: var(--rule-hair) solid var(--color-rule); border-radius: var(--radius-card);
}
.section.is-flow .steps::after {
    content: ""; inset: 0 0 auto; width: auto; height: var(--space-3xl); transform: none;
    background-color: transparent; background-image: linear-gradient(var(--rule-blueprint) 1px, transparent 1px), linear-gradient(90deg, var(--rule-blueprint) 1px, transparent 1px);
    background-size: 48px 48px; border-bottom: var(--rule-hair) solid var(--color-rule); border-radius: var(--radius-card) var(--radius-card) 0 0;
}
.section.is-flow .steps::before { left: var(--space-xl); right: var(--space-xl); top: calc(var(--space-3xl) - var(--space-lg)); bottom: auto; width: auto; height: var(--rule-hair); z-index: var(--z-base); }
.section.is-flow .steps li { padding: 0; }
.section.is-flow .steps li::before {
    top: calc(-1 * var(--space-3xl)); left: 0; width: auto; height: auto; display: block; border-radius: 0; background: none; box-shadow: none;
    font: 400 var(--text-2xl)/1 var(--font-display); font-variant-numeric: tabular-nums; color: var(--color-ink-2);
}
.section.is-flow .steps li::after { content: ""; position: absolute; left: 0; top: calc(-2 * var(--space-lg)); width: var(--rule-hair); height: var(--space-sm); background: var(--color-ink-2); z-index: var(--z-base); }
@media (max-width: 60rem) {
    .section.is-flow { padding-block: var(--section-gap-s); }
    .section.is-flow .steps { gap: var(--space-xl); padding: var(--space-lg) var(--space-lg) var(--space-lg) calc(var(--space-2xl) + var(--space-lg)); }
    .section.is-flow .steps::after { inset: 0 auto 0 0; width: var(--space-2xl); height: auto; border-bottom: 0; border-right: var(--rule-hair) solid var(--color-rule); border-radius: var(--radius-card) 0 0 var(--radius-card); }
    .section.is-flow .steps::before { content: none; }
    .section.is-flow .steps li::before { top: 0; left: calc(-1 * (var(--space-2xl) + var(--space-lg))); width: var(--space-2xl); text-align: center; }
    .section.is-flow .steps li::after { content: none; }
    .ink-pledge :is(strong, p) { grid-column: 1 / -1; }
}
.section.is-flow + .section { padding-top: var(--space-2xl); }

/* Agences, sous la grille de prix : la note sur toute la largeur, l'amorce sous « audit », les rangées
   sous les trois autres fiches, à partir de celle qu'elle commente. */
@media (min-width: 60.0625rem) {
    .pricing.is-four + .scope-note { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); }
    .pricing.is-four + .scope-note > strong { grid-column: 1; margin: 0; padding: var(--space-sm) var(--space-lg) 0; }
    .pricing.is-four + .scope-note > ul { grid-column: 2 / -1; margin-inline: var(--space-lg); }
}

/* Tirets d'Instrument Serif : 0,08 em d'approche de chaque côté contre 0,02 em pour les lettres ; on rend la différence. */
.tiret { margin-inline: -0.06em; }

/* Tarifs : « ce qu'une intervention couvre » prolonge la fiche, écart court au-dessus ; sa tête est empilée
   (vue : is-stacked) au lieu d'une troisième rangée scindée. */
.section[aria-labelledby="pricing-title"] + .section[aria-labelledby="scope-title"] { padding-top: 0; }

/* Agences : l'amorce des notes de la bande garde le ton d'étiquette (la bande éclaire ses gras). */
.section-ink .scope-note strong { color: var(--color-muted); }

/* p10a début */
/* ---------- Méthode : une forme par page (vue : $methodVariant) ---------- */

/* Rail à nœuds de l'accueil (dépannage, SEO WordPress) : nœuds de 48 px numérotés en laiton
   sur un filet, le tracé laiton par-dessus ; titres au corps de l'accueil, sans cases. */
.service-method.is-rail .path { padding: var(--space-2xl) var(--space-xl); }
.service-method.is-rail .steps { grid-template-columns: repeat(4, minmax(0, 1fr)); grid-template-rows: none; grid-auto-flow: row; padding: 0; }
/* Le filet et le tracé s'arrêtent au dernier nœud. */
.service-method.is-rail .steps::before { grid-row: auto; inset: 24px auto auto 24px; height: var(--rule-hair); z-index: auto; background: var(--color-rule-2); border: 0; }
.service-method.is-rail .steps::after { grid-row: auto; top: 24px; left: 24px; }
.service-method.is-rail .steps::before, .service-method.is-rail .steps::after { right: calc((100% - 3 * var(--gap-columns)) / 4 - 24px); }
.service-method.is-rail .steps li { display: block; grid-row: auto; padding-top: calc(48px + var(--space-lg)); }
.service-method.is-rail .steps li::before { content: counter(step, decimal-leading-zero); }
.service-method.is-rail .steps h3 { margin: 0 0 var(--space-sm); padding: 0; background: none; border: 0; border-radius: 0; font-size: var(--text-2xl); line-height: 1.02; }
.service-method.is-rail .steps h3::before { content: none; }
.service-method.is-rail .steps p { padding: 0; }

/* Schéma à deux chemins (automatisation) : sur la bande de trame, les nœuds à filet laiton, numérotés en
   mono, reliés par un filet droit en encre seconde (le chemin automatisé) et, au-dessus, la voie en tirets
   (le chemin à la main, bloc p13a) ; le laiton reste aux nœuds, le filet ne domine plus ; les textes sous la bande. */
.service-method.is-diagram { --node: 40px; --band: 96px; }
.service-method.is-diagram .steps { grid-template-columns: repeat(4, minmax(0, 1fr)); grid-template-rows: none; grid-auto-flow: row; padding: var(--band) var(--space-xl) 0; }
.service-method.is-diagram .steps::before { grid-row: auto; inset: 0 0 auto; height: var(--band); }
.service-method.is-diagram .steps::after { content: none; }
.service-method.is-diagram .steps li { display: block; grid-row: auto; padding: var(--space-lg) 0 var(--space-xl); }
.service-method.is-diagram .steps li::before {
    content: counter(step, decimal-leading-zero); top: calc(var(--band) / -2 - var(--node) / 2); width: var(--node); height: var(--node);
    box-shadow: inset 0 0 0 var(--rule-hair) var(--color-accent); color: var(--color-ink-2);
}
.service-method.is-diagram .steps h3 { margin: 0 0 var(--space-sm); padding: 0; background: none; border: 0; border-radius: 0; }
.service-method.is-diagram .steps h3::before { content: none; }
.service-method.is-diagram .steps li:not(:last-child) h3::before {
    content: ""; position: absolute; z-index: 0; top: calc(var(--band) / -2); left: calc(var(--node) / 2);
    width: calc(100% + var(--gap-columns)); height: var(--rule-hair); margin: 0; background: var(--color-ink-2);
}
.service-method.is-diagram .steps li:not(:last-child)::after {
    content: ""; position: absolute; z-index: 0; top: calc(var(--band) / -2 - 28px); left: calc(var(--node) / 2);
    width: calc(100% + var(--gap-columns)); height: 28px; box-sizing: border-box;
    border: var(--rule-hair) dashed var(--color-muted); border-bottom: 0; border-radius: 28px 28px 0 0;
}
.service-method.is-diagram .steps p { padding: 0; }

/* Chemin vertical des guides (sécurité PHP, migration, piratage) : sans puits, la tête à gauche, les étapes
   à droite ; le numéro en Geist tabulaire atténué, comme l'accueil, un anneau de 9 px sur un filet vertical d'un nœud à l'autre. */
.service-method.is-vertical { --num: 3rem; }
.service-method.is-vertical .path { padding: 0; background: none; border: 0; border-radius: 0; overflow: visible; }
.service-method.is-vertical .steps { display: block; padding: 0; }
.service-method.is-vertical .steps::before, .service-method.is-vertical .steps::after { content: none; }
.service-method.is-vertical .steps li { display: grid; grid-template-columns: var(--num) minmax(0, 1fr); grid-template-rows: none; padding: 0 0 var(--space-xl); font-size: var(--text-xl); }
.service-method.is-vertical .steps li + li { margin-top: 0; }
.service-method.is-vertical .steps li:last-child { padding-bottom: 0; }
.service-method.is-vertical .steps li::before {
    content: counter(step, decimal-leading-zero); position: static; grid-column: 1; grid-row: 1; display: block; width: auto; height: auto;
    background: none; box-shadow: none; border-radius: 0; font: 400 var(--text-xs)/calc(1.05 * var(--text-xl)) var(--font-body); color: var(--color-muted); font-variant-numeric: tabular-nums;
}
.service-method.is-vertical .steps li:not(:last-child)::after {
    content: ""; position: absolute; left: calc(var(--num) + 4px); top: calc(0.525em + 4.5px); bottom: calc(-0.525em + 4.5px);
    width: var(--rule-hair); background: var(--color-rule-2);
}
.service-method.is-vertical .steps h3 { grid-column: 2; position: relative; margin: 0 0 var(--space-sm); padding: 0 0 0 var(--space-xl); background: none; border: 0; border-radius: 0; font-size: 1em; line-height: 1.05; }
.service-method.is-vertical .steps h3::before {
    content: ""; position: absolute; left: 0; top: calc(0.525em - 4.5px); width: 9px; height: 9px; margin: 0; box-sizing: border-box;
    border: var(--rule-hair) solid var(--color-ink-2); border-radius: 50%;
}
.service-method.is-vertical .steps p { grid-column: 2; margin: 0; padding: 0 0 0 var(--space-xl); max-width: calc(62ch + var(--space-xl)); }
@media (min-width: 60.0625rem) {
    .service-method.is-vertical .wrap { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); gap: 0 var(--gap-columns); align-items: start; }
    .section.service-method.is-vertical > .wrap > .section-head:has(> h2 + p) { grid-column: 1 / span 4; grid-template-columns: minmax(0, 1fr); gap: var(--space-md); align-items: start; margin: 0; }
    .service-method.is-vertical .path { grid-column: 6 / -1; }
}

@media (max-width: 60rem) {
    .service-method.is-rail .path { padding: var(--space-xl) var(--space-lg); }
    .service-method.is-rail .steps { grid-template-columns: minmax(0, 1fr); gap: var(--space-xl); }
    /* Le rail descend d'un nœud au suivant et s'arrête au dernier. */
    .service-method.is-rail .steps::before, .service-method.is-rail .steps::after { content: none; }
    .service-method.is-rail .steps li:not(:last-child)::after { content: ""; position: absolute; left: 24px; top: 48px; width: var(--rule-hair); height: calc(100% + var(--space-xl) - 48px); background: var(--color-accent); }
    .service-method.is-rail .steps li { padding: var(--space-sm) 0 0 calc(48px + var(--space-lg)); }
    .service-method.is-rail .steps li + li { margin-top: 0; }
    .service-method.is-rail .steps h3 { font-size: var(--text-xl); }

    /* Le schéma se lit de haut en bas : filet vertical d'un nœud à l'autre, la voie en tirets à gauche. */
    .service-method.is-diagram .steps { grid-template-columns: minmax(0, 1fr); row-gap: var(--space-xl); padding: var(--space-xl) var(--space-lg) var(--space-xl) calc(var(--space-lg) + 20px); }
    .service-method.is-diagram .steps::before { content: none; }
    .service-method.is-diagram .steps li { min-height: var(--node); padding: 0 0 0 calc(var(--node) + var(--space-md)); }
    .service-method.is-diagram .steps li + li { margin-top: 0; }
    .service-method.is-diagram .steps li::before { top: 0; }
    .service-method.is-diagram .steps h3 { padding-top: calc((var(--node) - 1.05em) / 2); }
    .service-method.is-diagram .steps li:not(:last-child) h3::before { top: calc(var(--node) / 2); width: var(--rule-hair); height: calc(100% + var(--space-xl)); }
    .service-method.is-diagram .steps li:not(:last-child)::after {
        top: calc(var(--node) / 2); left: -20px; width: calc(var(--node) / 2 + 20px); height: calc(100% + var(--space-xl));
        border: var(--rule-hair) dashed var(--color-muted); border-right: 0; border-radius: 20px 0 0 20px;
    }

    .service-method.is-vertical { --num: 2.25rem; }
}

/* ---------- Cas réel à découvert (serveur, piratage) : sans puits, la tête à gauche,
   le chapô puis la suite sur deux colonnes sous un filet ---------- */
.service-case.is-open .case-well { padding: 0; background: none; border: 0; border-radius: 0; }
@media (min-width: 60.0625rem) {
    .service-case.is-open .case-well > .section-head { grid-column: 1 / span 5; }
    .service-case.is-open .section-head h2 { max-width: 14ch; font-size: var(--text-display-s); line-height: 0.98; }
    .service-case.is-open .case-body { grid-column: 6 / -1; }
    .service-case.is-open .case-lead { grid-column: 1 / -1; }
    .service-case.is-open .case-rest { grid-column: 1 / -1; margin-top: var(--space-lg); padding: var(--space-lg) 0 0; border-left: 0; border-top: var(--rule-hair) solid var(--color-rule-2); columns: 2; column-gap: var(--gap-columns); }
    .service-case.is-open .case-rest > * { break-inside: avoid; }
}
/* ---------- Relevé d'état sur téléphone : un relevé long (statut de la Search Console) passe à la ligne,
   chaque morceau garde son filet ---------- */
@media (max-width: 40rem) {
    .service-symptoms.is-states samp.is-long { white-space: normal; -webkit-box-decoration-break: clone; box-decoration-break: clone; }
}
/* p10a fin */

/* a11y9 début */
/* 1.4.1 : le trait des liens du texte passe de --color-rule-2 (1,8:1) à --color-muted (6,9:1) ; le survol garde l'accent. */
main p a, .footer-brand a { text-decoration-color: var(--color-muted); }
:is(.page-content, .prose-body, .case-body, .faq-item, .changelog, .glo-related, .about-services, .about-note, .about-proofs, .about-links, .article-meta, .case-meta, .res-item) a:not(.btn, .article-cat),
.contact-email, .vp-more { text-decoration-color: var(--color-muted); }

/* 1.4.1 : la page courante du menu se lit aussi par un trait (accent), pas par la couleur seule. */
.main-nav a[aria-current] { text-decoration: underline; text-decoration-color: var(--color-accent); text-decoration-thickness: var(--rule-hair); }
@media (min-width: 68.0625rem) {
    .main-nav a[aria-current] { text-underline-offset: 0.4em; }
}

/* 1.4.4 : un libellé de bouton passe à la ligne au lieu d'être coupé quand le texte est agrandi.
   Les rem d'une requête média suivent la taille de texte du navigateur : 40 rem ne couvre que les petits écrans ou un texte agrandi. */
@media (max-width: 40rem) {
    .btn { white-space: normal; text-align: center; padding-block: var(--space-xs); }
}

/* 1.4.4 / 1.4.10 : l'en-tête mobile passe à la ligne (et le logo se replie) quand le logo et « Menu » ne tiennent plus côte à côte. */
@media (max-width: 68rem) {
    .js .header-inner { flex-wrap: wrap; height: auto; min-height: var(--header-h); }
    .js .logo { flex-shrink: 1; min-width: 0; flex-wrap: wrap; }
    /* Le panneau du menu démarre sous l'en-tête réel (site.js pose --nav-top), même quand celui-ci passe sur deux lignes. */
    .js .main-nav { padding-top: calc(var(--nav-top, calc(var(--header-top) + var(--header-h))) + var(--space-xl)); }
}
@media (max-width: 68rem) and (max-height: 30rem) and (min-width: 34rem) {
    .js .main-nav { padding-top: calc(var(--nav-top, calc(var(--header-top) + var(--header-h))) + var(--space-md)); }
}

/* 1.4.4 : relevés et URL longues cassent plutôt que de sortir de leur boîte. */
.about-links a { overflow-wrap: anywhere; }
@media (max-width: 40rem) {
    .service-code { white-space: normal; overflow-wrap: anywhere; }
}
/* 22 rem ne couvre que 320 px ou un texte agrandi (voir plus haut). */
@media (max-width: 22rem) {
    .service-symptoms.is-states samp { white-space: normal; overflow-wrap: anywhere; }
}

/* 1.4.11 : en contraste forcé, les cadres tracés en box-shadow disparaissent ; un contour système les remplace. */
@media (forced-colors: active) {
    :is(.btn-primary, .btn-outline, .btn-dark, .btn-light, .nav-cta, .menu-toggle, .status-pill, .journey-panel, .proof-tile, .guide-link, .launch-badge, .price-card):not(:focus-visible) {
        outline: 1px solid ButtonText; outline-offset: -1px;
    }
    .price-card.is-featured:not(:focus-visible) { outline: 2px solid Highlight; outline-offset: -2px; }
    .console-tab[aria-selected="true"] { outline: 2px solid Highlight; outline-offset: -2px; text-decoration: underline; }
    .journey li::before, .devis-next .steps li::before { outline: 1px solid ButtonText; outline-offset: -1px; }
    .main-nav a[aria-current] { text-decoration-color: Highlight; }
    main p a, .footer-brand a, .contact-email, .vp-more { text-decoration-color: LinkText; }
}
/* a11y9 fin */

/* p10b début */
/* Clôtures : une seule forme pour l'appel final (.cta-band) et les fins de page de la famille « à propos »
   (/a-propos, /atari-retrogaming, /mon-controle-technique), celle de la Suite : sous un filet, la tête en
   colonne 1, le texte et les pilules en colonne 2, sur la grille 6/6 des rangées scindées. */
.cta-band { row-gap: var(--space-lg); padding-top: var(--space-xl); border-top: var(--rule-hair) solid var(--color-rule-2); }
@media (min-width: 60.0625rem) {
    .about-contact { grid-template-columns: minmax(0, 6fr) minmax(0, 6fr); align-items: start; }
    .about-contact > h2 { grid-column: 1; }
    .about-contact > .prose-body { grid-column: 2; }
    .section > .wrap > .project-end { grid-template-columns: minmax(0, 6fr) minmax(0, 6fr); grid-template-rows: auto 1fr; row-gap: var(--space-lg); align-items: start; }
    .project-end .project-end-head { grid-column: 1; grid-row: 1 / -1; }
    .project-end > div > p:not(.project-end-head) { grid-column: 2; grid-row: 1; }
    .project-end > div { display: grid; grid-column: 1 / -1; grid-row: 1 / -1; grid-template-columns: subgrid; grid-template-rows: subgrid; align-items: start; justify-items: start; }
    .project-end > div > .btn { grid-column: 2; grid-row: 2; }
}
/* Le bouton fait partie du groupe tête, réponse, action : la réponse ne prend pas de marge basse
   et le bouton garde l'écart d'avant (sur grand écran, celui de la grille). */
.cta-band > div:first-child > p { margin-bottom: 0; }
.cta-band > div:first-child > .cta-band-actions { margin-top: var(--space-lg); }
@media (min-width: 60.0625rem) { .cta-band > div:first-child > .cta-band-actions { margin-top: 0; } }

/* /outils/version-php : une seule grille, celle du bandeau d'index (12 colonnes, chapô en colonne 8).
   Formulaire et têtes sur les sept premières, note, tableau des versions et prose de clôture sur les cinq
   dernières : chapô, note, tableau et prose partent du même x. */
@media (min-width: 60.0625rem) {
    :is(.vp-layout, .section:has(> .vp-layout) ~ .section > .wrap.is-split) { grid-template-columns: repeat(12, minmax(0, 1fr)); }
    :is(.vp-layout, .section:has(> .vp-layout) ~ .section > .wrap.is-split) > :first-child { grid-column: 1 / span 7; }
    :is(.vp-layout, .section:has(> .vp-layout) ~ .section > .wrap.is-split) > :nth-child(2) { grid-column: 8 / -1; }
}
/* Le tableau des versions est un relevé : il se pose dans un puits, en face du puits du formulaire. */
.vp-versions { padding: var(--space-lg); background: var(--color-paper-2); border: var(--rule-hair) solid var(--color-rule); border-radius: var(--radius-card); }
.vp-versions .vp-table tr > :last-child { padding-right: 0; }
/* p10b fin */

/* p11a début */
/* Relevé d'état de l'automatisation : la fréquence ou le volume de la tâche ne sont ni du code ni une mesure de la
   machine, donc pas de mono ; ils passent en encre pleine, un cran plus lourds, sur le texte en encre atténuée. */
.service-symptoms .symptoms .freq { color: var(--color-ink); font-weight: 500; }

/* Clôture : le changement de fond de la bande qui la précède (.band de l'accueil, .section-ink de /auteur) marque déjà
   la limite, pas de second filet. */
:is(.band, .section-ink) + .section > .wrap > .cta-band { border-top: 0; padding-top: 0; }
/* p11a fin */

/* p11b début */
/* Une référence (CVE, tournure à trait d'union) ne se coupe pas à son tiret. */
.nowrap { white-space: nowrap; }
.guide-link strong .nowrap { font: inherit; color: inherit; text-transform: inherit; }

/* Auteur : titre, fonction et chapô partent du même haut, la fonction et le chapô en colonne 7 (comme /a-propos). */
@media (min-width: 75.0625rem) {
    .page-hero.is-author:not(.article-hero) > .wrap:not(.author-hero) > h1 { grid-column: 1 / span 6; grid-row: 2 / span 2; align-self: start; margin-bottom: 0; }
    .page-hero.is-author:not(.article-hero) > .wrap:not(.author-hero) > .author-role { grid-column: 7 / -1; grid-row: 2; align-self: start; }
    .page-hero.is-author:not(.article-hero) > .wrap:not(.author-hero) > .author-role + .lead { grid-column: 7 / -1; grid-row: 3; align-self: start; }
}

/* Guides à schéma : la méta sur toute la largeur sous le titre, puis le chapô et le schéma sur la même rangée. */
@media (min-width: 80rem) {
    .article-hero.is-stage > .wrap > .article-meta { grid-column: 1 / -1; grid-row: 3; margin-bottom: var(--space-xs); }
    .article-hero.is-stage > .wrap > .article-stage-lead { grid-row: 4; }
    .article-hero.is-stage > .wrap > .article-figure { grid-row: 4; margin-top: var(--space-lg); }
}

/* Guides sans schéma : le titre à l'échelle sur neuf colonnes, la méta en marge à droite, en pied de titre. */
@media (min-width: 60.0625rem) {
    .page-hero.article-hero:not(.is-stage) > .wrap { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: var(--gap-columns); align-items: end; }
    .page-hero.article-hero:not(.is-stage) > .wrap > .breadcrumb { grid-column: 1 / -1; align-self: start; }
    .page-hero.article-hero:not(.is-stage) > .wrap > h1 { grid-column: 1 / span 9; max-width: none; margin: 0; font-size: var(--text-display); text-wrap: balance; }
    .page-hero.article-hero:not(.is-stage) > .wrap > .article-meta { grid-column: 10 / -1; flex-direction: column; align-items: flex-start; gap: var(--space-xs); margin: 0 0 var(--space-xs); padding: var(--space-xs) 0 var(--space-xs) var(--space-lg); border-left: var(--rule-hair) solid var(--color-rule-2); clip-path: none; }
    .page-hero.article-hero:not(.is-stage) > .wrap > .article-meta > :not(.dot, :first-child)::before { content: none; }
    .page-hero.article-hero:not(.is-stage) > .wrap > .article-meta .article-cat { margin-bottom: var(--space-2xs); }
}
/* p11b fin */

/* p12a début */
/* Cas réel en colonnes sous filet (sécurité PHP, référencement) : ni puits ni vis-à-vis, la tête sur toute la largeur,
   puis le chapô et chaque paragraphe de la suite dans leur colonne, chacune ouverte par son filet. Trois paragraphes,
   trois colonnes de quatre ; deux paragraphes, une colonne de cinq et une de six. Mots et ordre de lecture inchangés. */
.service-case.is-columns .case-well { padding: 0; background: none; border: 0; border-radius: 0; }
.service-case.is-columns .case-body { row-gap: var(--space-lg); }
.service-case.is-columns .case-lead { padding-top: var(--space-md); border-top: var(--rule-hair) solid var(--color-rule-2); }
.service-case.is-columns .case-rest { display: grid; margin: 0; padding: 0; border: 0; row-gap: var(--space-lg); }
.service-case.is-columns .case-rest p { margin: 0; padding-top: var(--space-md); border-top: var(--rule-hair) solid var(--color-rule-2); }
.service-case.is-columns .case-rest > p:has(> a:only-child) { padding-top: 0; border-top: 0; }
@media (min-width: 60.0625rem) {
    .service-case.is-columns .case-lead { grid-column: 1 / span 5; }
    .service-case.is-columns .case-rest { grid-column: 7 / -1; }
    .service-case.is-columns .case-body:not(:has(.case-rest > :nth-child(3))) .case-rest p { font-size: var(--text-lg); line-height: 1.5; }
    .service-case.is-columns .case-body:has(.case-rest > :nth-child(3)) .case-lead { grid-column: 1 / span 4; }
    .service-case.is-columns .case-body:has(.case-rest > :nth-child(3)) .case-rest { grid-column: 5 / -1; grid-template-columns: subgrid; }
    .service-case.is-columns .case-body:has(.case-rest > :nth-child(3)) .case-rest > p { grid-column: span 4; }
    .service-case.is-columns .case-body:has(.case-rest > :nth-child(3)) .case-rest > p:has(> a:only-child) { grid-column: 1 / -1; }
}
/* p12a fin */

/* p13b début */
/* ---------- À propos, « mes projets » ; auteur, « réalisations publiques » : rangées d'index ---------- */
/* Le nom au corps des rubriques de /guides (--text-section) sur 7 colonnes, la phrase à droite sur la dernière ligne de base, un filet par rangée. */
.tools-grid.is-links.about-index > .tool-row { padding-block: var(--space-xl); }
.tools-grid.is-links.about-index .tool-row h3,
.proofs.author-proofs .proof h3 { font-size: var(--text-section); line-height: 0.98; letter-spacing: var(--tracking-display); text-wrap: balance; }
.tools-grid.is-links.about-index .tool-row-body p,
.proofs.author-proofs .proof p { color: var(--color-ink-2); }
.proofs.author-proofs .proof { padding-block: var(--space-xl); }
@media (min-width: 60.0625rem) {
    .page-hero.is-about ~ .section .tools-grid.is-links.about-index > .tool-row,
    .proofs.author-proofs .proof { grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); align-items: last baseline; }
    /* La précision qui suit les réalisations sort de leur grille : sous le filet de clôture, alignée sur la colonne des
       titres, en muted ; elle ne se lit plus comme une quatrième rangée sans titre. */
    .section > .wrap > .proofs.author-proofs + .author-aside { margin-left: 0; }
}

/* ---------- À propos, « ma façon de travailler » : la pile technique en bandeau dans un puits ---------- */
/* Sur grand écran : la tête et la phrase d'annonce à gauche, la méthode à droite, puis la pile sur toute la largeur,
   neuf cellules sur une ligne séparées par des filets, juste sous les deux points de l'annonce (ordre du DOM gardé).
   Les noms d'outils ne sont pas des relevés de machine : Geist 400 en encre, pas de mono. */
.stack-list.is-readouts { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--rule-hair); margin: 0; padding: 0; overflow: hidden; background: var(--color-rule); border: var(--rule-hair) solid var(--color-rule); border-radius: var(--radius-card); }
.stack-list.is-readouts .stack-tag { display: flex; align-items: center; min-height: 48px; padding: var(--space-sm) var(--space-md); border: 0; border-radius: 0; background: var(--color-paper); font: 400 var(--text-sm)/1.4 var(--font-body); color: var(--color-ink); }
.about-stack .launch-body > p:first-child { margin-bottom: var(--space-md); }
.about-stack .launch-body > .stack-list + p { margin-top: var(--space-lg); }
@media (min-width: 60.0625rem) {
    .wrap.is-split.about-stack { grid-template-rows: auto 1fr auto; row-gap: 0; }
    .wrap.is-split.about-stack > .section-head { grid-column: 1; grid-row: 1; margin-bottom: var(--space-lg); }
    .about-stack > .launch-body { display: contents; }
    .about-stack .launch-body > p:first-child { grid-column: 1; grid-row: 2; align-self: end; margin: 0; }
    .about-stack .launch-body > p:last-child { grid-column: 2; grid-row: 1 / 3; align-self: start; margin: 0; }
    .about-stack .launch-body > .stack-list { grid-column: 1 / -1; grid-row: 3; margin-top: var(--space-lg); grid-template-columns: repeat(9, minmax(0, 1fr)); }
    .about-stack .stack-list.is-readouts .stack-tag { min-height: 64px; padding-inline: clamp(var(--space-xs), 1vw, var(--space-md)); text-wrap: balance; }
}
@media (max-width: 40rem) {
    .stack-list.is-readouts { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .stack-list.is-readouts .stack-tag:last-child { grid-column: 1 / -1; }
}

/* ---------- À propos, puits des prix : les étiquettes en muted ---------- */
.about-note-lead, .about-rate-txt { color: var(--color-muted); }

/* ---------- Ressources : rangées à filet comme /guides, puits gardés pour les outils officiels ---------- */
/* Titre sur 5 colonnes, ce que la source apporte sur 5, le moment de la consulter en marge sur 2. */
/* Pas de filet de clôture : la rubrique suivante ouvre sur le sien (un seul trait entre deux rubriques). */
.res-grid.is-rows { display: block; }
.res-grid.is-rows .res-item { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-sm) var(--gap-columns); padding: var(--space-lg) 0; background: none; border: 0; border-top: var(--rule-hair) solid var(--color-rule); border-radius: 0; }
.res-grid.is-rows .res-item:first-child { border-top-color: var(--color-rule-2); }
.res-grid.is-rows .res-item .res-when { margin: 0; padding: 0; border: 0; }
.res-grid.is-tools { grid-template-columns: repeat(3, minmax(0, 1fr)); }
@media (min-width: 60.0625rem) {
    .res-grid.is-rows .res-item { grid-template-columns: repeat(12, minmax(0, 1fr)); align-items: baseline; }
    .res-grid.is-rows .res-item h3 { grid-column: 1 / span 5; }
    .res-grid.is-rows .res-item p { grid-column: 6 / span 5; }
    .res-grid.is-rows .res-item .res-when { grid-column: 11 / -1; }
}
@media (max-width: 60rem) { .res-grid.is-tools { grid-template-columns: minmax(0, 1fr); } }

/* ---------- Catégories de guides : rangées à filet comme /guides, prose collante ---------- */
/* Les cartes encadrées deviennent des rangées ouvertes (date, titre, durée ; l'extrait sous le titre) ; la prose de la rubrique accompagne la liste. */
.cat-main .guide-cards.is-index { background: none; border: 0; border-bottom: var(--rule-hair) solid var(--color-rule); border-radius: 0; overflow: visible; }
.cat-main .guide-cards.is-index .guide-card { grid-template-columns: 6rem minmax(0, 1fr) 3.5rem; grid-template-areas: "date title dur" ". text ."; padding: var(--space-md); }
.cat-main .guide-cards.is-index .guide-card:first-child { border-top: var(--rule-hair) solid var(--color-rule-2); }
.cat-main .guide-cards.is-index .guide-card :is(h2, h3) { font-size: var(--text-lg); line-height: 1.15; }
.cat-main .guide-cards.is-index .guide-card:first-child :is(h2, h3) { font-size: var(--text-xl); line-height: 1.1; }
.cat-main .guide-cards.is-index .guide-card-foot > time { justify-self: start; }
.cat-main .guide-cards.is-index .guide-card:hover { background: var(--color-paper-2); }
@media (min-width: 60.0625rem) {
    /* Collée par le bas : la prose se lit entière à côté du début de la liste, puis reste au bas de l'écran pendant que la liste défile. */
    .cat-layout > .cat-body { position: sticky; bottom: var(--space-xl); align-self: end; }
}
@media (max-width: 40rem) {
    .cat-main .guide-cards.is-index .guide-card { grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "date dur" "title title" "text text"; padding-inline: 0; }
}

/* ---------- Guides : un seul filet entre le bandeau et « à retenir » ---------- */
/* Le filet du pied du bandeau cède la place à ceux de « à retenir » et du premier intertitre, posés sur la même ligne. */
.page-hero.article-hero:has(+ .article-section .article-rail > .takeaways:first-child) { border-bottom: 0; }

/* ---------- Navigation de guide seule : la rangée entière, étiquette en marge et titre à gauche ---------- */
:is(.article-annex, .glo-foot) .guide-nav.is-single a { display: grid; grid-template-columns: minmax(0, 1fr); align-items: baseline; text-align: left; }
@media (min-width: 60.0625rem) {
    :is(.article-annex, .glo-foot) .guide-nav.is-single a { grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: var(--gap-columns); }
    :is(.article-annex, .glo-foot) .guide-nav.is-single .gn-label { grid-column: 1 / span 3; }
    :is(.article-annex, .glo-foot) .guide-nav.is-single .gn-title { grid-column: 4 / -1; font-size: var(--text-2xl); }
}
/* p13b fin */

/* p13a début */
/* ---------- Premier écran de la famille WordPress (.is-ledger) : le titre un cran au-dessus du display, sur huit
   colonnes, le chapô en tête de titre à droite, puis la fiche d'offre en rangée sur toute la largeur, juste sous le
   titre : le prix à gauche, les garanties sur deux colonnes, le bouton et la note à droite. La hauteur suit le contenu,
   pour que la console ou le relevé de la page entre dans le pli. Les variantes (bloc p14a) déplacent le chapô ou le
   prix. Sous 60 rem, la pile habituelle (prix et bouton sous le chapô). ---------- */
@media (min-width: 60.0625rem) {
    .service-hero.is-ledger { padding: var(--space-xl) 0; }
    .service-hero.is-ledger .service-hero-grid { grid-template-columns: repeat(12, minmax(0, 1fr)); gap: var(--space-xl) var(--gap-columns); align-items: end; }
    .service-hero.is-ledger .service-hero-grid > div { display: grid; grid-column: 1 / -1; grid-template-columns: subgrid; align-items: end; }
    .service-hero.is-ledger h1 { grid-column: 1 / span 8; grid-row: 1 / span 2; max-width: none; margin: 0; font-size: min(6.5rem, 7.2vw); text-wrap: balance; }
    .service-hero.is-ledger .lead { grid-column: 9 / -1; grid-row: 1; margin: 0; font-size: var(--text-lg); line-height: 1.5; }
    .service-hero.is-ledger .service-see-also { grid-column: 9 / -1; grid-row: 2; margin: var(--space-sm) 0 0; }
    .service-hero.is-ledger .offer-box { display: grid; grid-column: 1 / -1; grid-template-columns: subgrid; grid-template-rows: auto 1fr; align-items: start; padding: 0 var(--space-xl) 0 0; }
    .service-hero.is-ledger .offer-figure {
        grid-column: 1 / span 3; grid-row: 1 / -1; align-self: stretch; margin: 0; padding: var(--space-lg) var(--space-xl);
        border-bottom: 0; border-right: var(--rule-hair) solid var(--color-rule); border-radius: var(--radius-card) 0 0 var(--radius-card);
    }
    .service-hero.is-ledger .offer-figure .price-amount { margin-top: var(--space-sm); }
    .service-hero.is-ledger .offer-box ul { display: grid; grid-column: 4 / span 6; grid-row: 1 / -1; grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: var(--gap-columns); margin: 0; padding: var(--space-md) 0; }
    .service-hero.is-ledger .offer-box li:nth-last-child(-n + 2) { border-bottom: 0; }
    .service-hero.is-ledger .offer-box > .btn { grid-column: 10 / -1; grid-row: 1; margin-top: var(--space-lg); }
    .service-hero.is-ledger .offer-box > .pricing-note { grid-column: 10 / -1; grid-row: 2; margin: var(--space-sm) 0 var(--space-lg); }
}

/* ---------- Console des symptômes (.is-console : dépannage WordPress, lenteur, piratage) : en rangée scindée, comme
   la méthode, la tête sur quatre colonnes et le puits sur sept, à partir de la sixième ; une ligne par symptôme, numérotée en mono atténué dans une gouttière tramée sous filet ; le code ou le message réel en mono,
   sans pastille. La trame et le filet restent dans la gouttière des numéros, jamais sous le texte. ---------- */
.service-symptoms.is-console { --gutter-num: 96px; }
.service-symptoms.is-console .section-head { margin-bottom: var(--space-xl); }
@media (min-width: 60.0625rem) {
    .service-symptoms.is-console .wrap { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: var(--gap-columns); align-items: start; }
    .service-symptoms.is-console .section-head { grid-column: 1 / span 4; margin: 0; }
    .service-symptoms.is-console .symptoms { grid-column: 6 / -1; }
}
.service-symptoms.is-console .symptoms {
    display: block; counter-reset: line; padding: var(--space-lg) 0; border: var(--rule-hair) solid var(--color-rule); border-radius: var(--radius-card);
    background-color: var(--color-paper-2);
    background-image: linear-gradient(90deg, transparent calc(var(--gutter-num) - 1px), var(--color-rule-2) calc(var(--gutter-num) - 1px), var(--color-rule-2) var(--gutter-num), var(--color-paper-2) var(--gutter-num)),
        linear-gradient(var(--rule-blueprint) 1px, transparent 1px), linear-gradient(90deg, var(--rule-blueprint) 1px, transparent 1px);
    background-size: 100% 100%, 48px 48px, 48px 48px; background-position: 0 0, -1px -1px, -1px -1px;
}
.service-symptoms.is-console .symptoms li { padding: var(--space-sm) var(--space-xl) var(--space-sm) calc(var(--gutter-num) + var(--space-lg)); border: 0; font-size: var(--text-lg); line-height: 1.5; }
.service-symptoms.is-console .symptoms li::before {
    content: counter(line, decimal-leading-zero) / ""; counter-increment: line; inset: 0 auto 0 0; width: var(--gutter-num); height: auto;
    padding: var(--space-sm) var(--space-lg) 0 0; border: 0; border-radius: 0;
    font: 400 var(--text-xs)/calc(1.5 * var(--text-lg)) var(--font-outlier); color: var(--color-muted); text-align: right;
}
.service-symptoms.is-console samp { white-space: nowrap; font: 400 0.8em/1.3 var(--font-outlier); letter-spacing: 0; color: var(--color-ink); font-variant-numeric: tabular-nums; }
@media (max-width: 40rem) {
    .service-symptoms.is-console { --gutter-num: 48px; }
    .service-symptoms.is-console .symptoms { padding: var(--space-md) 0; }
    .service-symptoms.is-console .symptoms li { padding: var(--space-xs) var(--space-md) var(--space-xs) calc(var(--gutter-num) + var(--space-md)); font-size: var(--text-md); }
    .service-symptoms.is-console .symptoms li::before { padding: var(--space-xs) var(--space-sm) 0 0; line-height: calc(1.5 * var(--text-md)); }
    .service-symptoms.is-console samp.is-long { white-space: normal; }
}
@media (max-width: 22rem) {
    .service-symptoms.is-console samp { white-space: normal; overflow-wrap: anywhere; }
}

/* ---------- Schéma à deux voies (automatisation) : la voie à la main en haut, un filet en tirets en encre seconde,
   du premier anneau au dernier, dans le puits ; la voie automatisée en bas, les nœuds à filet laiton reliés par un
   filet droit, qui s'arrête au dernier ; un tiret vertical descend de chaque anneau à son nœud. Sous 60 rem, la voie
   court d'un anneau au suivant, sans dépasser le dernier. ---------- */
.service-method.is-diagram { --band: 144px; --lane: 40px; --rail: 104px; }
.service-method.is-diagram .steps::after {
    content: ""; position: absolute; z-index: 0; grid-row: auto; top: var(--lane); bottom: auto; left: calc(var(--space-xl) + var(--node) / 2);
    right: calc(var(--space-xl) + (100% - 2 * var(--space-xl) - 3 * var(--gap-columns)) / 4 - var(--node) / 2);
    width: auto; height: 0; background: none; border-top: var(--rule-hair) dashed var(--color-ink-2);
}
.service-method.is-diagram .steps li::before { z-index: 1; top: calc(var(--rail) - var(--band) - var(--node) / 2); }
.service-method.is-diagram .steps li:not(:last-child) h3::before { top: calc(var(--rail) - var(--band)); }
.service-method.is-diagram .steps li:nth-child(n)::after {
    content: ""; position: absolute; z-index: 1; top: calc(var(--lane) - var(--band) - 4px); left: calc(var(--node) / 2 - 4px);
    width: 9px; height: 9px; box-sizing: border-box; border: var(--rule-hair) solid var(--color-ink-2); border-radius: 50%; background: var(--color-paper-2);
}
.service-method.is-diagram .steps h3::after {
    content: ""; position: absolute; z-index: 0; top: calc(var(--lane) - var(--band) + 5px); left: calc(var(--node) / 2);
    height: calc(var(--rail) - var(--lane) - var(--node) / 2 - 5px); border-left: var(--rule-hair) dashed var(--color-ink-2);
}
@media (max-width: 60rem) {
    .service-method.is-diagram .steps { padding-left: calc(var(--space-lg) + 32px); }
    .service-method.is-diagram .steps::after { content: none; }
    .service-method.is-diagram .steps li:not(:last-child) p::before {
        content: ""; position: absolute; left: -32px; top: calc(var(--node) / 2 + 5px); height: calc(100% + var(--space-xl) - 9px);
        border-left: var(--rule-hair) dashed var(--color-ink-2);
    }
    .service-method.is-diagram .steps li:not(:last-child) h3::before { top: calc(var(--node) / 2); }
    .service-method.is-diagram .steps li:nth-child(n)::after { top: calc(var(--node) / 2 - 4px); left: -36px; border-radius: 50%; border: var(--rule-hair) solid var(--color-ink-2); width: 9px; height: 9px; }
    .service-method.is-diagram .steps h3::after { top: calc(var(--node) / 2); left: -27px; width: 27px; height: 0; border-left: 0; border-top: var(--rule-hair) dashed var(--color-ink-2); }
}

/* ---------- Bas de page sans cas réel (.service-close.is-open) : la FAQ ouverte, question et réponse en vis-à-vis
   sous filet, puis les guides en rangée de trois colonnes, chacune ouverte par son filet. ---------- */
.faq-open { margin: 0; }
.faq-open > div { padding: var(--space-lg) 0; border-bottom: var(--rule-hair) solid var(--color-rule); }
.faq-open dt { font-size: var(--text-lg); font-weight: 500; line-height: 1.35; color: var(--color-ink); }
.faq-open dd { margin: var(--space-sm) 0 0; max-width: 68ch; color: var(--color-ink-2); }
@media (min-width: 60.0625rem) {
    .service-close.is-open .service-close-grid > .close-faq,
    .service-close.is-open .service-close-grid > .close-guides { display: grid; grid-column: 1 / -1; grid-template-columns: subgrid; }
    .service-close.is-open .service-close-grid > div > .section-head { grid-column: 1 / -1; margin-bottom: var(--space-xl); }
    .service-close.is-open .service-close-grid > div > .faq-open { display: grid; grid-column: 1 / -1; grid-template-columns: subgrid; }
    .faq-open > div { display: grid; grid-column: 1 / -1; grid-template-columns: subgrid; align-items: baseline; }
    .faq-open dt { grid-column: 1 / span 5; }
    .faq-open dd { grid-column: 7 / -1; margin: 0; }
    .service-close.is-open .service-close-grid > div > .guide-links { grid-column: 1 / -1; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 0 var(--gap-columns); border-top: 0; }
    .service-close.is-open .close-guides .guide-link { justify-content: flex-start; padding: var(--space-md) 0 0; border-bottom: 0; border-top: var(--rule-hair) solid var(--color-rule-2); }
}

/* ---------- L'écran de clôture, composition de la famille WordPress : les autres services à gauche, l'appel en
   seconde colonne (ordre visuel = ordre du DOM, la tabulation va de gauche à droite), les services de la même famille
   en encre et le reste atténué. La colonne « services » du pied répète encore
   six de ces liens un écran plus bas : la grille d'ici les range par famille, le pied reste le plan du site. Les autres
   familles prennent la composition empilée (.is-stacked, bloc p14a). Ordre du DOM inchangé (les services, puis
   l'appel) ; sous 60 rem, la pile dans cet ordre. ---------- */
@media (min-width: 60.0625rem) {
    .service-end:not(.is-stacked) {
        display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: var(--gap-columns); align-items: start;
        box-sizing: border-box; max-width: var(--container); margin-inline: auto; padding: var(--section-gap-s) var(--gutter);
    }
    .service-end:not(.is-stacked) > .section { padding: 0; }
    .service-end:not(.is-stacked) > .section > .wrap { max-width: none; padding: 0; }
    .service-end:not(.is-stacked) > .service-other { grid-column: 1 / span 5; grid-row: 1; }
    .service-end:not(.is-stacked) > .section:not(.service-other) { grid-column: 7 / -1; grid-row: 1; }
    .service-end:not(.is-stacked) .cta-band { display: block; padding-top: 0; border-top: 0; }
    .service-end:not(.is-stacked) .cta-band > div:first-child { display: block; }
    .service-end:not(.is-stacked) .cta-band h2 { max-width: 14ch; font-size: var(--text-display); line-height: 0.95; }
    .service-end:not(.is-stacked) .cta-band > div:first-child > p { margin-top: var(--space-lg); }
    .service-end:not(.is-stacked) .cta-band > div:first-child > .cta-band-actions { margin-top: var(--space-xl); }
    .service-end:not(.is-stacked) .service-other .section-head { margin-bottom: var(--space-lg); }
    .service-end:not(.is-stacked) .link-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .service-end:not(.is-stacked) .link-grid a { min-height: 52px; font-size: var(--text-md); }
}
.service-end .link-grid li:not(.is-near) a { color: var(--color-muted); }
.service-end .link-grid li:not(.is-near) a:hover { color: var(--color-ink); }
.service-end .link-grid li.is-near a { color: var(--color-ink); }

/* ---------- Sécurité PHP : « vérifier vous-même » en puits, la tête à gauche, chaque vérification sur sa ligne,
   numérotée en mono atténué dans une gouttière tramée (comme la console des symptômes), les commandes en relevés
   mono (encre pleine, sans fond) ; le premier paragraphe de « ce qui s'est passé » un cran plus grand, en encre, pour
   ne plus enchaîner trois parties au même petit corps. ---------- */
.service-dossier .dossier-part:first-child .prose-body > p:first-child { font-size: var(--text-lg); line-height: 1.5; color: var(--color-ink); }
.service-dossier .dossier-part.is-check {
    --gutter-num: 48px; position: relative; isolation: isolate; padding-block: var(--space-xl);
    padding-inline: calc(var(--gutter) + var(--space-xl));
}
.service-dossier .dossier-part.is-check::before {
    content: ""; position: absolute; z-index: -1; inset: 0 var(--gutter);
    background: var(--color-paper-2); border: var(--rule-hair) solid var(--color-rule); border-radius: var(--radius-card);
}
.service-dossier .dossier-part + .dossier-part.is-check { padding-top: var(--space-xl); border-top: 0; }
.service-dossier .dossier-part.is-check .service-list {
    display: block; margin: 0; border-top: 0; counter-reset: check;
    background-image: linear-gradient(90deg, transparent calc(var(--gutter-num) - 1px), var(--color-rule-2) calc(var(--gutter-num) - 1px), var(--color-rule-2) var(--gutter-num), var(--color-paper-2) var(--gutter-num)),
        linear-gradient(var(--rule-blueprint) 1px, transparent 1px), linear-gradient(90deg, var(--rule-blueprint) 1px, transparent 1px);
    background-size: 100% 100%, 48px 48px, 48px 48px; background-position: 0 0, -1px -1px, -1px -1px;
}
.service-dossier .dossier-part.is-check .service-list li { position: relative; padding: var(--space-md) 0 var(--space-md) calc(var(--gutter-num) + var(--space-lg)); }
.service-dossier .dossier-part.is-check .service-list li:last-child { border-bottom: 0; }
.service-dossier .dossier-part.is-check .service-list li::before {
    content: counter(check, decimal-leading-zero) / ""; counter-increment: check; position: absolute; left: 0; top: var(--space-md);
    width: var(--gutter-num); padding-right: var(--space-sm); box-sizing: border-box; text-align: right;
    font: 400 var(--text-xs)/1.7 var(--font-outlier); color: var(--color-muted);
}
.service-dossier .dossier-part.is-check code { padding: 0; border-radius: 0; background: none; font-size: 0.88em; color: var(--color-ink); }
@media (max-width: 40rem) {
    .service-dossier .dossier-part.is-check { padding-inline: calc(var(--gutter) + var(--space-md)); }
}
/* p13a fin */

/* p14b début */
/* Un seul filet entre deux rubriques : la liste qui précède une rubrique ne se ferme pas, la rubrique ouvre sur son filet. */
.page-content.res-doc .res-toc a:last-child { border-bottom: 0; }
.tools-grid.about-index:has(+ .about-contact) { border-bottom: 0; }

/* Auteur, fin de page : « travailler avec moi » et « me contacter » dans une seule bande, deux colonnes sous filet
   comme le périmètre éditorial juste au-dessus ; le bouton sous la seconde. Le pied ouvre sur son propre filet. */
.section-ink.author-end { border-bottom: 0; }
.author-end-cols { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-2xl) var(--gap-columns); align-items: start; }
.author-end-col { min-width: 0; padding-top: var(--space-lg); border-top: var(--rule-hair) solid var(--color-rule-2); }
.author-end-col > .wrap { display: block; max-width: none; margin: 0; padding: 0; }
.author-end-col :is(.section-head, .launch-body, .cta-band, .cta-band > div:first-child) { display: block; margin: 0; padding: 0; border: 0; }
.author-end-col h2 { margin: 0 0 var(--space-lg); max-width: 18ch; font-size: var(--text-display-s); line-height: 0.98; letter-spacing: var(--tracking-display); }
.author-end-col p { margin: 0; max-width: var(--measure); font-size: var(--text-lead); line-height: 1.5; color: var(--color-ink-2); }
.author-end-col .cta-band > div:first-child > .cta-band-actions { margin-top: var(--space-xl); }
@media (max-width: 60rem) { .author-end-cols { grid-template-columns: minmax(0, 1fr); } }

/* Ressources, « comment nous utilisons ces sources » : la tête et son annonce à gauche, les trois règles en rangées
   à filet à droite, la note de bas en bas à gauche. Les trois puits des outils restent le seul trio de la page. */
.page-content.is-doc.res-doc > .res-method { display: grid; grid-template-columns: minmax(0, 1fr); margin: var(--space-3xl) 0 var(--space-xl); padding-top: var(--space-lg); border-top: var(--rule-hair) solid var(--color-rule-2); }
.page-content.res-doc .res-method h2 { position: static; max-width: none; margin: 0; font-size: var(--text-section); line-height: 0.98; text-transform: lowercase; text-wrap: balance; scroll-margin-top: calc(var(--header-h) + var(--space-lg)); }
.page-content.res-doc .res-method-head > p { margin: var(--space-lg) 0 0; max-width: var(--measure); }
.page-content.res-doc .res-method ol { margin: var(--space-xl) 0 0; padding: 0; list-style: none; }
.page-content.res-doc .res-method li { margin: 0; padding-block: var(--space-lg); border-top: var(--rule-hair) solid var(--color-rule); color: var(--color-ink-2); }
.page-content.res-doc .res-method li:first-child { border-top-color: var(--color-rule-2); }
.page-content.res-doc .res-method li strong { display: block; margin-bottom: var(--space-xs); font-weight: 500; font-size: var(--text-lg); line-height: 1.3; color: var(--color-ink); }
.page-content.res-doc .res-method-note { margin: var(--space-lg) 0 0; max-width: var(--measure); color: var(--color-ink-2); }
@media (min-width: 60.0625rem) {
    .page-content.is-doc.res-doc > .res-method { grid-template-columns: repeat(12, minmax(0, 1fr)); grid-template-rows: auto 1fr; column-gap: var(--gap-columns); }
    .res-method > .res-method-head { grid-column: 1 / span 5; grid-row: 1; }
    .page-content.res-doc .res-method ol { grid-column: 7 / -1; grid-row: 1 / -1; margin: 0; }
    .page-content.res-doc .res-method li:first-child { padding-top: 0; border-top: 0; }
    .page-content.res-doc .res-method li:last-child { padding-bottom: 0; }
    .page-content.res-doc .res-method-note { grid-column: 1 / span 5; grid-row: 2; align-self: end; }
}
@media (max-width: 40rem) { .page-content.is-doc.res-doc > .res-method { margin-top: var(--space-2xl); } }
/* p14b fin */

/* p14a début */
/* ---------- Premier écran WordPress, les variantes de la rangée (vue : $heroVariant) : cinq pages, cinq rangées.
   Le chapô au pied du titre (.is-lead-low : piratage, lenteur), sous le titre (.is-lead-under : migration, le titre
   sur douze colonnes en deux lignes, le lien voisin à droite du chapô), le prix en fin de fiche, le bouton et la note
   en tête (.is-price-end : piratage, SEO WordPress). Sous 60 rem, la pile habituelle. ---------- */
@media (min-width: 60.0625rem) {
    .service-hero.is-lead-low .lead { grid-row: 2; align-self: end; }
    .service-hero.is-lead-under h1 { grid-column: 1 / -1; grid-row: 1; }
    .service-hero.is-lead-under .lead { grid-column: 1 / span 7; grid-row: 2; margin-top: var(--space-lg); }
    .service-hero.is-price-end .offer-box { padding: 0 0 0 var(--space-xl); }
    .service-hero.is-price-end .offer-figure {
        grid-column: 10 / -1; border-right: 0; border-left: var(--rule-hair) solid var(--color-rule);
        border-radius: 0 var(--radius-card) var(--radius-card) 0;
    }
    .service-hero.is-price-end .offer-box > .btn, .service-hero.is-price-end .offer-box > .pricing-note { grid-column: 1 / span 3; }
}

/* ---------- Symptômes en cases (.is-cases : automatisation ; sécurité PHP en 3 × 2, bloc p16a) : la tête en première
   case, une case par tâche, numérotée en Geist tabulaire atténué, comme les cases de la méthode ; la fréquence en encre pleine. Huit cases sur quatre
   colonnes ; la liste, en sous-grille, couvre aussi la case de la tête, qui passe donc au premier plan. Deux colonnes
   sous 60 rem, une sous 40 rem. ---------- */
.service-symptoms.is-cases .symptoms { counter-reset: sym; gap: var(--gap-columns); border-top: 0; }
.service-symptoms.is-cases .symptoms li {
    counter-increment: sym; padding: var(--space-lg); background: var(--color-paper-2);
    border: var(--rule-hair) solid var(--color-rule-2); border-radius: var(--radius-card); font-size: var(--text-lg); line-height: 1.45;
}
.service-symptoms:is(.is-cases, .is-ledger) .symptoms li::before {
    content: counter(sym, decimal-leading-zero) / ""; position: static; display: block; width: auto; height: auto;
    margin-bottom: var(--space-sm); border: 0; border-radius: 0;
    font: 400 var(--text-xs)/1.5 var(--font-body); letter-spacing: 0; color: var(--color-muted); font-variant-numeric: tabular-nums;
}
.service-symptoms:is(.is-cases, .is-ledger) .symptoms li:last-child:nth-child(odd) { grid-column: auto; }
@media (min-width: 60.0625rem) {
    .service-symptoms.is-cases .wrap { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); column-gap: var(--gap-columns); }
    .service-symptoms.is-cases .section-head { position: relative; z-index: 1; grid-column: 1; grid-row: 1; margin: 0; padding-top: var(--space-lg); }
    .service-symptoms.is-cases .symptoms { grid-column: 1 / -1; grid-row: 1 / span 2; grid-template-columns: subgrid; grid-template-rows: subgrid; }
    .service-symptoms.is-cases .symptoms li:first-child { grid-column-start: 2; }
}
@media (max-width: 60rem) {
    .service-symptoms.is-cases .symptoms { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 40rem) {
    .service-symptoms.is-cases .symptoms { grid-template-columns: minmax(0, 1fr); gap: var(--space-md); }
    .service-symptoms.is-cases .symptoms li { padding: var(--space-md); font-size: var(--text-md); }
}

/* ---------- Symptômes en rangée de grand livre (.is-ledger : migration) : une colonne par symptôme entre deux filets,
   séparées par un filet, numérotées en Geist tabulaire atténué, comme la fiche du premier écran ; les versions en mono, sans
   pastille. Deux colonnes sous 60 rem, une sous 40 rem, chaque symptôme sous son filet. ---------- */
.service-symptoms.is-ledger .symptoms { counter-reset: sym; border-top: var(--rule-hair) solid var(--color-rule); }
.service-symptoms.is-ledger .symptoms li { counter-increment: sym; padding: var(--space-lg) 0 var(--space-xl); border: 0; border-bottom: var(--rule-hair) solid var(--color-rule); }
.service-symptoms:is(.is-cases, .is-ledger) samp { white-space: nowrap; font: 400 0.8em/1.3 var(--font-outlier); letter-spacing: 0; color: var(--color-ink); font-variant-numeric: tabular-nums; }
@media (min-width: 60.0625rem) {
    .service-symptoms.is-ledger .symptoms { grid-template-columns: none; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); column-gap: 0; border-bottom: var(--rule-hair) solid var(--color-rule); }
    .service-symptoms.is-ledger .symptoms li { padding: var(--space-lg) var(--space-lg) var(--space-xl); border-bottom: 0; font-size: var(--text-lg); line-height: 1.45; }
    .service-symptoms.is-ledger .symptoms li:first-child { padding-left: 0; }
    .service-symptoms.is-ledger .symptoms li + li { border-left: var(--rule-hair) solid var(--color-rule); }
}
@media (min-width: 40.0625rem) and (max-width: 60rem) {
    .service-symptoms.is-ledger .symptoms { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 40rem) {
    .service-symptoms.is-ledger .symptoms li { padding: var(--space-md) 0 var(--space-lg); font-size: var(--text-md); }
}

/* ---------- Sous le premier écran WordPress, la rangée à la hauteur de son contenu : la section suivante monte
   d'un cran, pour que la console ou le relevé entre dans le pli. ---------- */
@media (min-width: 60.0625rem) {
    .service-hero.is-ledger + .section.service-symptoms { padding-top: var(--space-lg); }
    .service-hero.is-ledger + .service-symptoms.is-console .section-head { margin-bottom: var(--space-lg); }
    .service-hero.is-ledger + .service-symptoms.is-console .section-head h2 { margin-bottom: 0; }
}

/* ---------- L'écran de clôture, composition empilée (.is-stacked : dépannage, sur mesure, automatisation,
   référencement, serveur, sécurité PHP) : les autres services en rangée de trois colonnes sous leur tête à gauche,
   puis l'appel en clôture 6/6 sous son filet. Sous 60 rem, la pile, comme la famille WordPress. ---------- */
@media (min-width: 60.0625rem) {
    .service-end.is-stacked > .service-other { padding-bottom: 0; }
    .service-end.is-stacked > .service-other > .wrap { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: var(--gap-columns); align-items: start; }
    .service-end.is-stacked .service-other .section-head { grid-column: 1 / span 4; margin: 0; }
    .service-end.is-stacked .service-other .link-grid { grid-column: 5 / -1; grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* ---------- Méthode sur téléphone : le tracé (lenteur, référencement) et la rangée de cases (dépannage WordPress,
   serveur) gardent leurs cases, sur deux colonnes, sans le filet vertical ; le tracé décale sa seconde colonne d'un
   cran, la descente reste lisible. Sous 22 rem, une colonne. ---------- */
@media (max-width: 60rem) {
    .service-method:not(.is-diagram, .is-schedule, .is-rail, .is-vertical) .steps {
        grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: var(--gap-columns); row-gap: var(--space-xl); padding: var(--space-lg);
    }
    .service-page:has(.service-case) .service-method:not(.is-diagram, .is-schedule, .is-rail, .is-vertical) .steps { padding-inline: 0; }
    .service-method:not(.is-diagram, .is-schedule, .is-rail, .is-vertical) .steps::after { content: none; }
    .service-method:not(.is-diagram, .is-schedule, .is-rail, .is-vertical) .steps li + li { margin-top: 0; }
    .service-method:not(.is-diagram, .is-schedule, .is-rail, .is-vertical, .is-trace) .steps { row-gap: 0; }
    .service-method:not(.is-diagram, .is-schedule, .is-rail, .is-vertical, .is-trace) .steps li { display: grid; grid-row: span 2; grid-template-rows: subgrid; }
    .service-method:not(.is-diagram, .is-schedule, .is-rail, .is-vertical, .is-trace) .steps li:nth-child(n + 3) { margin-top: var(--space-xl); }
    .service-method.is-trace .steps li:nth-child(even) { margin-top: var(--space-xl); }
}
@media (max-width: 40rem) {
    .service-method:not(.is-diagram, .is-schedule, .is-rail, .is-vertical) .steps h3 { padding: var(--space-sm); font-size: var(--text-lg); }
}
@media (max-width: 22rem) {
    .service-method:not(.is-diagram, .is-schedule, .is-rail, .is-vertical) .steps { grid-template-columns: minmax(0, 1fr); }
    .service-method.is-trace .steps li:nth-child(even) { margin-top: 0; }
    .service-method:not(.is-diagram, .is-schedule, .is-rail, .is-vertical) .steps li:nth-child(n + 2) { margin-top: var(--space-xl); }
}
/* p14a fin */

/* p15b début */
/* /outils : le puits de la version PHP sur toute la largeur, puis les quatre autres outils en grille 2 × 2
   à filets en croix (ni dessus, sous le puits, ni dessous, au-dessus du pied). Chaque case garde sa tête et ses liens ;
   tête et texte sur deux rangées partagées, les liens calés en bas de case. L'ordre suit le DOM ; une colonne sous 60rem. */
@media (min-width: 60.0625rem) {
    .tools-index .tools-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .tools-index .tools-grid > .tool-row:first-child { grid-column: 1 / -1; margin-bottom: var(--space-lg); }
    .tools-index .tools-grid > .tool-row:nth-child(n + 2) { grid-row: span 2; grid-template-columns: minmax(0, 1fr); grid-template-rows: subgrid; row-gap: var(--space-lg); padding: var(--space-xl) var(--gap-columns) var(--space-2xl) var(--space-md); border-top-color: var(--color-rule); }
    .tools-index .tools-grid > .tool-row:is(:nth-child(2), :nth-child(3)) { border-top-color: transparent; }
    .tools-index .tools-grid > .tool-row:nth-child(odd):nth-child(n + 3) { padding-inline: var(--gap-columns) var(--space-md); border-left: var(--rule-hair) solid var(--color-rule); }
    .tools-index .tools-grid > .tool-row:nth-child(n + 2) .tool-row-body { display: flex; flex-direction: column; align-items: flex-start; align-self: stretch; }
    .tools-index .tools-grid > .tool-row:nth-child(n + 2) .tool-links { margin-top: auto; }
}

/* Guide choisir, schéma du bandeau au téléphone : l'arbre de décision redessiné en colonne par figure.blade.php,
   mêmes mots, remplace sous 40rem le puits qui défilait et coupait la racine ; une seule des deux variantes est
   affichée (l'autre en display: none, hors de l'arbre d'accessibilité). */
.article-figure svg.figure-tree { display: none; }
@media (max-width: 40rem) {
    .article-figure .figure-scroll:has(> .figure-tree) { padding-right: 0; mask-image: none; }
    .article-figure .figure-scroll:has(> .figure-tree) > svg:not(.figure-tree) { display: none; }
    .article-figure .figure-scroll svg.figure-tree { display: block; min-width: 0; max-width: 24rem; }
}
/* p15b fin */

/* p15a début */
/* Agences : la liste « au-delà de WordPress » part au milieu de la page (x 736 à 1440), comme le reste du contenu. */
@media (min-width: 60.0625rem) {
    .wrap.is-split.is-even { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
/* p15a fin */

/* p16a début */
/* Sécurité PHP, « vous reconnaissez votre situation ? » : les cases de l'automatisation sous une tête pleine
   largeur, trois par rangée sur deux rangées, pour rompre la suite de listes (« qui est concerné », « vérifier
   vous-même ») ; deux colonnes sous 60 rem, une sous 40 rem, comme les cases de l'automatisation. */
@media (min-width: 60.0625rem) {
    .service-symptoms.is-cases.is-three .wrap { display: block; }
    .service-symptoms.is-cases.is-three .section-head { padding-top: 0; margin-bottom: var(--space-xl); }
    .service-symptoms.is-cases.is-three .symptoms { grid-row: auto; grid-template-columns: repeat(3, minmax(0, 1fr)); grid-template-rows: none; }
    .service-symptoms.is-cases.is-three .symptoms li:first-child { grid-column-start: auto; }
}
/* p16a fin */

/* p16b début */
/* MCT, les coulisses : les deux textes en rangées de puits sur toute la largeur, comme les projets de l'accueil ;
   le titre en Instrument Serif sur huit colonnes, la précision en légende Geist à droite, calée sur sa ligne de base.
   Toute la rangée répond au survol et au focus (lien étendu). Une colonne sous 60rem. */
.project-wells { margin: var(--space-2xl) 0 0; padding: 0; list-style: none; color: var(--color-ink); background: var(--color-paper-2); border: var(--rule-hair) solid var(--color-rule); border-radius: var(--radius-card); overflow: clip; }
.project-wells li { position: relative; display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); gap: var(--space-xs) var(--gap-columns); align-items: baseline; margin: 0; padding: var(--space-xl); transition: background-color var(--dur-short) var(--ease-out); }
.project-wells li + li { border-top: var(--rule-hair) solid var(--color-rule); }
.project-wells li > a { grid-column: 1 / span 8; font-family: var(--font-display); font-size: var(--text-2xl); font-weight: var(--display-weight); line-height: 1.05; letter-spacing: var(--tracking-display); text-transform: lowercase; text-wrap: balance; color: var(--color-ink); text-decoration: none; }
.project-wells a::after { content: ""; position: absolute; inset: 0; }
/* Sans :has (Firefox avant 121), le lien garde son propre contour de focus. */
@supports selector(:has(*)) { .project-wells a:focus-visible { outline: 0; } }
.project-wells li:is(:hover, :has(a:focus-visible)) { background: var(--color-paper-3); }
.project-wells li:has(a:focus-visible) { outline: 2px solid var(--color-focus); outline-offset: -2px; }
.project-wells li:hover a { text-decoration: underline; text-decoration-thickness: var(--rule-hair); text-decoration-color: var(--color-accent); text-underline-offset: 0.18em; }
.project-note { grid-column: 10 / -1; justify-self: end; font-size: var(--text-sm); color: var(--color-muted); }
@media (max-width: 60rem) {
    .project-wells li { grid-template-columns: minmax(0, 1fr); padding: var(--space-lg); }
    .project-wells a, .project-note { grid-column: 1; justify-self: start; }
}

/* Atari : ce qui est publié et la façon de l'écrire en deux colonnes de journal entre deux filets, séparées par un
   filet vertical ; têtes et textes sur deux rangées partagées. Ni rangée scindée de plus, ni puits (celui de MCT).
   Le filet du bas ferme la section : celle des articles ne redouble pas le sien. */
.project-row + .project-pair { margin-top: var(--section-gap-s); padding-block: var(--space-xl); border-block: var(--rule-hair) solid var(--color-rule); }
.project-sec:has(> .wrap > .project-pair:last-child) { padding-bottom: 0; }
.project-sec:has(> .wrap > .project-pair:last-child) + .project-sec { border-top: 0; }
.project-pair { display: grid; grid-template-columns: minmax(0, 1fr); row-gap: var(--space-2xl); }
.project-col { display: grid; row-gap: var(--space-lg); align-content: start; }
.project-col .section-head { margin: 0; align-self: end; }
.project-col .section-head h2 { margin: 0; font-size: var(--text-display-s); line-height: 0.98; max-width: 16ch; }
@media (min-width: 60.0625rem) {
    .project-row + .project-pair { padding-block: var(--space-2xl); }
    .project-pair { grid-template-columns: repeat(2, minmax(0, 1fr)); grid-template-rows: auto auto; column-gap: 0; }
    .project-col { grid-row: span 2; grid-template-rows: subgrid; row-gap: var(--space-xl); padding-right: var(--gap-columns); }
    .project-col + .project-col { padding: 0 0 0 var(--gap-columns); border-left: var(--rule-hair) solid var(--color-rule); }
}

/* À propos, ce qui fonde mon expérience : les quatre preuves dans un puits en 2 × 2 à filets en croix, l'attaque en
   Instrument Serif au corps des projets de l'accueil, sur sa ligne (la virgule qui la suit n'est lue que par les lecteurs
   d'écran) ; « mes projets », plus bas, reste en rangées ouvertes. */
.page-hero.is-about ~ .section .about-proofs { gap: 0; margin-top: var(--space-xl); color: var(--color-ink-2); background: var(--color-paper-2); border: var(--rule-hair) solid var(--color-rule); border-radius: var(--radius-card); overflow: clip; }
.page-hero.is-about ~ .section .about-proofs li { padding: var(--space-xl); border-top: 0; }
.page-hero.is-about ~ .section .about-proofs li + li { border-top: var(--rule-hair) solid var(--color-rule); }
.page-hero.is-about ~ .section .about-proofs strong { display: block; margin-bottom: var(--space-xs); font-size: var(--text-2xl); line-height: 1.02; }
@media (min-width: 40.0625rem) {
    .page-hero.is-about ~ .section .about-proofs li:nth-child(2) { border-top: 0; }
    .page-hero.is-about ~ .section .about-proofs li:nth-child(even) { border-left: var(--rule-hair) solid var(--color-rule); }
}
@media (max-width: 40rem) {
    .page-hero.is-about ~ .section .about-proofs li { padding: var(--space-lg); }
    .page-hero.is-about ~ .section .about-proofs strong { font-size: var(--text-xl); }
}

/* Accueil, pli : la méta resserrée (marge, filet, interligne) et la rangée des engagements montée de 16 px font tenir
   la méta entière à 1280 × 800 et la première ligne des engagements à 1440 × 900 ; titre, phrase, bouton et console
   gardent leur composition (seuls des espacements bougent). */
@media (min-width: 60.0625rem) {
    .hero-news { margin-bottom: var(--space-xl); }
    .hero-facts { margin-top: var(--space-md); padding-top: var(--space-sm); gap: var(--space-3xs); line-height: 1.4; }
}
@media (min-width: 75.0625rem) {
    .pledges li { padding-top: var(--space-lg); }
}
/* p16b fin */


/* p18 début */
/* 404 : les trois issues en rangées à filet dans un puits, colonne 2 (même matière que le panneau « ensuite » des pages merci). */
.gate-panel { padding-block: var(--space-md); }
.gate-rows { margin: 0; padding: 0; list-style: none; }
.gate-rows li { margin: 0; padding: var(--space-lg) 0; border-top: var(--rule-hair) solid var(--color-rule-2); }
.gate-rows li:first-child { border-top: 0; }
.gate-rows a:not(.btn) { display: flex; align-items: center; min-height: 48px; padding: 0 var(--space-lg); font-size: var(--text-lg); font-weight: 500; line-height: 1.2; color: var(--color-ink); text-transform: lowercase; text-decoration: none; border-radius: var(--radius-pill); transition: background-color var(--dur-micro) var(--ease-out), box-shadow var(--dur-micro) var(--ease-out); }
.gate-rows a:not(.btn):hover { background: var(--color-paper-3); box-shadow: inset 0 0 0 var(--rule-hair) var(--color-rule-2); }
.gate-rows .btn { font-size: var(--text-lg); }
/* /paiement : le virement dans un puits, les conditions en rangées à filet à côté (même matière que les deux puits de /contact). */
.author-scope.is-settle { align-items: stretch; }
.is-settle .author-scope-col:first-child { display: flex; flex-direction: column; gap: var(--space-lg); padding: var(--space-xl); color: var(--color-ink); background: var(--color-paper-2); border: var(--rule-hair) solid var(--color-rule); border-radius: var(--radius-card); }
.is-settle .author-scope-col:first-child h2 { margin: 0; font-size: var(--text-2xl); line-height: 1.05; }
/* Le texte suit son titre : poussé en bas, il laissait 100 px vides au milieu du puits à 1440. */
.is-settle .author-scope-col:first-child p { margin: 0; }
.is-settle .author-scope-col:last-child { padding: var(--space-xl) 0 0; border-top: 0; }
.is-settle .author-scope-col:last-child h2 { font-size: var(--text-2xl); line-height: 1.05; margin-bottom: var(--space-lg); }
.is-settle .about-links { border-top: var(--rule-hair) solid var(--color-rule-2); }
.is-settle .about-links li { padding: var(--space-md) 0; border-bottom-color: var(--color-rule-2); }
@media (max-width: 60rem) {
    .is-settle .author-scope-col:first-child { padding: var(--space-lg); }
    .is-settle .author-scope-col:last-child { padding-top: 0; }
}
/* p18 fin */

/* lap18 début : écrans portables étroits (961 à 1280 px) relevés par le contrôle à 1024 et 1180 */
/* Fiche des pages de service en grand livre : le bouton passe de trois à quatre colonnes, la liste de six à cinq ; sur trois, « décrire mon problème » débordait de sa pastille. */
@media (min-width: 60.0625rem) and (max-width: 80rem) {
    .service-hero.is-ledger .offer-box ul { grid-column: 4 / span 5; }
    .service-hero.is-ledger .offer-box > :is(.btn, .pricing-note) { grid-column: 9 / -1; }
    .service-hero.is-ledger.is-price-end .offer-box ul { grid-column: 5 / span 5; }
    .service-hero.is-ledger.is-price-end .offer-box > :is(.btn, .pricing-note) { grid-column: 1 / span 4; }
    /* Autres pages de service : la fiche passe à la moitié de la largeur, chaque formule tient sur deux lignes au lieu de trois ;
       à 1024 × 768, la fiche de /securite-php poussait son bouton sous le pli. */
    .service-hero:not(.is-ledger) .service-hero-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .service-hero:not(.is-ledger) h1 { font-size: var(--text-display-s); }
    .service-hero:not(.is-ledger) { padding-top: var(--space-xl); }
    .service-hero:not(.is-ledger) .offer-box { padding: var(--space-lg) var(--space-xl); }
    .service-hero:not(.is-ledger) .offer-box li { padding-block: var(--space-xs); }
    .service-hero:not(.is-ledger) .offer-box li::before { top: calc(var(--space-xs) + 0.45em); }
}
/* Index des services de l'accueil : la dernière piste prend la largeur de son libellé, qui mordait sur le paragraphe voisin. */
@media (min-width: 60.0625rem) and (max-width: 89.9375rem) {
    .service-row { grid-template-columns: minmax(0, 3fr) minmax(0, 4fr) minmax(0, 4fr) max-content; }
}
/* lap18 fin */

/* tz19 début : texte agrandi à 200 % au téléphone (RGAA 10.4, WCAG 1.4.4). La requête est en rem : 18rem vaut 576 px
   quand la police par défaut passe à 32 px (téléphone de 320 à 576 px), mais 288 px à 16 px, donc le rendu normal ne bouge pas. */
@media (max-width: 18rem) {
    /* Mots longs (adresses, noms de domaine, termes techniques) : coupables partout plutôt que de sortir de l'écran ;
       les tableaux gardent leur largeur et défilent dans leur cadre. */
    body, :is(h1, h2, h3, h4) { overflow-wrap: anywhere; }
    table { overflow-wrap: normal; }
    /* Pied : les liens passent sur une colonne, « Dépannage » ne tenait plus dans une demi-colonne. */
    .footer-col:not(.footer-brand) { grid-template-columns: minmax(0, 1fr); }
    /* Autres services des pages de service : une colonne, les mots longs se coupent au besoin. */
    .link-grid { grid-template-columns: minmax(0, 1fr); }
    .link-grid a { overflow-wrap: anywhere; }
    /* Fiche tarifaire : le nom de la formule, le prix et l'unité s'empilent au lieu de se serrer sur deux colonnes. */
    .offer-box > .offer-figure { display: flex; flex-direction: column; align-items: flex-start; gap: var(--space-2xs); }
    /* /a-propos : le tarif et son libellé s'empilent. */
    .about-rate { grid-template-columns: minmax(0, 1fr); gap: var(--space-2xs); }
    /* /glossaire : le compteur passe au-dessus du titre, le résumé n'est plus tronqué à trois lignes. */
    .gh-card { grid-template-columns: minmax(0, 1fr); grid-template-areas: "count" "title" "text"; }
    .gh-card p { display: block; -webkit-line-clamp: none; line-clamp: none; overflow: visible; overflow-wrap: anywhere; }
    /* Numéros de CVE et adresses : coupables où il faut. */
    .nowrap { white-space: normal; }
    .guide-card h3, .nowrap, .lead a { overflow-wrap: anywhere; }
    /* Parcours en étapes : marge intérieure réduite, les mots longs se coupent. */
    .path { padding-inline: var(--space-md); }
    .path :is(li, p) { min-width: 0; overflow-wrap: anywhere; }
    /* Fil d'Ariane : le titre passe à la ligne au lieu de finir en ellipse. */
    .breadcrumb { flex-wrap: wrap; }
    .breadcrumb > span:last-child { white-space: normal; }
    /* Sommaire de /glossaire/indexation : les intitulés longs passent à la ligne. */
    .glo-toc a { white-space: normal; text-align: left; }
    /* Mentions légales : une colonne au lieu de cartes de 16rem. */
    .doc-cards { grid-template-columns: minmax(0, 1fr); }
    .doc-card { min-width: 0; overflow-wrap: anywhere; }
    /* CGV : la formule et son prix s'empilent. */
    .page-content.is-doc > .cgv-rates > li { grid-template-columns: minmax(0, 1fr); }
    .cgv-price { text-align: left; }
    /* Identifiants de code (réglage de télémétrie, directives Nginx) : coupables. */
    :is(.page-content, .article-body) code { overflow-wrap: anywhere; }
    /* /guides, guides de référence : la durée et la date passent sous la catégorie, qu'elles recouvraient. */
    .guide-ref { grid-template-columns: minmax(0, 1fr); }
    .guide-ref > .guide-ref-foot { grid-column: 1; grid-row: 2; }
    /* Cas réel des pages de service : les mots longs du chapô se coupent. */
    .service-case .case-lead { overflow-wrap: anywhere; }
    /* /site-wordpress-pirate : le numéro de CVE du relevé passe à la ligne. */
    .service-case .readout { white-space: normal; }
    /* /outils/version-php : le tableau des versions, sans cadre de défilement, coupe ses mots longs. */
    .vp-table { overflow-wrap: anywhere; }
    /* Symptômes en états (pages SEO) : les pastilles collent au texte pour tenir dans la colonne. */
    .service-symptoms.is-states samp { margin-inline: 0; }
}
/* tz19 fin */
