/* Bobi.Studio — site vitrine
   Charte : thème « Studio » du produit (sombre chaud, accent ambre tally).
   Les neutres sont teintés vers l'ambre, jamais gris purs.
   Typo : Archivo (grotesque industrielle) + Fragment Mono (valeurs mesurées). */

/* ---------------------------------------------------------------- tokens */

:root {
  /* --paper* = fonds, du plus profond au plus élevé ; --ink* = textes */
  --paper:      oklch(0.208 0.008 68);
  --paper-2:    oklch(0.258 0.010 68);
  --paper-3:    oklch(0.305 0.011 68);
  --ink:        oklch(0.906 0.007 76);
  --ink-2:      oklch(0.735 0.011 72);
  --ink-3:      oklch(0.622 0.012 72);
  --rule:       oklch(0.352 0.013 68);
  --rule-soft:  oklch(0.292 0.011 68);

  --signal:     oklch(0.780 0.148 72);   /* ambre tally */
  --signal-tx:  oklch(0.800 0.140 74);   /* texte ambre sur fond sombre */
  --signal-dp:  oklch(0.775 0.152 71);   /* aplats */
  --on-signal:  oklch(0.192 0.020 62);   /* texte sur aplat ambre */

  --gutter: clamp(20px, 4.2vw, 60px);
  --measure: 62ch;
  --rail-x: max(var(--gutter), calc(50% - 640px + var(--gutter)));

  --step--1: clamp(0.80rem, 0.78rem + 0.10vw, 0.86rem);
  --step-0:  clamp(1.06rem, 1.02rem + 0.22vw, 1.18rem);
  --step-1:  clamp(1.32rem, 1.22rem + 0.44vw, 1.60rem);
  --step-2:  clamp(1.66rem, 1.46rem + 0.86vw, 2.20rem);
  --step-3:  clamp(2.05rem, 1.70rem + 1.50vw, 3.00rem);
  --step-4:  clamp(2.50rem, 2.00rem + 2.30vw, 4.00rem);

  --ease: cubic-bezier(0.16, 1, 0.3, 1);
  /* Hauteur de la barre collante. Elle sert aux ancres : sans elle, une cible
     atteinte au clavier ou par un lien #… se pose SOUS la barre, invisible. */
  --nav-h: 54px;
  color-scheme: dark;
}

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

html {
  -webkit-text-size-adjust: 100%; scroll-behavior: smooth; background: var(--paper);
  /* Vaut pour TOUT défilement provoqué par le navigateur, y compris celui du
     parcours au clavier — c'est ce qui rend la tabulation utilisable. */
  scroll-padding-top: calc(var(--nav-h) + 18px);
}
[id] { scroll-margin-top: calc(var(--nav-h) + 18px); }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: Archivo, "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-size: var(--step-0);
  line-height: 1.72;              /* texte clair sur fond sombre : on respire davantage */
  font-variation-settings: "wdth" 100;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

::selection { background: var(--signal); color: var(--on-signal); }

/* ------------------------------------------------------------ primitives */

.wrap { max-width: 1280px; margin-inline: auto; padding-inline: var(--gutter); }

.mono {
  font-family: "Fragment Mono", ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  font-size: 0.86em;
  letter-spacing: -0.01em;
}

a { color: inherit; }

.lnk {
  color: var(--signal-tx);
  text-decoration: none;
  border-bottom: 1px solid color-mix(in oklch, var(--signal) 38%, transparent);
  padding-bottom: 1px;
  transition: border-color 0.25s var(--ease), color 0.25s var(--ease);
}
.lnk:hover { border-bottom-color: var(--signal); }

h1, h2, h3 {
  margin: 0;
  font-weight: 700;
  line-height: 1.08;
  letter-spacing: -0.026em;
  color: oklch(0.975 0.004 80);
  text-wrap: balance;
}
h1, h2, h3 { font-variation-settings: "wdth" 114; letter-spacing: -0.012em; }
h2 { font-size: var(--step-2); }
h3 { font-size: var(--step-0); letter-spacing: -0.012em; font-weight: 700; line-height: 1.25; }

p { margin: 0 0 0.9em; max-width: var(--measure); }
p:last-child { margin-bottom: 0; }

.lede { font-size: var(--step-1); line-height: 1.55; letter-spacing: -0.014em; color: var(--ink); font-weight: 400; }
.muted { color: var(--ink-2); }
.tiny { font-size: var(--step--1); color: var(--ink-3); }

/* ------------------------------------------------------------------- nav */

.nav {
  position: sticky; top: 0; z-index: 40;
  background: color-mix(in oklch, var(--paper) 86%, transparent);
  backdrop-filter: saturate(1.3) blur(10px);
  border-bottom: 1px solid var(--rule);
}
.nav-in {
  display: flex; align-items: center;
  padding-block: 15px;
}
.mark {
  font-weight: 800; font-size: 1.06rem; letter-spacing: -0.04em;
  font-variation-settings: "wdth" 88;
  text-transform: uppercase; text-decoration: none; color: oklch(0.98 0.004 80);
  margin-right: clamp(26px, 4.5vw, 64px); flex: none;
}
.mark b { color: var(--signal); font-weight: 800; }

