/* La feuille du site : une seule feuille globale, découpée en partiels. Les onze premiers suivent l'ordre exact du prototype
   (prototypes/plateforme.html). L'ordre compte : plusieurs règles de même poids se départagent par leur position. *//* Les polices, servies par le site. Ce sont les @font-face que Google Fonts sert à Chrome pour
   family=Space+Grotesk:wght@400;500;700&family=Space+Mono&display=swap, recopiés tels quels (mêmes unicode-range,
   mêmes graisses, font-display: swap) : seules les URL changent. Sous-ensembles latin et latin-ext ; le sous-ensemble
   vietnamien n'est pas repris (aucun de ses caractères n'est dans la page). Space Grotesk est une police variable :
   les trois graisses pointent vers le même fichier. Licence : src/assets/fonts/OFL.txt. */
/* latin-ext */
@font-face {
  font-family: 'Space Grotesk';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(/_astro/space-grotesk-latin-ext.D9tNdqV9.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: 'Space Grotesk';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(/_astro/space-grotesk-latin.BhU9QXUp.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* latin-ext */
@font-face {
  font-family: 'Space Grotesk';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url(/_astro/space-grotesk-latin-ext.D9tNdqV9.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: 'Space Grotesk';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url(/_astro/space-grotesk-latin.BhU9QXUp.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* latin-ext */
@font-face {
  font-family: 'Space Grotesk';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url(/_astro/space-grotesk-latin-ext.D9tNdqV9.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: 'Space Grotesk';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url(/_astro/space-grotesk-latin.BhU9QXUp.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* latin-ext */
@font-face {
  font-family: 'Space Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(/_astro/space-mono-latin-ext.DTLbW2xa.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: 'Space Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(/_astro/space-mono-latin.Rg4St2Dn.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* Plateforme : la page d'accueil retenue. Elle réunit deux dérivés de T18 · Plateforme :
   T18c (une pièce de la plateforme dans chaque section) et T18d (la même page en deux lumières).
   Deux thèmes : <html data-theme="nuit"> ou <html data-theme="jour">. Toutes les couleurs sont des tokens, celles des dessins comprises.
   De nuit, la page est celle de T18c, valeur pour valeur.

   NUIT. Contrastes sur --bg : --ink 16,0:1 · --ink-2 8,5:1 · --amber 12,2:1 · --accent 12,9:1.
   Sur --slab : --ink 14,3:1. CTA : --cta-ink sur --cta, 14,3:1.
   JOUR. La même maquette, posée sur une table lumineuse. Contrastes sur --bg : --ink 16,1:1 · --ink-2 6,8:1 ·
   --edge 6,7:1 · --accent 5,3:1 · --key 5,5:1. Sur --slab : --ink 14,2:1. CTA : --cta-ink sur --cta, 17,8:1.
   (Mesures : plateforme-contraste.mjs, sur tout le texte de la page, dans les deux thèmes.)
   L'ambre de jour (#E08A00) fait 2,4:1 sur le fond : il ne porte jamais de texte. Les liens passent au bleu d'accent,
   et le mot « Illustration » prend --key, un ambre assombri dérivé de l'ambre de la fiche.

   Rôles (les deux thèmes) : --link les liens de texte, --key l'ambre qui porte du texte (le mot-clé de la légende,
   le numéro d'un étage éclairé), --cta le fond du bouton principal (une pièce de la dalle), --cta-ink son texte, --cta-line son trait au repos (au survol
   il prend --accent, comme la flèche et le paquet qui file sous le bouton), --on-amber le texte posé sur l'ambre,
   --left-lit le fond de la pastille d'un poste éclairé (de nuit, la face gauche teintée de 16 % d'ambre ; de jour, un ambre très clair),
   --fl-lit la lumière posée sur les faces d'un étage éclairé et --fl-k sa force (1 de nuit, 4 de jour).
   Scène : --rule les filets, --slab-l et --slab-r les deux chants de la dalle, --pad le fond des emplacements,
   --hot le cœur d'un paquet, --trail sa traîne, --halo ce qui l'entoure (une lueur de nuit, une ombre de jour),
   --glow ce qui entoure la dalle (idem), --lit la teinte d'un bloc traversé, --ao l'ombre de contact au pied d'un bloc,
   --cast son ombre portée (transparente de nuit), --grid-o l'opacité du quadrillage.
   Portrait : quatre teintes lui sont propres, --po-papier l'aplat du sujet (la valeur de --right de nuit, de --top de jour),
   --po-ciel le bleu du chapeau, --po-marine celui de la chemise, --po-verre celui des verres ; le visage garde --edge.
   Cinq autres en sont tirées, par mélange dans l'espace oklab, avec la même formule dans les deux thèmes : --po-p-ciel,
   --po-p-clair et --po-p-marine teintent le papier sous le chapeau et la chemise, --po-clair est l'encre du clair de la chemise,
   --po-reflet le reflet des verres. Typées comme les autres, elles fondent avec elles au changement de thème.
   Clins d'œil du clavier (12-clins.css) : --clc-* quand on tape « claude » (corail), --clb-* quand on tape « btc » (orange).
   --clc et --clb la teinte des paquets, -halo et -lit ce qu'elle donne à --halo et --lit, -key au mot-clé de la légende,
   -top, -left, -right et -edge les faces et les arêtes du septième bloc. */
:root {
  color-scheme: dark;
  --bg-0: #0B1026; --bg: var(--bg-0); --slab: #141B3C; --top: #343F7A; --left: #283266; --right: #1E2752;
  --edge: #8EA2FF; --ink: #E9ECFB; --ink-2: #A4ADD6; --amber: #FFC857; --accent: #6EE7F9;
  --rule: #283266; --slab-l: #10163A; --slab-r: #0D1230; --pad: #10162F; --hot: #FFF1CC;
  --link: #8EA2FF; --link-line: rgba(142, 162, 255, .45); --key: #FFC857;
  --cta: #141B3C; --cta-ink: #E9ECFB; --cta-line: #343F7A; --on-amber: #0B1026;
  --glow: #8EA2FF; --halo: #FFC857; --lit: #FFC857; --trail: #FFC857; --ao: #0B1026; --cast: rgba(63, 77, 166, 0); --grid-o: .085;
  --left-lit: #4A4A64; --fl-lit: #FFC857; --fl-k: 1;
  --po-papier: #1E2752; --po-ciel: #93D0FF; --po-marine: #4D69E6; --po-verre: #2F6BFF;
  --po-p-ciel: color-mix(in oklab, var(--po-ciel) 20%, var(--po-papier)); --po-p-clair: color-mix(in oklab, var(--po-ciel) 11%, var(--po-papier));
  --po-p-marine: color-mix(in oklab, var(--po-marine) 14%, var(--po-papier)); --po-clair: color-mix(in oklab, var(--po-ciel) 55%, var(--ink));
  --po-reflet: color-mix(in oklab, var(--po-verre) 35%, #FFFFFF);
  --clc: #F08A66; --clc-halo: #F08A66; --clc-lit: #F08A66; --clc-key: #F4A083; --clc-top: #D97757; --clc-left: #B55D42; --clc-right: #8E4731; --clc-edge: #FFD3C2;
  --clb: #F7931A; --clb-halo: #F7931A; --clb-lit: #F7931A; --clb-key: #FFB04D; --clb-top: #F7931A; --clb-left: #C8750F; --clb-right: #9C5A0A; --clb-edge: #FFDDA8;
  --sans: "Space Grotesk", "Segoe UI", system-ui, -apple-system, "Helvetica Neue", Arial, sans-serif;
  --mono: "Space Mono", ui-monospace, "Cascadia Mono", "SF Mono", Consolas, "Liberation Mono", monospace;
  --gut: clamp(16px, 4vw, 48px); --maxw: 1320px;
}
:root[data-theme="jour"] {
  color-scheme: light;
  --bg-0: #F1F3FA; --slab: #E1E5F4; --top: #FFFFFF; --left: #D5DBF3; --right: #BAC3EA;
  --edge: #3F4DA6; --ink: #11162E; --ink-2: #4A5378; --amber: #E08A00; --accent: #2B4BFF;
  --rule: #CBD1EA; --slab-l: #CBD1EA; --slab-r: #B9C1E3; --pad: #D3D9EF; --hot: #FFD98A;
  --link: #3F4DA6; --link-line: rgba(63, 77, 166, .45); --key: #8F5400;
  --cta: #FFFFFF; --cta-ink: #11162E; --cta-line: #BAC3EA; --on-amber: #11162E;
  --glow: #5F6BB5; --halo: rgba(63, 77, 166, .2); --lit: rgba(224, 138, 0, .6); --trail: #D97800; --ao: rgba(63, 77, 166, 0); --cast: rgba(63, 77, 166, .24); --grid-o: .13;
  --left-lit: #F7E7CB; --fl-lit: #FFE9BD; --fl-k: 4;
  --po-papier: #FFFFFF; --po-ciel: #4A9FE3; --po-marine: #1B2A7A; --po-verre: #3D62C2;
  --po-p-ciel: color-mix(in oklab, var(--po-ciel) 20%, var(--po-papier)); --po-p-clair: color-mix(in oklab, var(--po-ciel) 11%, var(--po-papier));
  --po-p-marine: color-mix(in oklab, var(--po-marine) 14%, var(--po-papier)); --po-clair: color-mix(in oklab, var(--po-ciel) 55%, var(--ink));
  --po-reflet: color-mix(in oklab, var(--po-verre) 35%, #FFFFFF);
  --clc: #D2603A; --clc-halo: rgba(190, 80, 40, .22); --clc-lit: rgba(210, 96, 58, .6); --clc-key: #A8472A; --clc-top: #FCE6DD; --clc-left: #F3BDA9; --clc-right: #E89E85; --clc-edge: #A8472A;
  --clb: #F08000; --clb-halo: rgba(200, 110, 0, .22); --clb-lit: rgba(240, 128, 0, .6); --clb-key: #8F5400; --clb-top: #FFEBCB; --clb-left: #FACD8B; --clb-right: #F0B35A; --clb-edge: #8F5400;
}
/* Les tokens sont typés : au changement de thème, ils fondent tous ensemble depuis la racine (0,5 s).
   --bg-0 ne l'est pas : il donne tout de suite la couleur d'arrivée à la meta theme-color. */
@property --bg { syntax: "<color>"; inherits: true; initial-value: #0B1026; }
@property --slab { syntax: "<color>"; inherits: true; initial-value: #141B3C; }
@property --top { syntax: "<color>"; inherits: true; initial-value: #343F7A; }
@property --left { syntax: "<color>"; inherits: true; initial-value: #283266; }
@property --right { syntax: "<color>"; inherits: true; initial-value: #1E2752; }
@property --edge { syntax: "<color>"; inherits: true; initial-value: #8EA2FF; }
@property --ink { syntax: "<color>"; inherits: true; initial-value: #E9ECFB; }
@property --ink-2 { syntax: "<color>"; inherits: true; initial-value: #A4ADD6; }
@property --amber { syntax: "<color>"; inherits: true; initial-value: #FFC857; }
@property --accent { syntax: "<color>"; inherits: true; initial-value: #6EE7F9; }
@property --rule { syntax: "<color>"; inherits: true; initial-value: #283266; }
@property --slab-l { syntax: "<color>"; inherits: true; initial-value: #10163A; }
@property --slab-r { syntax: "<color>"; inherits: true; initial-value: #0D1230; }
@property --pad { syntax: "<color>"; inherits: true; initial-value: #10162F; }
@property --hot { syntax: "<color>"; inherits: true; initial-value: #FFF1CC; }
@property --link { syntax: "<color>"; inherits: true; initial-value: #8EA2FF; }
@property --link-line { syntax: "<color>"; inherits: true; initial-value: rgba(142, 162, 255, .45); }
@property --key { syntax: "<color>"; inherits: true; initial-value: #FFC857; }
@property --cta { syntax: "<color>"; inherits: true; initial-value: #141B3C; }
@property --cta-ink { syntax: "<color>"; inherits: true; initial-value: #E9ECFB; }
@property --cta-line { syntax: "<color>"; inherits: true; initial-value: #343F7A; }
@property --on-amber { syntax: "<color>"; inherits: true; initial-value: #0B1026; }
@property --glow { syntax: "<color>"; inherits: true; initial-value: #8EA2FF; }
@property --halo { syntax: "<color>"; inherits: true; initial-value: #FFC857; }
@property --lit { syntax: "<color>"; inherits: true; initial-value: #FFC857; }
@property --trail { syntax: "<color>"; inherits: true; initial-value: #FFC857; }
@property --ao { syntax: "<color>"; inherits: true; initial-value: #0B1026; }
@property --cast { syntax: "<color>"; inherits: true; initial-value: rgba(63, 77, 166, 0); }
@property --grid-o { syntax: "<number>"; inherits: true; initial-value: .085; }
@property --left-lit { syntax: "<color>"; inherits: true; initial-value: #4A4A64; }
@property --fl-lit { syntax: "<color>"; inherits: true; initial-value: #FFC857; }
@property --fl-k { syntax: "<number>"; inherits: true; initial-value: 1; }
@property --po-papier { syntax: "<color>"; inherits: true; initial-value: #1E2752; }
@property --po-ciel { syntax: "<color>"; inherits: true; initial-value: #93D0FF; }
@property --po-marine { syntax: "<color>"; inherits: true; initial-value: #4D69E6; }
@property --po-verre { syntax: "<color>"; inherits: true; initial-value: #2F6BFF; }
/* Les teintes tirées des précédentes : leur valeur initiale est le mélange de nuit, arrondi (elle ne sert que si la racine n'en donne aucune). */
@property --po-p-ciel { syntax: "<color>"; inherits: true; initial-value: #324672; }
@property --po-p-clair { syntax: "<color>"; inherits: true; initial-value: #293863; }
@property --po-p-marine { syntax: "<color>"; inherits: true; initial-value: #243065; }
@property --po-clair { syntax: "<color>"; inherits: true; initial-value: #BBDDFE; }
@property --po-reflet { syntax: "<color>"; inherits: true; initial-value: #B4CFFF; }
/* Les teintes des deux clins d'œil du clavier (12-clins.css). */
@property --clc { syntax: "<color>"; inherits: true; initial-value: #F08A66; }
@property --clc-halo { syntax: "<color>"; inherits: true; initial-value: #F08A66; }
@property --clc-lit { syntax: "<color>"; inherits: true; initial-value: #F08A66; }
@property --clc-key { syntax: "<color>"; inherits: true; initial-value: #F4A083; }
@property --clc-top { syntax: "<color>"; inherits: true; initial-value: #D97757; }
@property --clc-left { syntax: "<color>"; inherits: true; initial-value: #B55D42; }
@property --clc-right { syntax: "<color>"; inherits: true; initial-value: #8E4731; }
@property --clc-edge { syntax: "<color>"; inherits: true; initial-value: #FFD3C2; }
@property --clb { syntax: "<color>"; inherits: true; initial-value: #F7931A; }
@property --clb-halo { syntax: "<color>"; inherits: true; initial-value: #F7931A; }
@property --clb-lit { syntax: "<color>"; inherits: true; initial-value: #F7931A; }
@property --clb-key { syntax: "<color>"; inherits: true; initial-value: #FFB04D; }
@property --clb-top { syntax: "<color>"; inherits: true; initial-value: #F7931A; }
@property --clb-left { syntax: "<color>"; inherits: true; initial-value: #C8750F; }
@property --clb-right { syntax: "<color>"; inherits: true; initial-value: #9C5A0A; }
@property --clb-edge { syntax: "<color>"; inherits: true; initial-value: #FFDDA8; }
:root.theme-fade {
  transition: .5s ease;
  transition-property: --bg, --slab, --top, --left, --right, --edge, --ink, --ink-2, --amber, --accent, --rule, --slab-l, --slab-r, --pad, --hot,
    --link, --link-line, --key, --cta, --cta-ink, --cta-line, --on-amber, --glow, --halo, --lit, --trail, --ao, --cast, --grid-o,
    --left-lit, --fl-lit, --fl-k, --po-papier, --po-ciel, --po-marine, --po-verre, --po-p-ciel, --po-p-clair, --po-p-marine, --po-clair, --po-reflet,
    --clc, --clc-halo, --clc-lit, --clc-key, --clc-top, --clc-left, --clc-right, --clc-edge,
    --clb, --clb-halo, --clb-lit, --clb-key, --clb-top, --clb-left, --clb-right, --clb-edge;
}
/* Pendant le fondu, les éléments qui ont leur propre transition de couleur suivent la racine sans retard. */
.theme-fade :is(.cta, .btn, .skip, .theme-btn, .top .nav-proj a, .fl-n, .jr-key) { transition: none; }
@media (prefers-reduced-motion: reduce) { :root.theme-fade { transition: none; } }
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; background: var(--bg); scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }
body { margin: 0; background: var(--bg); color: var(--ink); font: 400 1.0625rem/1.6 var(--sans); -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility; overflow-x: clip; }
:is(h1, h2, h3, h4, h5, p, dl, dd, figure, ul, ol) { margin: 0; }
:is(ul, ol) { list-style: none; padding: 0; }
:is(h1, h2, h3, h4, h5) { font-weight: 700; text-wrap: balance; }
svg { display: block; }
a { color: inherit; text-decoration-thickness: 1px; text-underline-offset: .24em; }
button { font: inherit; color: inherit; }
::selection { background: var(--amber); color: var(--on-amber); }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 3px; }
h1:focus { outline: none; }
.wrap { width: min(100% - 2 * var(--gut), var(--maxw)); margin-inline: auto; }
.num { font-variant-numeric: tabular-nums; }
/* ── En-tête ─────────────────────────────────────────────────── */
.top { position: relative; z-index: 3; }
.top-in { position: relative; display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 0 24px; min-height: 64px; padding-block: 8px; }
.brand { display: inline-flex; align-items: center; gap: 10px; min-height: 44px; font: 400 .86rem/1 var(--mono); text-decoration: none; }
/* Le losange ambre : la forme d'un paquet de la scène. */
.brand::before { content: ""; width: 14px; height: 7px; background: var(--amber); clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%); }
.top nav ul { display: flex; flex-wrap: wrap; align-items: center; gap: 0 clamp(18px, 2.4vw, 32px); }
.top nav a { display: inline-flex; align-items: center; min-height: 44px; font-size: .94rem; font-weight: 500; text-decoration: none; }
.top nav a:hover, .brand:hover { text-decoration: underline; text-decoration-color: var(--amber); text-decoration-thickness: 2px; text-underline-offset: .4em; }
.top .nav-proj a { min-height: 38px; padding: 0 14px; border: 1px solid var(--edge); border-radius: 6px; transition: background-color .15s, color .15s; }
.top .nav-proj a:hover { background: var(--edge); color: var(--bg); text-decoration: none; }
.nav-proj a::after { content: "→"; content: "→" / ""; margin-left: 8px; font-family: var(--mono); font-weight: 400; }
/* Le bouton de thème, seul ajout à l'en-tête. Il suit la navigation, calé à droite : un pictogramme au trait
   (le soleil propose le jour, la lune propose la nuit) et, dès 960 px, le libellé de l'action.
   Sans JS il reste masqué : c'est le script d'en-tête qui pose data-theme.
   Les deux libellés occupent la même case : le bouton garde sa largeur quand le thème change.
   Ses 6 px de marge intérieure, repris en marge négative, laissent de l'air au contour du focus sans décaler le pictogramme. */
.top nav { margin-left: auto; }
.theme-btn { display: none; align-items: center; justify-content: flex-end; gap: 8px; min-width: 46px; min-height: 44px; margin: 0 -6px 0 -16px; padding: 0 6px; background: none; border: 0; color: var(--ink-2); font: 400 .78rem/1 var(--mono); white-space: nowrap; cursor: pointer; transition: color .15s; }
:root[data-theme] .theme-btn { display: inline-flex; }
.theme-btn:hover { color: var(--ink); }
.theme-ico { flex: none; width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 1.3; stroke-linecap: round; stroke-linejoin: round; }
.theme-txt { display: inline-grid; }
.theme-txt > :is(.to-jour, .to-nuit) { grid-area: 1 / 1; }
.theme-btn:hover .theme-txt > span { text-decoration: underline; text-decoration-color: var(--amber); text-decoration-thickness: 2px; text-underline-offset: .4em; }
[data-theme="nuit"] .theme-ico.to-nuit, [data-theme="jour"] .theme-ico.to-jour { display: none; }
[data-theme="nuit"] .theme-txt > .to-nuit, [data-theme="jour"] .theme-txt > .to-jour { visibility: hidden; }
.vh { position: absolute; width: 1px; height: 1px; margin: -1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
/* Mouvement réduit : le bouton change de couleur d'un coup, comme le reste (dans T18d, sa couleur fondait encore en 0,15 s). */
@media (prefers-reduced-motion: reduce) { .theme-btn { transition: none; } }
@media (max-width: 959px) {
  /* Pas la place pour le libellé : il reste dans le nom accessible du bouton. */
  .theme-txt { position: absolute; width: 1px; height: 1px; margin: -1px; overflow: hidden; clip-path: inset(50%); }
}
@media (min-width: 960px) {
  .theme-btn { margin-left: -6px; }
  .theme-ico { width: 16px; height: 16px; }
}
/* En-tête sur deux rangées. T18 la quittait à 700 px ; ici à 720 px, pour que le bouton tienne sur la rangée unique. */
@media (max-width: 719px) {
  .top-in { min-height: 0; padding-block: 6px 0; }
  .top nav { width: 100%; }
  .top nav ul { gap: 0 22px; }
  .top nav a { min-height: 40px; }
  .top .nav-proj { position: absolute; top: 9px; right: 0; }
  .top .nav-proj a { min-height: 38px; }
  .theme-btn { position: absolute; right: -6px; bottom: 0; width: 50px; min-height: 40px; margin: 0; }
}
/* ── Hero : le texte à gauche, la scène à droite (45 % au plus) ──
   Sous 960 px, tout s'empile : nom, portrait et rôle, certification, scène, puis pitch, bouton et repères. */
.hero { padding-block: clamp(10px, 2.2vw, 32px) clamp(48px, 6vw, 88px); }
.hero-grid { display: flex; flex-direction: column; }
.hero-text { display: contents; }
h1 { margin-left: -.04em; font-size: clamp(3rem, 14vw, 4.6rem); line-height: .95; letter-spacing: -.045em; }
/* L'identité, sous le nom : le portrait à gauche du rôle et de la certification.
   Téléphone : le rôle à côté du portrait, la certification dessous, sur toute la largeur. */
.hero-id { display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: center; gap: 14px 16px; margin-top: 14px; }
.hero-id-t { display: contents; }
.hero-role { font-size: clamp(1.06rem, 1.9vw, 1.45rem); line-height: 1.3; font-weight: 500; letter-spacing: -.012em; text-wrap: balance; }
/* La certification, sous le rôle : son logo, ce qu'elle est, son intitulé. Tout le cartouche est le lien vers sa preuve. */
.hero-cert { grid-column: 1 / -1; }
.hero-cert a { display: inline-flex; align-items: center; gap: 12px; max-width: 100%; padding: 6px 16px 6px 6px; border: 1px solid var(--rule); border-radius: 8px; color: var(--ink); text-decoration: none; }
.hero-cert a:hover { border-color: var(--edge); }
.hero-cert-txt { display: grid; min-width: 0; }
.hero-cert-k { font: 400 .7rem/1.7 var(--mono); letter-spacing: .08em; text-transform: uppercase; color: var(--ink-2); }
.hero-cert-n { font-size: .98rem; line-height: 1.35; font-weight: 500; }
.hero-cert-n::after { content: "↗"; content: "↗" / ""; margin-left: 6px; font-family: var(--mono); font-weight: 400; }
.hero-pitch { order: 4; margin-top: 22px; max-width: 34em; font-size: clamp(1rem, 1.25vw, 1.14rem); line-height: 1.6; color: var(--ink-2); text-wrap: pretty; }
.hero-act { order: 5; margin-top: 24px; }
/* Le lien principal : une ligne de commande. Du texte en chasse fixe, une invite, une flèche, et un trait sous le texte
   qui s'allonge au survol et au focus pendant que la flèche avance. En mouvement réduit, rien ne glisse. */
.cta { display: inline-flex; align-items: center; gap: 12px; min-height: 48px; padding: 0 2px; background: linear-gradient(var(--accent), var(--accent)) left bottom / 34% 2px no-repeat; color: var(--ink); font: 400 1.05rem/1 var(--mono); text-decoration: none; transition: background-size .25s ease-out; }
.cta::before { content: ">"; content: ">" / ""; color: var(--accent); }
.cta::after { content: "→"; content: "→" / ""; display: inline-block; color: var(--accent); transition: transform .2s ease-out; }
.cta:is(:hover, :focus-visible) { background-size: 100% 2px; }
.cta:is(:hover, :focus-visible)::after { transform: translateX(4px); }
@media (prefers-reduced-motion: reduce) {
  .cta::after { transition: none; }
  .cta:is(:hover, :focus-visible)::after { transform: none; }
}
.facts { order: 6; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: 24px; max-width: 34rem; margin-top: 28px; border-top: 1px solid var(--rule); }
.facts > div { min-width: 0; padding-block: 9px 10px; border-bottom: 1px solid var(--rule); }
/* Un nombre impair de repères : le dernier prend toute la largeur, pour que la rangée ne reste pas à moitié vide. */
.facts > div:last-child:nth-child(odd) { grid-column: 1 / -1; }
:is(.facts, .terms) dt { font: 400 .7rem/1.7 var(--mono); letter-spacing: .08em; text-transform: uppercase; color: var(--ink-2); }
.facts dd { font-size: .98rem; line-height: 1.35; font-weight: 500; }
/* ── Le portrait (src/components/home/Portrait.astro) ────────────
   Une tuile hexagonale, la silhouette d'un bloc de la scène : 112 × 132, et 72 × 85 sur téléphone.
   Chaque calque est un rectangle rempli d'un token et découpé par un masque monochrome : le portrait suit le thème sans script.
   Ses teintes sont les tokens --po-* de 01-tokens.css : le papier (l'aplat du sujet), le bleu ciel du chapeau, le marine de la
   chemise, le bleu des verres, et ce qui en est tiré. Le visage et la barbe gardent --edge.
   Le papier d'abord, teinté par région ; puis l'encre, teintée par les mêmes régions ; puis les verres et leurs reflets.
   La trame a deux encres : de nuit les losanges grandissent avec la lumière, de jour avec l'ombre. Elles se relaient en fondu,
   avec les couleurs ; en mouvement réduit la classe theme-fade n'est jamais posée, et le relais est immédiat. */
.po { display: block; width: 72px; height: auto; overflow: visible; }
.po-fond { fill: var(--slab); }
.po-grille { fill: none; stroke: var(--edge); stroke-opacity: calc(var(--grid-o) * 1.5); stroke-width: 1px; vector-effect: non-scaling-stroke; }
.po-arete { fill: none; stroke: var(--edge); stroke-opacity: .6; stroke-width: 1.15px; stroke-linejoin: round; vector-effect: non-scaling-stroke; }
.po-papier { fill: var(--po-papier); }
.po-p-ciel { fill: var(--po-p-ciel); }
.po-p-clair { fill: var(--po-p-clair); }
.po-p-marine { fill: var(--po-p-marine); }
.po-enc { fill: var(--edge); }
.po-ciel { fill: var(--po-ciel); }
.po-clair { fill: var(--po-clair); }
.po-marine { fill: var(--po-marine); }
.po-verre { fill: var(--po-verre); }
.po-reflet { fill: var(--po-reflet); }
.po-j { opacity: 0; }
[data-theme="jour"] .po-n { opacity: 0; }
[data-theme="jour"] .po-j { opacity: 1; }
.theme-fade :is(.po-n, .po-j) { transition: opacity .5s ease; }
@media (min-width: 600px) { .po { width: 112px; } }
/* ── Fin du portrait ── */
.scene-cap { font: 400 .72rem/1.55 var(--mono); color: var(--ink-2); }
@media (min-width: 600px) {
  .hero-id { gap: 24px; margin-top: 22px; }
  .hero-id-t { display: grid; gap: 14px; justify-items: start; min-width: 0; }
  .hero-cert { grid-column: auto; }
}
@media (min-width: 960px) {
  .hero-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 45%); align-items: center; column-gap: clamp(28px, 4vw, 64px); min-height: min(calc(100svh - 200px), 700px); }
  .hero-text { display: block; min-width: 0; }
  h1 { font-size: min(7vw, 6.2rem); }
}
/* ── La scène : une dalle, six blocs, des liaisons, des paquets ──
   Projection isométrique 2:1 : une case de la grille (i, j) mesure 48 × 24 unités à l'écran,
   sx = ox + (i − j) × 24, sy = oy + (i + j) × 12 − z. Les coordonnées du SVG viennent de cette formule.
   Ordre des calques : dalle, emplacements, ombres portées, liaisons, paquets, blocs (du fond vers l'avant), étiquettes.
   Les paquets circulent sous les blocs : ils sortent d'une face et disparaissent derrière le bloc suivant.
   La lumière vient de la gauche, dans les deux thèmes : la face gauche est la plus claire, l'ombre portée tombe à droite.
   De nuit, les blocs et les paquets luisent. De jour, les ombres remplacent les lueurs : --cast, --glow et --halo changent de rôle. */
.scene { order: 3; position: relative; min-width: 0; margin-top: 16px; }
.scene-frame { margin-inline: calc(-1 * var(--gut)); }
/* Téléphone : la scène est recadrée (les deux pointes de la dalle sortent du cadre), les six blocs restent entiers. */
.scene-svg { --sw: 1.5px; width: 100%; height: auto; aspect-ratio: 620 / 372; }
.scene-cap { max-width: 47ch; margin-top: 8px; }
.scene-cap:empty { display: none; }     /* vide hors clin d'œil : ni ligne ni marge */
.cap-k { color: var(--key); }
.scene-svg text { font-family: var(--mono); }
/* Les deux dégradés de la scène prennent leur couleur ici : le SVG n'en porte aucune. */
.g-ground stop { stop-color: var(--glow); }
.g-halo stop { stop-color: var(--halo); }
.s-glow { fill: url(#t18-ground); }
.slab-top { fill: var(--slab); }
.slab-l { fill: var(--slab-l); }
.slab-r { fill: var(--slab-r); }
.slab-edge, .slab-rim, .s-grid path, .edge, .lnk, .ring, .lit-e { fill: none; stroke-width: var(--sw); stroke-linecap: round; stroke-linejoin: round; }
.slab-edge { stroke: var(--edge); stroke-opacity: .6; }
.slab-rim { stroke: var(--edge); stroke-opacity: .26; }
.s-grid path { stroke: var(--edge); stroke-opacity: var(--grid-o); stroke-width: 1px; }
.ao { fill: var(--ao); fill-opacity: .42; }
/* Les ombres portées, douces et visibles seulement de jour (--cast est transparent de nuit) :
   celle de chaque bloc sur la dalle, celle de la dalle sur la table. */
.s-casts { filter: blur(2.6px); }
.s-under { filter: blur(5px); }
.cast { fill: var(--cast); }
.pad { fill: var(--pad); stroke: var(--edge); stroke-opacity: .34; stroke-width: 1px; }
.ring { stroke: var(--accent); opacity: 0; }
.lnk { stroke: var(--accent); stroke-opacity: .78; }
.chev { fill: var(--accent); }
.f-t { fill: var(--top); }
.f-l { fill: var(--left); }
.f-r { fill: var(--right); }
.skirt { display: none; }               /* le bas des faces, prolongé sous la dalle : utile seulement pendant la montée */
.is-intro .skirt { display: inline; }
.edge { stroke: var(--edge); }
.edge-s { stroke-opacity: .42; }
/* Les détails : un écran (client), des anneaux (CDN), une page (front), des ports (API), des fentes (file), des strates (base). */
.d-hole { fill: var(--bg); stroke: var(--edge); stroke-opacity: .75; stroke-width: 1px; stroke-linejoin: round; }
.d-line { fill: none; stroke: var(--accent); stroke-opacity: .85; stroke-width: var(--sw); stroke-linecap: round; stroke-linejoin: round; }
.d-seam { fill: none; stroke: var(--edge); stroke-opacity: .7; stroke-width: 1px; stroke-linejoin: round; }
.d-fill { fill: var(--accent); }
.d-soft { fill: var(--edge); fill-opacity: .5; }
/* Un bloc traversé par un paquet : ses faces se teintent d'ambre, ses arêtes aussi.
   De nuit c'est un éclat, de jour un liseré ambre et une teinte légère (--lit est alors translucide). */
.lit { opacity: 0; pointer-events: none; }
.lit-t { fill: var(--lit); fill-opacity: .36; }
.lit-l { fill: var(--lit); fill-opacity: .16; }
.lit-r { fill: var(--lit); fill-opacity: .09; }
.lit-e { stroke: var(--amber); }
.pkt { visibility: hidden; }
.pkt-halo { fill: url(#t18-halo); }
.pkt-core { fill: var(--amber); }
.pkt-trail { fill: var(--trail); }
.pkt-hot { fill: var(--hot); }
.lab { fill: var(--ink); font-size: 18px; text-anchor: middle; letter-spacing: .02em; }
@media (min-width: 600px) {
  .scene-frame { margin-inline: 0; }
  .scene-svg { --sw: 1.15px; aspect-ratio: 676 / 372; max-width: 700px; }
  .lab { font-size: 15px; }
}
@media (min-width: 960px) {
  .scene { margin-top: 0; }
  .scene-cap { margin-top: 12px; }
}
@media (prefers-reduced-motion: reduce) { .cta, .top .nav-proj a { transition: none; } }
/* ── Sections : un filet, puis le titre. Chaque section porte une pièce de la plateforme. ── */
.sec { padding-block: clamp(52px, 7vw, 96px); border-top: 1px solid var(--rule); }
.sec-head { display: grid; grid-template-columns: minmax(0, 1fr); align-items: center; gap: 12px 16px; margin-bottom: clamp(28px, 4vw, 48px); }
h2 { font-size: clamp(1.9rem, 4vw, 3rem); line-height: 1.05; letter-spacing: -.035em; }
h3 { font-size: clamp(1.2rem, 1.7vw, 1.4rem); line-height: 1.2; letter-spacing: -.02em; }
.sec-lede { grid-column: 1 / -1; max-width: 46ch; font-size: clamp(1.02rem, 1.35vw, 1.14rem); line-height: 1.45; color: var(--ink-2); }
/* Le logo d'une organisation (src/components/Logo.astro) : une vignette carrée aux coins arrondis, cernée d'un filet. */
.logo { display: block; flex: none; width: 40px; height: 40px; border: 1px solid var(--rule); border-radius: 6px; }
.tags { display: flex; flex-wrap: wrap; align-content: flex-start; align-items: flex-start; gap: 6px; }
.tags li { padding: 2px 8px; border: 1px solid var(--rule); border-radius: 4px; font: 400 .72rem/1.5 var(--mono); color: var(--ink-2); }
/* ── Expertise : huit cartes à filets fins, un pictogramme et un numéro en tête ── */
.px { display: grid; grid-template-columns: minmax(0, 1fr); gap: 14px; }
.px > li { display: flex; flex-direction: column; gap: 12px; min-width: 0; padding: clamp(20px, 2vw, 26px); border: 1px solid var(--rule); border-radius: 6px; }
.px-top { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
.px-n { font: 400 .78rem/1 var(--mono); letter-spacing: .04em; color: var(--ink-2); }
/* Les pièces de la plateforme au fil de la page : même projection 2:1 que la scène, mêmes trois tons, mêmes arêtes.
   Elles sont dessinées à une échelle proche de 1 (une unité du SVG ≈ un pixel), d'où des traits d'environ un pixel.
   Les huit pictogrammes ont la même hauteur et reposent sur la même ligne ; ils sont plus petits sur téléphone.
   De jour, chaque bloc porte la même ombre douce que ceux du hero (.cast, transparente de nuit), tombée à droite. */
.pic, .tw-svg, .ct-svg { --sw: 1.1px; flex: none; overflow: visible; }
.pic { --sw: 1.2px; width: auto; height: 54px; margin: -2px 0 2px -2px; }
@media (min-width: 680px) { .pic { --sw: 1px; height: 70px; } }
.cote { stroke-width: 1px; }
.p-casts { filter: blur(1.6px); }
/* Quand une pièce arrive à l'écran (.pose, posée par le script), ses blocs montent de quelques pixels et se posent,
   une seule fois, en 0,5 s, à 70 ms d'écart. Ils partent d'un état visible : sans script, ils sont déjà en place. */
@keyframes t18c-pose {
  0% { transform: translateY(7px); animation-timing-function: cubic-bezier(.2, .8, .3, 1); }
  66% { transform: translateY(-1.5px); animation-timing-function: cubic-bezier(.4, 0, .6, 1); }
  100% { transform: translateY(0); }
}
.b1 { --i: 1; } .b2 { --i: 2; } .b3 { --i: 3; }
@media (prefers-reduced-motion: no-preference) {
  .pose .b { animation: t18c-pose .5s backwards; animation-delay: calc(var(--d, 0ms) + var(--i, 0) * 70ms); }
}
.px-text { font-size: .98rem; line-height: 1.55; text-wrap: pretty; }
.px-note { margin-top: 24px; font-size: 1.02rem; font-weight: 500; }
/* Pictogramme et numéro, titre, texte et technos s'alignent d'une carte à l'autre sur une même rangée. */
@supports (grid-template-rows: subgrid) {
  .px > li { display: grid; grid-template-rows: subgrid; grid-row: span 4; row-gap: 12px; }
}
@media (min-width: 680px) { .px { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1040px) { .px { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
/* ── Parcours : liste datée, périodes en mono, et la tour à côté ── */
.jr { border-top: 1px solid var(--rule); }
.jr > li { display: grid; grid-template-columns: minmax(0, 1fr); gap: 10px; padding-block: clamp(22px, 2.8vw, 32px); border-bottom: 1px solid var(--rule); }
.jr-when { font: 400 .84rem/1.5 var(--mono); color: var(--ink-2); }
.jr-dates { color: var(--ink); }
.jr-body { display: grid; gap: 8px; min-width: 0; justify-items: start; }
.jr-head { display: flex; align-items: center; gap: 14px; min-width: 0; }
.jr-head > div { display: grid; gap: 4px; min-width: 0; }
.jr-org { font-weight: 500; color: var(--ink-2); }
.jr-text { max-width: 62ch; text-wrap: pretty; }
.jr .tags { margin-top: 4px; }
.jr-more { display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 20px; margin-top: 26px; }
.jr-more a { display: inline-flex; align-items: center; min-height: 44px; color: var(--link); font-weight: 700; text-decoration-color: var(--link-line); }
.jr-more a::after { content: "→"; content: "→" / ""; margin-left: 8px; font-family: var(--mono); font-weight: 400; }
.jr-more a:hover, .links a:hover { text-decoration-color: var(--link); }
.jr-more span { font-size: .95rem; color: var(--ink-2); }
/* Le diplôme et la certification, sous la liste des postes : deux vignettes côte à côte, l'une sous l'autre sur téléphone. */
.dp { margin-top: clamp(32px, 4vw, 48px); }
.dp-list { display: grid; grid-template-columns: minmax(0, 1fr); gap: 12px; margin-top: 18px; }
.dp-list > li { display: flex; align-items: flex-start; gap: 14px; min-width: 0; padding: clamp(16px, 2vw, 22px); border: 1px solid var(--rule); border-radius: 6px; }
.dp-body { display: grid; gap: 4px; min-width: 0; justify-items: start; }
.dp-nom { font-weight: 700; line-height: 1.3; text-wrap: balance; }
.dp-org { font-weight: 500; color: var(--ink-2); }
.dp-detail { font: 400 .78rem/1.55 var(--mono); color: var(--ink-2); }
.dp-lien { display: inline-flex; align-items: center; min-height: 44px; margin-bottom: -10px; color: var(--link); font-weight: 500; text-decoration-color: var(--link-line); }
.dp-lien::after { content: "↗"; content: "↗" / ""; margin-left: 6px; font-family: var(--mono); }
.dp-lien:hover { text-decoration-color: var(--link); }
@media (min-width: 700px) { .dp-list { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; } }
/* La tour du parcours : une baie graduée en années, un châssis par poste, le plus ancien en bas. Chaque châssis occupe
   la place de ses vraies dates et porte un tiroir par année ; les années sont écrites à gauche, le rang du poste à droite,
   et le paquet du hero est posé sur le châssis du poste en cours. Le même numéro figure sur le châssis et devant le poste.
   Le châssis s'éclaire quand son poste est survolé ou passe au milieu de l'écran : un liseré ambre, une teinte sur ses faces,
   son numéro en ambre. Téléphone : la tour est une colonne étroite, collée au milieu de l'écran le long de la liste. */
.jr-wrap { display: grid; grid-template-columns: minmax(0, 1fr) 64px; column-gap: 12px; }
.jr-when { display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: center; }
.jr-dates, .jr-dur { grid-column: 2; }
.jr-dur { white-space: nowrap; }
.jr-sep { display: none; }
.jr { grid-area: 2 / 1; }
.tw { display: contents; }
.tw-cap { grid-area: 1 / 1 / 2 / -1; margin-bottom: 12px; font: 400 .72rem/1.55 var(--mono); color: var(--ink-2); }
.tw-svg { grid-area: 2 / 2; align-self: start; position: sticky; top: calc(50svh - 44px); width: 100%; height: auto; margin-block: 22px; }
.tw-svg path { vector-effect: non-scaling-stroke; }
.ax { fill: none; stroke: var(--edge); stroke-opacity: .8; stroke-width: 1px; }
.fl-n { fill: var(--ink); font: 400 27px/1 var(--mono); text-anchor: start; }
.fl-y { fill: var(--ink-2); font: 400 22px/1 var(--mono); text-anchor: end; }
.tw-halo { fill: url(#tw-halo); }
.fl .lit, .fl-n, .jr-key { transition: opacity .22s ease-out, fill .22s ease-out, color .22s ease-out, background-color .22s ease-out, border-color .22s ease-out; }
/* Les faces d'un étage éclairé : les proportions des blocs traversés du hero (dessus .36, gauche .16, droite .09),
   multipliées par --fl-k. De nuit, --fl-k vaut 1 et --fl-lit est l'ambre : c'est l'éclat du hero. De jour, une lumière
   crème, quatre fois plus présente, pour que l'étage se détache autant sur fond clair. */
.fl :is(.lit-l, .lit-r, .lit-t) { fill: var(--fl-lit); }
.fl .lit-l { fill-opacity: calc(.16 * var(--fl-k)); }
.fl .lit-r { fill-opacity: calc(.09 * var(--fl-k)); }
.fl .lit-t { fill-opacity: calc(.36 * var(--fl-k)); }
.fl.is-on .lit { opacity: 1; }
.fl.is-on .fl-n, .jr > li.is-on .jr-key { fill: var(--key); color: var(--key); }
/* Le repère devant le poste : le numéro de son étage, dans une pastille au ton d'une face. */
.jr-key { grid-row: 1 / span 2; align-self: start; display: grid; place-items: center; width: 1.5rem; height: 1.5rem; margin: -.1rem 12px 0 0; background: var(--left); border: 1px solid var(--edge); border-radius: 3px; color: var(--ink); font: 400 .8rem/1 var(--mono); }
.jr > li.is-on .jr-key { background: var(--left-lit); border-color: var(--amber); }
@media (min-width: 600px) {
  .jr-wrap { grid-template-columns: minmax(0, 1fr) 84px; column-gap: 24px; }
  .tw-svg { top: calc(50svh - 58px); }
  .fl-n { font-size: 22px; }
  .fl-y { font-size: 18px; }
}
@media (min-width: 860px) {
  .jr-wrap { grid-template-columns: minmax(0, 1fr) 186px; column-gap: clamp(24px, 4vw, 64px); }   /* 186 : la largeur de la tour */
  .jr { grid-area: 1 / 1; }
  .tw { display: block; grid-area: 1 / 2; align-self: start; position: sticky; top: calc(50svh - 196px); padding-block: 26px; }   /* 196 : la moitié du bloc (tour, marges, légende) */
  .tw-svg { position: static; width: auto; margin: 0; }
  .tw-cap { margin: 14px 0 0; }
  .tw-cap span { display: block; }
  .fl-n { font-size: 15px; }
  .fl-y { font-size: 11px; }
  .jr > li { grid-template-columns: minmax(0, 15rem) minmax(0, 1fr); gap: 10px clamp(24px, 4vw, 64px); }
  .jr-when { align-content: start; padding-top: .1em; }
}
@media (prefers-reduced-motion: reduce) { .fl .lit, .fl-n, .jr-key { transition: none; } }

/* Le détail d'un poste : replié sous son résumé, dans un <details>. Le bouton est le <summary> : un lien de texte, un chevron,
   et ce que le détail contient (« 3 missions · 23 technos »). Il s'ouvre sans script ; là où le navigateur sait animer une
   hauteur vers « auto », il s'ouvre en 0,3 s. Dedans : le contexte, les missions par thème, ce qui tourne en production,
   la stack complète par catégorie. Avant la liste, un bouton les ouvre tous : il a besoin du script (src/scripts/parcours.ts)
   et reste masqué sans lui, comme le bouton de thème. */
.jd-tout { display: none; margin: calc(-1 * clamp(12px, 2vw, 22px)) 0 6px; }
:root[data-theme] .jd-tout { display: flex; }
.jd-tout button { min-height: 44px; padding: 0; background: none; border: 0; color: var(--link); font-weight: 500; text-decoration: underline; text-decoration-color: var(--link-line); text-decoration-thickness: 1px; text-underline-offset: .24em; cursor: pointer; }
.jd-tout button:hover, .jd-sum:hover .jd-lib { text-decoration-color: var(--link); }
.jd { justify-self: stretch; min-width: 0; interpolate-size: allow-keywords; }
.jd-sum { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 2px 14px; min-height: 44px; list-style: none; cursor: pointer; }
.jd-sum::-webkit-details-marker { display: none; }
.jd-lib { display: inline-flex; align-items: center; gap: 10px; color: var(--link); font-weight: 500; text-decoration: underline; text-decoration-color: var(--link-line); text-decoration-thickness: 1px; text-underline-offset: .24em; }
.jd-lib::after { content: ""; width: 7px; height: 7px; border: solid currentColor; border-width: 0 1.5px 1.5px 0; transform: translateY(-2px) rotate(45deg); transition: transform .2s ease; }
.jd[open] .jd-lib::after { transform: translateY(2px) rotate(-135deg); }
.jd-fermer, .jd[open] .jd-ouvrir { display: none; }
.jd[open] .jd-fermer { display: inline; }
.jd-hint { font: 400 .72rem/1.5 var(--mono); color: var(--ink-2); }
.jd::details-content { block-size: 0; overflow-y: clip; transition: block-size .3s ease, content-visibility .3s allow-discrete; }
.jd[open]::details-content { block-size: auto; }
.jd-in { display: grid; gap: 24px; padding-block: 12px 6px; }
.jd-ctx { max-width: 62ch; text-wrap: pretty; }
.jd-blk { display: grid; gap: 12px; min-width: 0; }
.jd-k { font: 400 .72rem/1.3 var(--mono); text-transform: uppercase; letter-spacing: .06em; color: var(--accent); }
.jd-ms { display: grid; gap: 18px; }
.jd-ms h5 { font-size: 1rem; line-height: 1.3; letter-spacing: -.01em; }
.jd-pts { display: grid; gap: 6px; }
.jd-ms .jd-pts { margin-top: 6px; }
.jd-pts li { position: relative; max-width: 62ch; padding-left: 20px; font-size: .98rem; line-height: 1.5; text-wrap: pretty; }
/* La puce : le losange d'un paquet de la scène. */
.jd-pts li::before { content: ""; position: absolute; left: 1px; top: .6em; width: 10px; height: 5px; background: var(--edge); clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%); }
.jd-stk { display: grid; gap: 4px; }
.jd-stk > div { display: grid; grid-template-columns: minmax(0, 1fr); gap: 4px 20px; }
.jd-stk dt { margin-top: 8px; font: 400 .72rem/1.5 var(--mono); color: var(--ink-2); }
.jd-stk .tags { margin-top: 0; }
.jd-stk .tags li { color: var(--ink); }
@media (min-width: 600px) {
  .jd-stk { gap: 10px; }
  .jd-stk > div { grid-template-columns: 9.5rem minmax(0, 1fr); }
  .jd-stk dt { margin-top: 0; padding-top: 3px; }
}
@media (prefers-reduced-motion: reduce) { .jd-lib::after, .jd::details-content { transition: none; } }
/* ── Contact, pied ───────────────────────────────────────── */
.ct-grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: 28px; align-items: start; }
.ct-main .sec-head { margin-bottom: 0; }
/* Contact : le client, d'où part un paquet.
   La liaison du contact s'efface vers sa pointe : son dégradé prend sa couleur ici, comme ceux de la scène. */
.ct-svg { width: 100px; height: auto; }
.g-fade stop { stop-color: var(--accent); }
.lnk-fade { stroke: url(#t18c-fade); stroke-opacity: 1; }
.ct-halo { fill: url(#t18c-halo); }
.ct-svg .lab { font-family: var(--mono); font-size: 12px; }
.ct-svg .p-casts, .tw-svg .p-casts { filter: blur(2.4px); }
.ct-main { display: grid; justify-items: start; gap: 16px; min-width: 0; }
.ct-lead { max-width: 36ch; font-size: clamp(1.1rem, 1.8vw, 1.36rem); line-height: 1.4; font-weight: 500; letter-spacing: -.01em; text-wrap: pretty; }
.mail { display: flex; margin-top: 8px; }
/* L'adresse est le bouton : un clic la copie. Une petite icône le dit ; elle prend la couleur d'accent au survol et une fois l'adresse copiée. */
.mail-btn { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 10px 14px; max-width: 100%; min-height: 48px; padding: 0; background: none; border: 0; color: inherit; font: inherit; text-align: left; cursor: pointer; }
.mail-addr { padding-bottom: 3px; border-bottom: 1px dashed var(--edge); font: 400 clamp(1.05rem, 2.4vw, 1.5rem)/1.25 var(--mono); letter-spacing: -.02em; overflow-wrap: anywhere; }
.mail-ico { flex: none; width: 20px; height: 20px; fill: none; stroke: var(--ink-2); stroke-width: 1.5px; stroke-linecap: round; stroke-linejoin: round; }
.mail-btn:hover .mail-addr { border-bottom-style: solid; }
.mail-btn:hover .mail-ico, .mail-btn.fait .mail-ico { stroke: var(--accent); }
.skip {
  display: inline-flex; align-items: center; justify-content: center; min-height: 44px; padding: 0 18px;
  background: var(--slab); color: var(--ink); border: 1px solid var(--edge); border-radius: 6px; font: 500 .92rem/1 var(--sans); cursor: pointer; transition: background-color .15s, color .15s;
}
.skip:hover { background: var(--edge); color: var(--bg); }
.copy-status { min-height: 1.5em; margin-block: -6px; font-size: .9rem; color: var(--ink-2); }
.links { display: flex; flex-wrap: wrap; gap: 0 28px; }
.links a { display: inline-flex; align-items: center; min-height: 44px; color: var(--link); font-weight: 500; text-decoration-color: var(--link-line); }
.links a::after { content: "↗"; content: "↗" / ""; margin-left: 6px; font-family: var(--mono); }
.terms { border-top: 1px solid var(--rule); }
.terms > div { display: grid; grid-template-columns: minmax(0, 8.5rem) minmax(0, 1fr); align-items: baseline; gap: 2px 16px; padding-block: 13px; border-bottom: 1px solid var(--rule); }
.terms dd { font-weight: 500; }
.foot { border-top: 1px solid var(--rule); padding-block: 26px calc(64px + env(safe-area-inset-bottom)); font-size: .88rem; color: var(--ink-2); }
/* Téléphone : le client se range à droite du titre « Contact ». */
@media (max-width: 899px) {
  .ct-grid { grid-template-columns: minmax(0, 1fr) auto; gap: 16px; }
  .ct-main { display: contents; }
  .ct-main > * { grid-column: 1 / -1; justify-self: start; }
  .ct-main > .sec-head { grid-column: 1; align-self: end; }
  .ct-svg { grid-area: 1 / 2; }
  .terms { grid-column: 1 / -1; margin-top: 12px; }
}
@media (min-width: 900px) {
  .ct-svg { width: auto; }
  .ct-grid { grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr); grid-template-rows: auto 1fr; gap: 20px clamp(40px, 7vw, 112px); }
  .ct-main { grid-area: 1 / 1 / 3 / 2; }
  .ct-svg { grid-area: 1 / 2; }
  .terms { grid-area: 2 / 2; }
}
/* ── Bouton « Passer », état d'attente de l'intro ────────────── */
.skip { position: fixed; bottom: calc(12px + env(safe-area-inset-bottom)); right: max(12px, env(safe-area-inset-right)); z-index: 30; }
.skip[hidden] { display: none; }
/* Seuls les éléments que l'intro fait apparaître sont masqués, et seulement tant que la classe est là. */
.intro-pending .scene-svg > g, .intro-pending .scene-cap { visibility: hidden; }
@media (prefers-reduced-motion: reduce) { .btn, .skip { transition: none; } }
@media print { .skip { display: none !important; } }
/* ── Pages simples : la 404 et les mentions légales ──────────────
   La marque en tête, puis un titre et son contenu. Les mêmes tokens que l'accueil : ces pages suivent le thème mémorisé. */
.page { padding-block: clamp(36px, 8vw, 104px) clamp(56px, 8vw, 112px); }
.page h1 { margin-left: -.03em; font-size: clamp(2.3rem, 6vw, 3.6rem); line-height: 1; letter-spacing: -.04em; }
.page-lede { margin-top: 18px; max-width: 34em; font-size: clamp(1.02rem, 1.35vw, 1.14rem); line-height: 1.55; color: var(--ink-2); text-wrap: pretty; }
.page-act { margin-top: 30px; }
.page section { max-width: 44rem; margin-top: clamp(36px, 5vw, 56px); }
.page h2 { margin-bottom: 16px; font-size: clamp(1.3rem, 2.2vw, 1.6rem); line-height: 1.15; letter-spacing: -.02em; }
/* Une adresse e-mail ou une immatriculation ne déborde pas de sa colonne sur téléphone : elle se coupe au besoin. */
.page .terms dd { overflow-wrap: anywhere; }
.page section p { max-width: 62ch; text-wrap: pretty; }
.page section p + p { margin-top: 10px; }
.page-back, .foot-legal a { display: inline-flex; align-items: center; min-height: 44px; }
.page-back { color: var(--link); font-weight: 700; text-decoration-color: var(--link-line); }
.page-back:hover { text-decoration-color: var(--link); }
/* Le résumé des mentions légales et le lien vers leur page : ils n'existent que si la page existe. */
.foot-ml { max-width: 78ch; margin-top: 6px; text-wrap: pretty; }
.foot-legal { margin-top: 2px; }
.foot-legal a:hover { color: var(--ink); }
/* ── Les deux clins d'œil du clavier (src/scripts/clins-jeu.ts) : « claude » et « btc » ──
   Le temps qu'il dure, et pour la scène seulement, un clin d'œil donne sa teinte aux tokens des paquets (--amber, --trail,
   --halo, --lit) et à celui du mot-clé de la légende (--key) : les paquets d'ambiance, l'éclat des blocs et la légende
   la prennent sans qu'aucune règle ne les vise. Les teintes sont des tokens (--clc-* le corail, --clb-* l'orange, 01-tokens.css).
   Contrastes du mot-clé sur --bg : corail 8,6:1 de nuit et 5,2:1 de jour ; orange 9,6:1 de nuit, 5,5:1 de jour. */
.scene.cl-t { transition: --amber .45s ease, --trail .45s ease, --halo .45s ease, --lit .45s ease, --key .45s ease; }
.scene.cl-claude { --amber: var(--clc); --trail: var(--clc); --halo: var(--clc-halo); --lit: var(--clc-lit); --key: var(--clc-key); }
.scene.cl-btc { --amber: var(--clb); --trail: var(--clb); --halo: var(--clb-halo); --lit: var(--clb-lit); --key: var(--clb-key); }
/* Le septième bloc : les mêmes faces que les six autres, dans la teinte du clin d'œil. Son masque cache ce qui passe sous la dalle. */
.cl-blk .skirt { display: inline; }
.cl-ring { stroke: var(--amber); }
.cl-b-claude { --top: var(--clc-top); --left: var(--clc-left); --right: var(--clc-right); --edge: var(--clc-edge); --accent: var(--clc-edge); }
.cl-b-btc { --top: var(--clb-top); --left: var(--clb-left); --right: var(--clb-right); --edge: var(--clb-edge); --accent: var(--clb-edge); }
.cl-glyph { fill: none; stroke: var(--accent); stroke-width: 1.9px; stroke-linecap: round; stroke-linejoin: round; }
.cl-rays { fill: none; stroke: var(--amber); stroke-width: 2.6px; stroke-linecap: round; }
@media (prefers-reduced-motion: reduce) { .scene.cl-t { transition: none; } }
/* ── Page Projets : les projets professionnels en liste, les sites en cartes ──
   Presque tout vient de l'accueil : .sec et .sec-head, les blocs .jd-* du détail d'un poste, .tags, .links, la grille .px
   des piliers, .dp-lien, .cta. Ici : le titre de la page, la ligne d'un projet (ce qu'il est à gauche, son détail à droite
   dès 860 px, comme un poste du parcours), le surtitre, et la phrase d'un composant. */
.pj-top { padding-bottom: clamp(36px, 5vw, 64px); }
.pj { border-top: 1px solid var(--rule); }
.pj > li { display: grid; grid-template-columns: minmax(0, 1fr); gap: 18px; padding-block: clamp(26px, 3.4vw, 44px); border-bottom: 1px solid var(--rule); }
.pj-id { display: grid; gap: 6px; align-content: start; min-width: 0; }
.pj-k { font: 400 .7rem/1.7 var(--mono); letter-spacing: .08em; text-transform: uppercase; color: var(--ink-2); }
/* Dans une carte de site, le nom se cale en bas de sa rangée : les quatre noms restent alignés quand un surtitre passe sur deux lignes. */
.px .pj-id { align-content: end; }
.pj .jd-in { padding-block: 0; }
.pj-comp dd { max-width: 62ch; font-size: .98rem; line-height: 1.5; text-wrap: pretty; }
@media (min-width: 860px) {
  .pj > li { grid-template-columns: minmax(0, 17rem) minmax(0, 1fr); gap: 18px clamp(24px, 4vw, 64px); }
}