/* la navigation lit de gauche à droite ; le sélecteur de langue est seul à droite */
.nav nav { display: flex; flex-wrap: wrap; align-items: center; gap: clamp(16px, 2.4vw, 34px); }

.nav a.n {
  text-decoration: none; color: var(--ink-2);
  font-size: 0.95rem; font-weight: 500; white-space: nowrap;
  padding-block: 4px; border-bottom: 2px solid transparent;
  transition: color 0.2s var(--ease), border-color 0.2s var(--ease);
}
.nav a.n:hover { color: var(--ink); }
.nav a.n[aria-current="page"] { color: oklch(0.98 0.004 80); border-bottom-color: var(--signal); }

.lang {
  margin-left: auto; flex: none;
  font-family: "Fragment Mono", ui-monospace, monospace;
  font-size: 0.74rem; text-decoration: none; color: var(--ink-3);
  border: 1px solid var(--rule); border-radius: 2px;
  padding: 5px 10px; letter-spacing: 0.03em; line-height: 1;
  transition: border-color 0.2s var(--ease), color 0.2s var(--ease), background-color 0.2s var(--ease);
}
.lang:hover { color: var(--ink); border-color: var(--ink-3); background: var(--paper-2); }

/* sous 860 px la navigation prend sa propre ligne, pleine largeur */
@media (max-width: 860px) {
  .nav-in { flex-wrap: wrap; padding-block: 13px 0; }
  .mark { margin-right: 0; }
  .nav nav {
    order: 3; width: 100%; margin-top: 12px;
    border-top: 1px solid var(--rule-soft);
    padding-block: 9px 10px;
    gap: 18px; overflow-x: auto; flex-wrap: nowrap;
    scrollbar-width: none;
  }
  .nav nav::-webkit-scrollbar { display: none; }
}

/* ------------------------------------------------- aplat ambre (tally on) */

.drench {
  background: var(--signal-dp);
  color: var(--on-signal);
  --ink: var(--on-signal);
  --ink-2: color-mix(in oklch, var(--on-signal) 76%, var(--signal-dp));
  --ink-3: color-mix(in oklch, var(--on-signal) 58%, var(--signal-dp));
  --rule: color-mix(in oklch, var(--on-signal) 30%, transparent);
  --rule-soft: color-mix(in oklch, var(--on-signal) 17%, transparent);
}
.drench h1, .drench h2, .drench h3 { color: var(--on-signal); }
.drench a.lnk { color: var(--on-signal); border-bottom-color: color-mix(in oklch, var(--on-signal) 45%, transparent); }
.drench a.lnk:hover { border-bottom-color: var(--on-signal); }
.drench .btn-solid { background: var(--on-signal); color: var(--signal); border-color: var(--on-signal); }
.drench .btn-solid:hover { background: oklch(0.135 0.018 62); border-color: oklch(0.135 0.018 62); }
.drench .btn-ghost { color: var(--on-signal); border-color: color-mix(in oklch, var(--on-signal) 42%, transparent); }
.drench .btn-ghost:hover { background: color-mix(in oklch, var(--on-signal) 12%, transparent); }
.drench .facts .v, .drench .sec-label .num { color: var(--on-signal); }

/* ------------------------------------------------------------------ hero */

.hero-band { background: transparent; }
.hero { padding-block: clamp(60px, 11vw, 150px) clamp(34px, 5vw, 64px); }
.hero h1 {
  font-size: var(--step-4);
  font-variation-settings: "wdth" 112;
  letter-spacing: -0.016em;
  line-height: 1.08;
  max-width: 17ch;
}
.hero .lede { max-width: 50ch; margin-top: clamp(20px, 2.6vw, 34px); color: var(--ink-2); }
.hero-kick {
  font-family: "Fragment Mono", ui-monospace, monospace;
  font-size: 0.78rem; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--signal-tx); margin: 0 0 clamp(22px, 3.4vw, 40px);
  display: flex; gap: 12px; align-items: center;
}
/* le témoin tally, allumé */
.hero-kick::before {
  content: ""; width: 26px; height: 5px; border-radius: 1px; flex: none;
  background: var(--signal);
  box-shadow: 0 0 14px -1px color-mix(in oklch, var(--signal) 60%, transparent);
}
.hero-kick::after { content: ""; flex: 1; height: 1px; background: var(--rule); }

.hero-sub { padding-block: clamp(16px, 2.4vw, 26px) clamp(38px, 6vw, 74px); }

.strip {
  border-top: 1px solid var(--rule);
  display: grid; grid-template-columns: repeat(auto-fit, minmax(158px, 1fr));
}
.strip > div { padding: 15px 18px 17px 0; border-right: 1px solid var(--rule-soft); }
.strip > div:last-child { border-right: 0; }
.strip dt {
  font-family: "Fragment Mono", ui-monospace, monospace;
  font-size: 0.68rem; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--ink-3); margin-bottom: 5px;
}
.strip dd { margin: 0; font-size: 0.95rem; font-weight: 600; letter-spacing: -0.015em; color: var(--ink); }

/* ---------------------------------------------------------------- boutons */

.btns { display: flex; flex-wrap: wrap; gap: 12px; margin-top: clamp(26px, 3.6vw, 42px); }
.btn {
  display: inline-flex; align-items: center; gap: 9px;
  font-size: 0.94rem; font-weight: 600; letter-spacing: -0.01em;
  text-decoration: none; padding: 11px 19px; border-radius: 2px;
  border: 1px solid currentColor;
  transition: background-color 0.22s var(--ease), color 0.22s var(--ease),
              border-color 0.22s var(--ease), transform 0.22s var(--ease);
}
.btn:hover { transform: translateY(-1px); }
.btn-solid { background: var(--signal); color: var(--on-signal); border-color: var(--signal); }
.btn-solid:hover { background: oklch(0.845 0.145 80); border-color: oklch(0.845 0.145 80); }
.btn-ghost { color: var(--ink); border-color: var(--rule); }
.btn-ghost:hover { background: var(--paper-2); border-color: var(--ink-3); }

.arrow { font-family: "Fragment Mono", monospace; font-size: 0.9em; }

/* --------------------------------------------------------------- sections */

.sec { padding-block: clamp(62px, 10vw, 148px); }
.sec-grid {
  display: grid; gap: clamp(22px, 3vw, 40px);
  grid-template-columns: 1fr;
}
/* Sans ceci, la min-width du tableau des paliers remonte dans la piste de grille et élargit
   TOUTE la section : la page défilait horizontalement sous 940 px, jusqu'à 300 px de trop
   sur un téléphone. Le tableau doit défiler dans son cadre, pas pousser la page. */
.sec-grid > * { min-width: 0; }
/* Une comparaison à cinq colonnes n'a pas sa place dans une colonne de 800 px : la section
   passe sur une seule colonne, le titre au-dessus, et le tableau prend toute la largeur utile.
   Sans ça il défilait horizontalement même sur un grand écran. */
@media (min-width: 940px) {
  .sec.wide .sec-grid { grid-template-columns: 1fr; gap: clamp(18px, 2.2vw, 30px); }
  .sec.wide .sec-label { position: relative; top: auto; }
  .sec.wide .sec-label .hint { max-width: 70ch; }
}

@media (min-width: 940px) {
  /* le rail : un trait continu qui traverse toute la pile de sections */
  .sec { position: relative; }
  .sec::before {
    content: ""; position: absolute; top: 0; bottom: 0;
    left: var(--rail-x); width: 1px; background: var(--rule);
  }
  .sec-grid { grid-template-columns: minmax(210px, 3fr) minmax(0, 9fr); gap: clamp(40px, 5.5vw, 96px); }
  .sec-label { position: sticky; top: 96px; align-self: start; padding-left: 30px; }
  /* En section « wide » la grille est sur UNE colonne : sans ce retrait, le corps commence
     au bord de la gouttière, c'est-à-dire collé au rail — et 30 px à gauche du titre. */
  .sec.wide .sec-body { padding-left: 30px; }
  /* Le débordement dans la gouttière de .tiers-wrap n'a plus lieu d'être ici : il annulerait
     le retrait ci-dessus à gauche, et sortait de l'écran à droite autour de 940 px. */
  .sec.wide .tiers-wrap { margin-inline: 0; padding-inline: 0; }
  /* le connecteur, solidaire du titre : il descend le rail au fil de la lecture */
  .sec-label::before {
    content: ""; position: absolute; left: -5.5px; top: 10px;
    width: 11px; height: 11px; border-radius: 50%;
    background: var(--signal);
    box-shadow: 0 0 0 5px var(--paper), 0 0 16px -1px color-mix(in oklch, var(--signal) 70%, transparent);
  }
}
.sec-label .num {
  font-family: "Fragment Mono", ui-monospace, monospace;
  font-size: 0.74rem; color: var(--signal-tx); letter-spacing: 0.06em;
  display: block; margin-bottom: 12px;
}
.sec-label h2 { font-size: var(--step-1); font-variation-settings: "wdth" 100; }
.sec-label .hint { margin-top: 14px; font-size: 0.92rem; color: var(--ink-2); line-height: 1.6; max-width: 34ch; }

.sec-body > * + * { margin-top: clamp(28px, 3.6vw, 52px); }

/* --------------------------------------------------------------- listings */

.cols {
  display: grid; gap: clamp(28px, 3.6vw, 56px);
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
}
.cols > div > h3 { margin-bottom: 7px; }
.cols > div > h3 + p { color: var(--ink-2); font-size: 0.95rem; }

.spec { width: 100%; border-collapse: collapse; font-size: 0.94rem; }
.spec th, .spec td { text-align: left; vertical-align: top; padding: 16px 20px 16px 0; border-bottom: 1px solid var(--rule-soft); }
.spec tr:last-child th, .spec tr:last-child td { border-bottom: 0; }
.spec th { font-weight: 600; letter-spacing: -0.01em; width: 30%; min-width: 130px; color: var(--ink); }
.spec td { color: var(--ink-2); }
.spec td b, .spec td strong { color: var(--signal-tx); font-weight: 400; font-family: "Fragment Mono", ui-monospace, monospace; font-size: 0.9em; }
.spec caption {
  text-align: left; padding-bottom: 10px; border-bottom: 1px solid var(--rule);
  font-family: "Fragment Mono", ui-monospace, monospace;
  font-size: 0.7rem; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-3);
}

.facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(196px, 1fr)); gap: 4px; }
.facts > div { padding: 20px 20px 26px 0; }
.facts .v {
  font-family: "Fragment Mono", ui-monospace, monospace;
  font-size: clamp(1.5rem, 1.1rem + 1.5vw, 2.2rem); line-height: 1; color: var(--signal-tx);
  letter-spacing: -0.03em;
}
.facts .k { margin-top: 9px; font-size: 0.9rem; font-weight: 600; letter-spacing: -0.012em; color: var(--ink); }
.facts .d { margin-top: 3px; font-size: var(--step--1); color: var(--ink-3); line-height: 1.5; }

.tags { display: flex; flex-wrap: wrap; gap: 7px; }
.tag {
  font-family: "Fragment Mono", ui-monospace, monospace;
  font-size: 0.76rem; letter-spacing: -0.01em;
  border: 1px solid var(--rule); border-radius: 2px;
  padding: 5px 9px; color: var(--ink-2); background: var(--paper-2);
}
.tag.hot { border-color: color-mix(in oklch, var(--signal) 48%, transparent); color: var(--signal-tx); background: color-mix(in oklch, var(--signal) 9%, var(--paper-2)); }

/* ------------------------------------------------- protocoles dépliables */

button.tag {
  font: inherit; font-family: "Fragment Mono", ui-monospace, monospace;
  font-size: 0.76rem; letter-spacing: -0.01em; line-height: 1.5;
  cursor: pointer; text-align: left;
  transition: border-color 0.18s var(--ease), color 0.18s var(--ease),
              background-color 0.18s var(--ease);
}
button.tag:hover { color: var(--ink); border-color: var(--ink-3); }
button.tag[aria-expanded="true"] {
  color: var(--on-signal); background: var(--signal); border-color: var(--signal);
}

.proto-hint { margin-top: 14px; }

.proto-panel { margin-top: 16px; }
.proto-def {
  border: 1px solid color-mix(in oklch, var(--signal) 34%, var(--rule));
  border-radius: 3px; background: var(--paper-2);
  padding: 18px 20px 20px;
}
.proto-def + .proto-def { margin-top: 10px; }   /* visible seulement sans JavaScript */
.proto-def h3 {
  font-family: "Fragment Mono", ui-monospace, monospace;
  font-size: 0.82rem; font-weight: 400; letter-spacing: -0.01em;
  color: var(--signal-tx); margin-bottom: 8px;
}
.proto-def p { color: var(--ink-2); font-size: 0.95rem; max-width: 74ch; }

.notes { counter-reset: n; display: grid; padding: 0; margin: 0; }
.notes > li {
  counter-increment: n; list-style: none;
  display: grid; grid-template-columns: 40px 1fr; gap: 14px;
  padding: 20px 0;
}
.notes > li::before {
  content: counter(n, decimal-leading-zero);
  font-family: "Fragment Mono", ui-monospace, monospace;
  font-size: 0.74rem; color: var(--signal-tx); padding-top: 5px;
}
.notes h3 { margin-bottom: 4px; }
.notes p { color: var(--ink-2); font-size: 1rem; line-height: 1.65; }

/* ------------------------------------------------------------- paliers */

.tiers-wrap { overflow-x: auto; margin-inline: calc(var(--gutter) * -0.5); padding-inline: calc(var(--gutter) * 0.5); }
.tiers { border-collapse: collapse; width: 100%; min-width: 860px; font-size: 0.93rem; }
/* Rembourrage SYMÉTRIQUE : avec 18 px à droite et 0 à gauche, chaque colonne était collée
   au bord de la précédente — flagrant depuis qu'il y en a quatre, et pire encore contre la
   colonne teintée. Le filet de séparation fait le reste du travail. */
.tiers th, .tiers td {
  text-align: left; vertical-align: top;
  padding: 13px 16px; border-bottom: 1px solid var(--rule-soft);
}
.tiers tbody th { padding-left: 0; }
.tiers thead th, .tiers tbody td { border-left: 1px solid var(--rule-soft); }
.tiers thead th { border-bottom: 1px solid var(--rule); padding-bottom: 20px; vertical-align: bottom; }
/* Quatre paliers : le critère garde 22 %, les colonnes se partagent le reste. */
.tiers tbody th { font-weight: 500; color: var(--ink-3); width: 22%; }
.tiers td { width: 19.5%; color: var(--ink-2); }
.tiers td.na { color: oklch(0.47 0.010 70); }
.tiers .hi { background: color-mix(in oklch, var(--signal) 9%, transparent); }
.tiers thead .hi { padding-top: 14px; }
.tiers .t-name { display: block; font-size: var(--step-1); font-weight: 700; letter-spacing: -0.022em; line-height: 1.1; color: oklch(0.975 0.004 80); }
.tiers .t-pos { display: block; margin-top: 7px; font-size: var(--step--1); color: var(--ink-3); font-weight: 400; line-height: 1.5; max-width: 26ch; }
.tiers .t-price {
  display: block; margin-top: 16px;
  font-family: "Fragment Mono", ui-monospace, monospace;
  font-size: 1.02rem; color: var(--signal-tx); letter-spacing: -0.02em; font-weight: 400;
}
.tiers .t-unit { display: block; margin-top: 4px; font-size: 0.72rem; color: var(--ink-3); font-weight: 400; font-family: "Fragment Mono", ui-monospace, monospace; }

/* ------------------------------------------------------------------ code */

.code {
  background: oklch(0.168 0.007 68); color: var(--ink);
  border-radius: 3px; padding: 16px 18px; overflow-x: auto;
  font-family: "Fragment Mono", ui-monospace, monospace;
  font-size: 0.79rem; line-height: 1.75; margin: 0;
  border: 1px solid var(--rule-soft);
}
.code .c { color: var(--ink-3); }
.code .p { color: var(--signal-tx); }

/* Liste simple à puces discrètes, pour une énumération courte en prose. */
.notes-plain { list-style: none; margin: 0 0 1em; padding: 0; display: grid; gap: 6px; max-width: var(--measure); }
.notes-plain li { position: relative; padding-left: 18px; color: var(--ink-2); }
.notes-plain li::before { content: "·"; position: absolute; left: 4px; color: var(--signal-tx); }

/* ─── Menu de l'installeur ───────────────────────────────────────────────────────
   Reproduction du menu à navigation clavier dessiné par install.py. Le cadre est fait
   en CSS et non en caractères de filets : Fragment Mono ne les porte pas, et un repli
   de police disloquerait la boîte alignée au caractère près. */
.tui {
  background: oklch(0.150 0.006 68); border: 1px solid var(--rule);
  border-radius: 4px; overflow: hidden;
  font-family: "Fragment Mono", ui-monospace, monospace; font-size: 0.76rem;
  line-height: 1.6; color: var(--ink-2);
  box-shadow: 0 24px 48px -32px oklch(0 0 0 / 0.9);
}
.tui-h {
  padding: 15px 18px 13px; text-align: center;
  border-bottom: 1px solid var(--rule-soft); background: oklch(0.178 0.007 68);
}
.tui-h b { display: block; color: oklch(0.98 0.004 80); letter-spacing: 0.34em; font-weight: 400; }
.tui-h span { display: block; margin-top: 4px; color: var(--signal-tx); font-size: 0.72rem; }
/* La mesure de lecture des paragraphes ne s'applique pas dans une maquette de terminal :
   sans cela, le bandeau de navigation s'arrête au milieu du cadre. */
.tui p { max-width: none; margin: 0; }
.tui-q { padding: 15px 18px 4px; color: var(--ink); }
.tui-l { list-style: none; margin: 0; padding: 4px 0 8px; }
.tui-l li { padding: 4px 18px 4px 34px; position: relative; }
.tui-l b { font-weight: 400; color: var(--ink); }
.tui-l span { display: block; color: var(--ink-3); font-size: 0.72rem; }
.tui-l li.on { background: oklch(0.205 0.012 68); }
.tui-l li.on b { color: var(--signal-tx); }
.tui-l li.on::before {
  content: "\276F"; position: absolute; left: 16px; top: 4px; color: var(--signal-tx);
}
.tui-n {
  padding: 11px 18px; border-top: 1px solid var(--rule-soft);
  color: var(--ink-3); font-size: 0.72rem; background: oklch(0.178 0.007 68);
}

/* --------------------------------------------------- maquette de console */

.console {
  background: #18181b; border: 1px solid #36363f; border-radius: 4px;
  overflow: hidden; color: #e4e4e7;
  font-size: 13px; line-height: 1.5;
  box-shadow: 0 24px 48px -30px oklch(0 0 0 / 0.9);
}
.console-bar {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  padding: 9px 14px; background: #23232a; border-bottom: 1px solid #36363f;
}
.console-bar .cm { font-weight: 800; font-size: 0.8rem; letter-spacing: -0.03em; color: #fafafa; text-transform: uppercase; }
.console-bar .cm b { color: #f59e0b; }
.console-bar .ci { font-family: "Fragment Mono", monospace; font-size: 0.68rem; color: #a1a1aa; }
.console-bar .ci.on { color: #7ab98a; }
.console-bar .sp { margin-left: auto; }

.console-body { display: grid; grid-template-columns: repeat(auto-fit, minmax(215px, 1fr)); gap: 1px; background: #36363f; }
.cc { background: #23232a; padding: 13px 14px 14px; }
.cc .r1 { display: flex; align-items: center; gap: 8px; }
.cc .h { font-weight: 600; color: #fafafa; font-size: 0.86rem; letter-spacing: -0.01em; }
.cc .mode {
  margin-left: auto; font-family: "Fragment Mono", monospace; font-size: 0.62rem;
  padding: 2px 6px; border-radius: 3px; text-transform: uppercase; letter-spacing: 0.04em;
}
.cc .meta { margin-top: 9px; font-family: "Fragment Mono", monospace; font-size: 0.68rem; color: #a1a1aa; display: grid; gap: 3px; }
.cc .meta span b { color: #e4e4e7; font-weight: 400; }

.badge {
  font-family: "Fragment Mono", monospace; font-size: 0.63rem; letter-spacing: 0.03em;
  padding: 2px 7px; border-radius: 3px; text-transform: uppercase;
}
.b-run  { background: #1d2e23; color: #7ab98a; }
.b-warn { background: #2e2a1e; color: #c4a667; }
.b-stop { background: #322023; color: #d07a82; }
.b-unk  { background: #25272c; color: #8a8d94; }

.m-io   { background: oklch(0.72 0.06 250 / 16%); color: oklch(0.74 0.06 250); }
.m-mix  { background: oklch(0.78 0.05 20 / 16%);  color: oklch(0.78 0.05 20); }
.m-mv   { background: oklch(0.78 0.05 150 / 16%); color: oklch(0.78 0.05 150); }
.m-str  { background: oklch(0.78 0.05 80 / 16%);  color: oklch(0.80 0.05 80); }

.console-foot {
  padding: 10px 14px; background: #1c1c21; border-top: 1px solid #36363f;
  font-family: "Fragment Mono", monospace; font-size: 0.68rem; color: #a1a1aa;
  display: flex; gap: 8px; align-items: baseline;
}
.console-foot .lvl { color: #c4a667; }

.caption { margin-top: 11px; font-size: var(--step--1); color: var(--ink-3); max-width: 62ch; }

/* ------------------------------------------------------------------- svg */

.fig { width: 100%; height: auto; display: block; }
.fig text { font-family: "Fragment Mono", ui-monospace, monospace; }

/* ---------------------------------------------------------------- footer */

.foot { border-top: 1px solid var(--rule); padding-block: clamp(38px, 5vw, 62px) 30px; background: var(--paper-2); }
.foot-grid { display: grid; gap: clamp(24px, 3.4vw, 52px); grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); }
.foot h2 {
  font-family: "Fragment Mono", ui-monospace, monospace;
  font-size: 0.68rem; letter-spacing: 0.09em; text-transform: uppercase;
  color: var(--ink-3); font-weight: 400; margin-bottom: 12px;
}
.foot ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 7px; }
.foot ul a { text-decoration: none; color: var(--ink-2); font-size: 0.93rem; }
.foot ul a:hover { color: var(--signal-tx); }
.foot-bot {
  margin-top: clamp(30px, 4vw, 54px); padding-top: 18px; border-top: 1px solid var(--rule-soft);
  display: flex; flex-wrap: wrap; gap: 8px 22px;
  font-size: var(--step--1); color: var(--ink-3);
}

/* bandeau d'appel : le tally s'allume en bas de page */
.cta { padding-block: clamp(56px, 8vw, 110px); }
.cta h2 { font-size: var(--step-3); max-width: 20ch; font-variation-settings: "wdth" 94; letter-spacing: -0.03em; line-height: 1.1; }
.cta p { margin-top: 16px; max-width: 54ch; font-size: var(--step-1); line-height: 1.45; letter-spacing: -0.01em; }

/* --------------------------------------------------------------- reveals */

.rv { opacity: 0; transform: translateY(14px); }
.rv.in { opacity: 1; transform: none; transition: opacity 0.7s var(--ease), transform 0.7s var(--ease); }
/* Filet de sécurité : la tabulation peut atteindre un bloc que l'observateur n'a pas
   encore révélé. Sans ceci, le focus se pose sur du contenu à opacité nulle. */
.rv:focus-within { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  .rv, .rv.in { opacity: 1; transform: none; transition: none; }
}

:focus-visible { outline: 2px solid var(--signal); outline-offset: 3px; border-radius: 2px; }
/* main porte tabindex="-1" pour que le lien d'évitement pose vraiment le focus.
   Ce focus est programmatique : il ne doit pas dessiner de contour. */
main:focus { outline: none; }
/* Sur l'aplat ambre du bouton plein, un contour ambre se lit comme une bordure du
   bouton plutôt que comme un focus. On le passe en clair : il ne peut plus être
   confondu avec le bouton lui-même. */
.btn-solid:focus-visible { outline-color: var(--ink); }
.drench .btn-solid:focus-visible { outline-color: var(--on-signal); }
.drench :focus-visible { outline-color: var(--on-signal); }

.skip {
  position: absolute; left: -9999px; top: 0;
  background: var(--signal); color: var(--on-signal); padding: 10px 16px; z-index: 90;
  font-weight: 600;
}
.skip:focus { left: 8px; top: 8px; }

/* ─── Sommaire latéral ──────────────────────────────────────────────────────────
   Le même vocabulaire que le rail des sections : un trait vertical, une pastille
   ambre sur le chapitre courant. Il ne s'affiche qu'au-delà de 1500 px, là où la
   gouttière est assez large pour l'accueillir sans rogner le contenu. */
.toc { display: none; }

@media (min-width: 1500px) and (min-height: 560px) {
  .toc {
    display: block; position: fixed; z-index: 30;
    top: 50%; transform: translateY(-50%);
    left: max(18px, calc(50% - 640px - 172px));
    width: 156px;
    border-left: 1px solid var(--rule);
    padding: 4px 0 4px 18px;
  }
  .toc ol { list-style: none; margin: 0; padding: 0; display: grid; gap: 2px; }
  .toc a {
    display: grid; grid-template-columns: 26px 1fr; gap: 6px; align-items: baseline;
    padding: 5px 0; text-decoration: none; color: var(--ink-3);
    font-size: 0.8rem; line-height: 1.35; position: relative;
    transition: color 0.2s var(--ease);
  }
  .toc a .n {
    font-family: "Fragment Mono", ui-monospace, monospace; font-size: 0.7rem;
    opacity: 0.8;
  }
  .toc a:hover { color: var(--ink); }
  /* Chapitre courant : la pastille se pose SUR le rail, comme celle des sections. */
  .toc a[aria-current="true"] { color: var(--signal-tx); }
  .toc a[aria-current="true"]::before {
    content: ""; position: absolute; left: -22.5px; top: 11px;
    width: 9px; height: 9px; border-radius: 50%;
    background: var(--signal);
    box-shadow: 0 0 0 4px var(--paper), 0 0 12px -1px color-mix(in oklch, var(--signal) 70%, transparent);
  }
}

@media (prefers-reduced-motion: reduce) {
  .toc a { transition: none; }
}

/* ─── Captures d'écran du produit ───────────────────────────────────────────────
   Le chrome du navigateur est conservé dans l'image : il dit sans une phrase que le
   produit est une application web. Le cadre ci-dessous ne fait que le détacher du fond. */
.shot { margin: 0; }
.shot img {
  display: block; width: 100%; height: auto;
  border: 1px solid var(--rule); border-radius: 4px;
  background: var(--paper-2);
  box-shadow: 0 28px 56px -34px oklch(0 0 0 / 0.85);
}

/* ─── Agrandissement d'une capture ──────────────────────────────────────────────
   Le bouton et la modale sont posés par site.js : sans script, la capture reste une
   image normale plutôt qu'un contrôle qui ne répond pas. */
.shot-open {
  display: block; width: 100%; padding: 0; margin: 0;
  border: 0; background: none; cursor: zoom-in; position: relative;
  border-radius: 4px;
}
.shot-open .zoom {
  position: absolute; right: 10px; bottom: 10px;
  font-family: "Fragment Mono", ui-monospace, monospace; font-size: 0.7rem;
  color: var(--on-signal); background: var(--signal);
  padding: 4px 8px; border-radius: 3px; line-height: 1;
  opacity: 0; transition: opacity 0.2s var(--ease);
  pointer-events: none;
}
.shot-open:hover .zoom, .shot-open:focus-visible .zoom { opacity: 1; }
.shot-open:hover img { border-color: color-mix(in oklch, var(--signal) 45%, var(--rule)); }

.lightbox {
  padding: 0; border: 1px solid var(--rule); border-radius: 4px;
  background: var(--paper-2); color: var(--ink);
  max-width: 96vw; max-height: 96vh; width: auto;
}
.lightbox::backdrop { background: oklch(0.12 0.01 60 / 0.86); }
.lightbox img { display: block; max-width: 96vw; max-height: 88vh; width: auto; height: auto; }
.lightbox figcaption {
  padding: 12px 16px; font-size: 0.86rem; color: var(--ink-2);
  border-top: 1px solid var(--rule); max-width: 90ch;
}
.lightbox .close {
  position: absolute; top: 8px; right: 8px;
  font: inherit; font-size: 0.9rem; line-height: 1;
  background: var(--paper); color: var(--ink);
  border: 1px solid var(--rule); border-radius: 3px;
  padding: 7px 11px; cursor: pointer;
}
.lightbox .close:hover { background: var(--signal); color: var(--on-signal); border-color: var(--signal); }

@media (prefers-reduced-motion: reduce) {
  .shot-open .zoom { transition: none; }
}

/* Le sommaire est en position fixe (z-index 30). Le bandeau d'appel et le pied de page
   sont dans le flux : sans contexte d'empilement, ils passaient DESSOUS et le sommaire
   restait posé sur l'aplat ambre, illisible. On les remonte d'un cran — ils recouvrent
   alors le sommaire au fil du défilement, ce qui le retire exactement quand il ne sert
   plus. La barre de navigation (z-index 40) reste au-dessus de tout. */
.drench, .foot { position: relative; z-index: 31; }

/* Texte réservé aux lecteurs d'écran : présent dans l'arbre d'accessibilité, invisible à l'œil. */
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
}
/* Marqueur visible sur les liens sortants en prose et en pied de page. Pas sur les boutons :
   ils portent déjà une flèche, deux signes vaudraient bruit. */
.lnk[target="_blank"]::after,
.foot ul a[target="_blank"]::after { content: " ↗"; font-size: 0.85em; opacity: 0.7; }

/* ─── Feuille de route ──────────────────────────────────────────────────────────
   Même vocabulaire que le rail des sections : un trait vertical, une pastille par
   jalon. Le jalon courant est ambre plein, les suivants sont creux — et la date en
   toutes lettres dit la même chose, pour ne pas dépendre de la couleur. */
.rm { list-style: none; margin: 0; padding: 0; border-left: 1px solid var(--rule); }
.rm-item {
  position: relative; display: grid; gap: 4px 26px;
  grid-template-columns: 1fr; padding: 0 0 clamp(26px, 3.2vw, 40px) 30px;
}
@media (min-width: 720px) {
  .rm-item { grid-template-columns: 190px minmax(0, 1fr); }
}
.rm-item::before {
  content: ""; position: absolute; left: -5.5px; top: 6px;
  width: 11px; height: 11px; border-radius: 50%;
  background: var(--paper); border: 1px solid var(--rule);
}
.rm-now::before {
  background: var(--signal); border-color: var(--signal);
  box-shadow: 0 0 0 4px var(--paper), 0 0 14px -1px color-mix(in oklch, var(--signal) 65%, transparent);
}
.rm-next::before { background: var(--paper); border-color: var(--signal); }
.rm-done::before { background: var(--ink-3); border-color: var(--ink-3); }
.rm-when {
  font-family: "Fragment Mono", ui-monospace, monospace;
  font-size: 0.8rem; color: var(--signal-tx); padding-top: 2px;
}
.rm-later .rm-when, .rm-done .rm-when { color: var(--ink-3); }
.rm-body h3 { margin-bottom: 5px; }
.rm-body p { color: var(--ink-2); font-size: 0.97rem; max-width: 68ch; }
.rm-maj { margin-top: 6px; padding-left: 30px; }

/* ─── Mention « supporter DMF » ─────────────────────────────────────────────────
   Composée en typographie, pas en logo : aucun badge officiel n'est distribué sur la
   page des supporters, et reprendre une marque tierce sans conditions d'usage écrites
   n'est pas une décision de mise en page. Voir le commentaire dans content_fr.py. */
.dmf {
  display: inline-flex; align-items: center; gap: 12px;
  border: 1px solid color-mix(in oklch, var(--signal) 42%, var(--rule));
  border-radius: 3px; padding: 9px 14px;
  text-decoration: none; color: var(--ink-2); font-size: 0.86rem; line-height: 1.35;
  background: color-mix(in oklch, var(--signal) 6%, transparent);
  transition: border-color 0.2s var(--ease), color 0.2s var(--ease);
  max-width: 62ch;
}
.dmf:hover { border-color: var(--signal); color: var(--ink); }
/* Le badge officiel est blanc sur transparent : il vit tel quel sur le fond sombre, sans
   cartouche ni retouche — CC BY-ND interdit d'en faire une œuvre dérivée. */
.dmf img { height: 34px; width: auto; flex: none; display: block; }
.dmf-wrap { padding-block: 0 clamp(30px, 4.5vw, 56px); }
