/* ==========================================================================
   DRAKE DESIGN SYSTEM — Les Loups de Yela
   Implementation of DRAKE_DESIGN_SPEC.md + tokens.css
   Dark-only. All values normative. No hardcoded colors outside :root.
   ==========================================================================
   1.  Fonts
   2.  Tokens
   3.  Keyframes
   4.  Motion utilities
   5.  Base / reset
   6.  Grit layer (grain · scanlines · rivets · tape)
   7.  Layout primitives
   8.  Typography helpers
   9.  Buttons
   10. Forms
   11. Tabs / segmented
   12. Panels / cards
   13. Progress / meters / gauges
   14. Status / badges / pills
   15. Alerts / toasts
   16. Modal / drawer
   17. Accordion
   18. Tables
   19. Charts
   20. Terminal / log
   21. Loading / empty
   22. Navigation
   23. Site components (hero · timeline · gallery · grades · join · footer)
   24. Boot sequence
   25. Reduced motion
   ========================================================================== */

/* ── 1. FONTS ─────────────────────────────────────────────────────────── */
/* Polices auto-hébergées. L'@import vers fonts.googleapis.com a été
   supprimé : c'était la dernière requête tierce émise sans consentement.
   Les woff2 sont dans assets/fonts/, les @font-face dans assets/fonts.css. */
@import url('fonts.css');

/* ── 2. TOKENS ────────────────────────────────────────────────────────── */
:root{
  /* Brand / accent */
  --color-primary:        #FF3B30;
  --color-primary-hover:  #FF4D3A;
  --color-primary-active: #E63946;
  --color-accent:         #FF6B57;

  /* Semantic — never interchange with brand accent */
  --color-danger:         #B91C1C;
  --color-danger-fg:      #FF6B57;
  --color-warning:        #FFB020;
  --color-success:        #22C55E;
  --color-info:           #3B82F6;

  /* Surfaces L0→L4 */
  --surface-0:            #0A0A0A;
  --surface-1:            #0B0D0F;
  --surface-2:            #111417;
  --surface-3:            #1F2427;
  --surface-4:            #2A3035;
  --surface-scrim:        rgba(10,10,10,.78);

  /* Borders */
  --border-hairline:      #1F2427;
  --border-default:       #33383D;
  --border-strong:        #4A5157;
  --border-accent:        var(--color-primary);

  /* Text */
  --text-primary:         #E6E6E1;
  --text-secondary:       #A6A6A0;
  --text-dim:             #6B6B66;
  --text-disabled:        #6B6B66;
  --text-on-primary:      #0A0A0A;
  /* Boutons pleins rouges — traitement dédié, distinct de --color-primary.
     Texte blanc sur un rouge assombri : 4,93:1, conforme AA, là où le
     blanc sur #FF3B30 ne donnait que 3,55:1. Ce rouge est aussi celui de
     la rim light du personnage 3D, ce qui unifie les deux surfaces.
     Les badges, la sélection et le lightbox gardent --text-on-primary. */
  --btn-primary-fg:       #FFFFFF;
  --btn-primary-bg:       #E01020;
  --btn-primary-bg-hover: #E81828;

  /* Data-viz */
  --data-1:#FF3B30; --data-2:#FF6B57; --data-3:#FFB020; --data-4:#A6A6A0; --data-5:#22C55E;

  /* Glows */
  --glow-primary:         0 0 12px rgba(255,59,48,.45);
  --glow-primary-soft:    0 0 24px rgba(255,59,48,.18);
  --glow-success:         0 0 10px rgba(34,197,94,.45);
  --glow-warning:         0 0 10px rgba(255,176,32,.45);

  /* Decorative-only — NOT semantic. Brand texture, red/black so the
     yellow/black hazard pattern stays reserved for real warnings. */
  --deco-tape: repeating-linear-gradient(-45deg,
                 var(--color-primary) 0 10px, var(--surface-0) 10px 20px);
  --warn-tape: repeating-linear-gradient(-45deg,
                 var(--color-warning) 0 10px, var(--surface-0) 10px 20px);
  --deco-rivet: radial-gradient(circle at 35% 30%,
                 rgba(255,255,255,.18), rgba(0,0,0,.85) 65%);

  /* Spacing */
  --space-2:2px;  --space-4:4px;  --space-8:8px;  --space-12:12px; --space-16:16px;
  --space-24:24px; --space-32:32px; --space-48:48px; --space-64:64px; --space-96:96px;

  /* Radii & strokes */
  --radius-sm:4px; --radius-md:8px; --radius-lg:12px; --radius-pill:999px;
  --stroke-hairline:1px; --stroke-default:1px; --stroke-strong:2px;

  /* Typography */
  --font-display:'Orbitron', system-ui, sans-serif;
  --font-ui:'Rajdhani', system-ui, sans-serif;
  --font-mono:'Share Tech Mono', ui-monospace, monospace;
  --font-body:'Inter', system-ui, sans-serif;
  --font-prose:'IBM Plex Serif', Georgia, serif;   /* long-form novel only */

  --text-display:28px; --tracking-display:.12em; --lh-display:1.2;
  --text-heading:20px; --tracking-heading:.08em; --lh-heading:1.3;
  --text-subhead:16px; --tracking-subhead:.06em;
  --text-body:16px;    --lh-body:1.5;
  --text-label:13px;   --tracking-label:.10em;
  --text-data:14px;    --lh-data:1.4;
  --text-micro:11px;   --tracking-micro:.14em;

  /* Grid */
  --grid-max-width:1440px; --grid-columns:12; --grid-column:80px;
  --grid-gutter:24px; --grid-margin:32px;

  /* Motion */
  --dur-instant:80ms; --dur-fast:140ms; --dur-base:220ms; --dur-slow:380ms;
  --dur-deliberate:600ms; --dur-boot:1200ms; --dur-loop-slow:3s; --dur-loop-fast:1.2s;

  --ease-mech:cubic-bezier(.2,.8,.2,1);
  --ease-snap:cubic-bezier(.16,1,.3,1);
  --ease-in:cubic-bezier(.4,0,1,1);
  --ease-hold:cubic-bezier(.65,0,.35,1);
  --ease-step:steps(12,end);
  --ease-linear:linear;

  --stagger-step:40ms;
  --shift-xs:2px; --shift-sm:6px; --shift-md:12px; --shift-lg:24px;
}

/* ── 3. KEYFRAMES ─────────────────────────────────────────────────────── */
@keyframes drk-hud-in{0%{opacity:0;transform:translateY(var(--shift-sm)) scaleY(.96);clip-path:inset(0 0 100% 0)}55%{opacity:1;clip-path:inset(0 0 0 0)}100%{opacity:1;transform:translateY(0) scaleY(1);clip-path:inset(0 0 0 0)}}
@keyframes drk-wipe-in{0%{clip-path:inset(0 100% 0 0);opacity:.4}100%{clip-path:inset(0 0 0 0);opacity:1}}
@keyframes drk-wipe-down{0%{clip-path:inset(0 0 100% 0);opacity:.4}100%{clip-path:inset(0 0 0 0);opacity:1}}
@keyframes drk-scanline{0%{transform:translateY(-100%);opacity:0}10%{opacity:.55}90%{opacity:.55}100%{transform:translateY(1000%);opacity:0}}
@keyframes drk-flicker{0%,100%{opacity:1}8%{opacity:.3}12%{opacity:1}22%{opacity:.55}26%{opacity:1}}
@keyframes drk-glitch{0%,100%{transform:translateX(0);clip-path:inset(0 0 0 0)}20%{transform:translateX(-2px);clip-path:inset(20% 0 60% 0)}40%{transform:translateX(2px);clip-path:inset(60% 0 20% 0)}60%{transform:translateX(-1px);clip-path:inset(40% 0 40% 0)}80%{transform:translateX(1px);clip-path:inset(10% 0 75% 0)}}
@keyframes drk-pulse{0%,100%{box-shadow:0 0 0 0 currentColor;opacity:1}50%{box-shadow:0 0 0 5px transparent;opacity:.6}}
@keyframes drk-bar-fill{from{transform:scaleX(0)}to{transform:scaleX(1)}}
@keyframes drk-stripes{from{background-position:0 0}to{background-position:32px 0}}
@keyframes drk-segment-on{from{opacity:.15;transform:scaleY(.5)}to{opacity:1;transform:scaleY(1)}}
@keyframes drk-caret{0%,49%{opacity:1}50%,100%{opacity:0}}
@keyframes drk-typewriter{from{width:0}to{width:100%}}
@keyframes drk-sweep{from{transform:rotate(0)}to{transform:rotate(360deg)}}
@keyframes drk-marching{from{stroke-dashoffset:0}to{stroke-dashoffset:-16}}
@keyframes drk-draw{from{stroke-dashoffset:var(--path-length,1000)}to{stroke-dashoffset:0}}
@keyframes drk-modal-in{0%{opacity:0;transform:scaleY(.02) scaleX(.9)}40%{opacity:1;transform:scaleY(.02) scaleX(1)}100%{opacity:1;transform:scaleY(1) scaleX(1)}}
@keyframes drk-drawer-in{from{transform:translateX(100%)}to{transform:translateX(0)}}
@keyframes drk-toast-in{0%{opacity:0;transform:translateX(var(--shift-lg))}70%{opacity:1;transform:translateX(calc(var(--shift-xs) * -1))}100%{opacity:1;transform:translateX(0)}}
@keyframes drk-toast-timer{from{transform:scaleX(1)}to{transform:scaleX(0)}}
@keyframes drk-alarm{0%,100%{border-color:var(--color-danger);box-shadow:none}50%{border-color:var(--color-primary);box-shadow:var(--glow-primary)}}
@keyframes drk-spin{from{transform:rotate(0)}to{transform:rotate(360deg)}}
@keyframes drk-skeleton{from{background-position:-200% 0}to{background-position:200% 0}}
@keyframes drk-tick{0%{transform:translateY(0);opacity:1}40%{transform:translateY(-4px);opacity:0}41%{transform:translateY(4px);opacity:0}100%{transform:translateY(0);opacity:1}}
@keyframes drk-shake{0%,100%{transform:translateX(0)}20%{transform:translateX(-3px)}40%{transform:translateX(3px)}60%{transform:translateX(-2px)}80%{transform:translateX(2px)}}
@keyframes drk-boot-bar{from{transform:scaleX(0)}to{transform:scaleX(1)}}
@keyframes drk-fade-out{to{opacity:0;visibility:hidden}}
@keyframes drk-vu{from{opacity:.12;transform:scaleY(.35)}to{opacity:1;transform:scaleY(1)}}
@keyframes drk-onde{0%,100%{opacity:1;transform:translateX(0) scale(1)}50%{opacity:.45;transform:translateX(-1px) scale(.92)}}
@keyframes drk-scan-x{from{transform:translateX(-100%)}to{transform:translateX(200%)}}
@keyframes drk-hud-sweep{from{background-position:-150% 0}to{background-position:250% 0}}

/* ── 4. MOTION UTILITIES ──────────────────────────────────────────────── */
.drk-anim-hud     {animation:drk-hud-in var(--dur-slow) var(--ease-snap) both}
.drk-anim-wipe    {animation:drk-wipe-in var(--dur-base) var(--ease-mech) both}
.drk-anim-flicker {animation:drk-flicker var(--dur-deliberate) var(--ease-linear) both}
.drk-anim-pulse   {animation:drk-pulse var(--dur-loop-fast) var(--ease-hold) infinite}
.drk-anim-alarm   {animation:drk-alarm var(--dur-loop-slow) var(--ease-hold) infinite}
.drk-anim-glitch  {animation:drk-glitch 400ms var(--ease-hold) 1 both}

.drk-stagger>*{animation:drk-hud-in var(--dur-slow) var(--ease-snap) both}
.drk-stagger>*:nth-child(1){animation-delay:calc(var(--stagger-step)*0)}
.drk-stagger>*:nth-child(2){animation-delay:calc(var(--stagger-step)*1)}
.drk-stagger>*:nth-child(3){animation-delay:calc(var(--stagger-step)*2)}
.drk-stagger>*:nth-child(4){animation-delay:calc(var(--stagger-step)*3)}
.drk-stagger>*:nth-child(5){animation-delay:calc(var(--stagger-step)*4)}
.drk-stagger>*:nth-child(6){animation-delay:calc(var(--stagger-step)*5)}
.drk-stagger>*:nth-child(7){animation-delay:calc(var(--stagger-step)*6)}
.drk-stagger>*:nth-child(8){animation-delay:calc(var(--stagger-step)*7)}
.drk-stagger>*:nth-child(n+9){animation-delay:calc(var(--stagger-step)*8)}

.drk-interactive{transition:
  background-color var(--dur-fast) var(--ease-mech),
  border-color var(--dur-fast) var(--ease-mech),
  color var(--dur-fast) var(--ease-mech),
  box-shadow var(--dur-fast) var(--ease-mech),
  transform var(--dur-instant) var(--ease-mech)}

/* Reveal-on-scroll — JS adds .is-in */
.drk-reveal{opacity:0;transform:translateY(var(--shift-md));
  transition:opacity var(--dur-slow) var(--ease-snap),transform var(--dur-slow) var(--ease-snap)}
.drk-reveal.is-in{opacity:1;transform:none}

/* ── 5. BASE ──────────────────────────────────────────────────────────── */
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
html{background:var(--surface-0);color:var(--text-primary);
  font-family:var(--font-body);font-size:var(--text-body);line-height:var(--lh-body);
  scroll-behavior:smooth;overflow-x:hidden;-webkit-font-smoothing:antialiased}
body{background:var(--surface-0);min-height:100vh;overflow-x:hidden;position:relative;
  background-image:radial-gradient(circle at 50% 0%,rgba(255,59,48,.05),transparent 60%)}

::-webkit-scrollbar{width:8px;height:8px}
::-webkit-scrollbar-track{background:var(--surface-0)}
::-webkit-scrollbar-thumb{background:var(--surface-3);border-radius:var(--radius-sm)}
::-webkit-scrollbar-thumb:hover{background:var(--color-primary)}
::selection{background:var(--color-primary);color:var(--text-on-primary)}

a{color:var(--color-primary);text-decoration:none;transition:color var(--dur-fast) var(--ease-mech)}
a:hover{color:var(--color-accent)}
:focus-visible{outline:var(--stroke-strong) solid var(--color-primary);outline-offset:2px}

/* ── 6. GRIT LAYER ────────────────────────────────────────────────────── */
.drk-grain{position:fixed;inset:0;z-index:2;pointer-events:none;opacity:.05;
  background-image:url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size:128px 128px}
.drk-crt{position:fixed;inset:0;z-index:3;pointer-events:none;opacity:.5;mix-blend-mode:multiply;
  background:repeating-linear-gradient(0deg,transparent 0 2px,rgba(0,0,0,.20) 2px 3px)}
.drk-vignette{position:fixed;inset:0;z-index:2;pointer-events:none;
  background:radial-gradient(ellipse at 50% 50%,transparent 55%,rgba(0,0,0,.55) 100%)}

/* Decorative brand tape (red/black) */
.drk-tape{height:var(--space-4);background:var(--deco-tape);opacity:.5}
.drk-tape--warn{background:var(--warn-tape);opacity:.7}

/* Rivets */
.drk-rivet{position:absolute;width:6px;height:6px;border-radius:50%;
  background:var(--deco-rivet);box-shadow:inset 0 0 1px rgba(0,0,0,.9);pointer-events:none;z-index:4}
.drk-rivet.tl{top:var(--space-8);left:var(--space-8)}
.drk-rivet.tr{top:var(--space-8);right:var(--space-8)}
.drk-rivet.bl{bottom:var(--space-8);left:var(--space-8)}
.drk-rivet.br{bottom:var(--space-8);right:var(--space-8)}

/* Scroll progress */
.drk-progress{position:fixed;top:0;left:0;height:var(--stroke-strong);width:0;z-index:60;
  background:var(--color-primary);box-shadow:var(--glow-primary)}

/* ── 7. LAYOUT ────────────────────────────────────────────────────────── */
.wrap{max-width:var(--grid-max-width);margin:0 auto;padding:0 var(--grid-margin)}
.sec{position:relative;z-index:10;padding:var(--space-96) 0;border-bottom:var(--stroke-hairline) solid var(--border-hairline)}
.sec--alt{background:var(--surface-1)}
.row{display:flex;flex-wrap:wrap;gap:var(--space-12);align-items:center}
.grid-auto{display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));gap:var(--space-24)}
.grid-auto--wide{grid-template-columns:repeat(auto-fit,minmax(340px,1fr))}
.grid-auto--narrow{grid-template-columns:repeat(auto-fit,minmax(220px,1fr))}

/* Section header */
.sec-head{display:flex;align-items:baseline;gap:var(--space-16);margin-bottom:var(--space-24);flex-wrap:wrap}
.sec-id{font-family:var(--font-mono);font-size:var(--text-data);color:var(--color-primary);white-space:nowrap}
.sec-id::before{content:'['}.sec-id::after{content:']'}
.sec-kicker{font-family:var(--font-ui);font-weight:600;font-size:var(--text-micro);
  letter-spacing:var(--tracking-micro);text-transform:uppercase;color:var(--text-secondary)}
.sec-rule{flex:1;height:var(--stroke-hairline);background:linear-gradient(90deg,var(--border-default),transparent);min-width:40px}
.sec-title{font-family:var(--font-display);font-weight:700;font-size:var(--text-display);
  letter-spacing:var(--tracking-display);line-height:var(--lh-display);text-transform:uppercase;
  color:var(--text-primary);margin-bottom:var(--space-16)}
.sec-title em{font-style:normal;color:var(--color-primary);text-shadow:var(--glow-primary-soft)}
.sec-intro{font-family:var(--font-body);font-size:var(--text-body);color:var(--text-secondary);
  max-width:72ch;line-height:var(--lh-body);margin-bottom:var(--space-32)}

/* ── 8. TYPOGRAPHY HELPERS ────────────────────────────────────────────── */
.h-display{font-family:var(--font-display);font-weight:700;font-size:var(--text-display);
  letter-spacing:var(--tracking-display);line-height:var(--lh-display);text-transform:uppercase}
.h-heading{font-family:var(--font-display);font-weight:500;font-size:var(--text-heading);
  letter-spacing:var(--tracking-heading);line-height:var(--lh-heading);text-transform:uppercase}
.lbl{font-family:var(--font-ui);font-weight:600;font-size:var(--text-label);
  letter-spacing:var(--tracking-label);text-transform:uppercase;color:var(--text-secondary)}
.micro{font-family:var(--font-ui);font-weight:500;font-size:var(--text-micro);
  letter-spacing:var(--tracking-micro);text-transform:uppercase;color:var(--text-secondary)}
.mono{font-family:var(--font-mono);font-size:var(--text-data);line-height:var(--lh-data)}
.val{font-family:var(--font-mono);font-size:var(--text-data);color:var(--color-primary)}
.dim{color:var(--text-dim)}
/* Réservé aux lecteurs d'écran : retiré de l'affichage, jamais du DOM. */
.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;
  clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0}

/* ── 9. BUTTONS ───────────────────────────────────────────────────────── */
.btn{font-family:var(--font-ui);font-weight:600;font-size:var(--text-label);
  letter-spacing:var(--tracking-label);text-transform:uppercase;
  height:36px;padding:0 var(--space-24);border-radius:var(--radius-sm);
  cursor:pointer;position:relative;display:inline-flex;align-items:center;justify-content:center;
  gap:var(--space-8);border:var(--stroke-default) solid transparent;background:transparent;
  color:var(--text-primary);text-decoration:none;white-space:nowrap;
  transition:background-color var(--dur-fast) var(--ease-mech),
             border-color var(--dur-fast) var(--ease-mech),
             color var(--dur-fast) var(--ease-mech),
             box-shadow var(--dur-fast) var(--ease-mech),
             transform var(--dur-instant) var(--ease-mech)}
.btn:active{transform:translateY(1px)}
.btn--sm{height:28px;padding:0 var(--space-16);font-size:var(--text-micro)}
.btn--lg{height:44px;padding:0 var(--space-32)}
.btn--icon{width:32px;height:32px;padding:0}

.btn--primary{background:var(--btn-primary-bg);color:var(--btn-primary-fg)}
.btn--primary:hover{background:var(--btn-primary-bg-hover);box-shadow:var(--glow-primary);color:var(--btn-primary-fg)}
.btn--primary:active{background:var(--color-primary-active)}
.btn--secondary{border-color:var(--border-default);color:var(--text-primary)}
.btn--secondary:hover{border-color:var(--color-primary);color:var(--color-accent);box-shadow:var(--glow-primary-soft)}
.btn--ghost{color:var(--text-secondary)}
.btn--ghost:hover{color:var(--text-primary);background:var(--surface-2)}
.btn--destructive{border-color:var(--color-danger);color:var(--color-danger-fg)}
.btn--destructive:hover{background:rgba(185,28,28,.18);box-shadow:0 0 12px rgba(185,28,28,.4)}
.btn[disabled],.btn.is-disabled{color:var(--text-disabled);border-color:var(--border-hairline);
  background:var(--surface-2);cursor:not-allowed;pointer-events:none}
.btn.is-loading{color:transparent!important}
.btn.is-loading::after{content:'';position:absolute;width:14px;height:14px;border-radius:50%;
  border:2px solid rgba(255,255,255,.2);border-top-color:var(--color-primary);
  animation:drk-spin 900ms var(--ease-linear) infinite}
.btn--primary.is-loading::after{border-color:rgba(255,255,255,.35);border-top-color:var(--btn-primary-fg)}

/* ── 10. FORMS ────────────────────────────────────────────────────────── */
.field{margin-bottom:var(--space-16)}
.field>.lbl{display:block;margin-bottom:var(--space-8)}
.inp-wrap{position:relative}
.inp-wrap::after{content:'';position:absolute;left:0;right:0;bottom:0;height:var(--stroke-hairline);
  background:var(--color-primary);transform:scaleX(0);transform-origin:center;
  transition:transform var(--dur-base) var(--ease-snap)}
.inp-wrap:focus-within::after{transform:scaleX(1)}
.inp,input[type=text].inp,input[type=url].inp,input[type=password].inp,textarea.inp,select.inp{
  width:100%;height:40px;background:var(--surface-2);color:var(--text-primary);
  border:var(--stroke-default) solid var(--border-default);border-radius:var(--radius-sm);
  padding:0 var(--space-12);font-family:var(--font-mono);font-size:var(--text-data);outline:none;
  transition:border-color var(--dur-fast) var(--ease-mech),background-color var(--dur-fast) var(--ease-mech)}
textarea.inp{height:auto;min-height:96px;padding:var(--space-12);line-height:var(--lh-body);resize:vertical}
.inp::placeholder{color:var(--text-dim)}
.inp:focus{border-color:var(--color-primary);background:var(--surface-1)}
.inp:disabled{opacity:.5;cursor:not-allowed}
.inp.is-error{border-color:var(--color-danger-fg);animation:drk-shake 180ms var(--ease-hold)}
.hint{min-height:18px;font-family:var(--font-ui);font-size:12px;letter-spacing:.06em;
  color:var(--text-secondary);margin-top:var(--space-4)}
.hint.is-error{color:var(--color-danger-fg)}
.hint.is-ok{color:var(--color-success)}

/* Checkbox / radio / toggle */
.opt{display:flex;align-items:center;gap:var(--space-12);cursor:pointer;padding:var(--space-4) 0;
  font-family:var(--font-ui);font-size:var(--text-label);letter-spacing:.08em;text-transform:uppercase;
  color:var(--text-secondary);transition:color var(--dur-fast) var(--ease-mech)}
.opt:hover{color:var(--text-primary)}
.opt-box{width:18px;height:18px;border:var(--stroke-default) solid var(--border-default);
  border-radius:3px;display:grid;place-items:center;flex:none;
  transition:border-color var(--dur-instant) var(--ease-mech),background-color var(--dur-instant) var(--ease-mech)}
.opt.is-on .opt-box{border-color:var(--color-primary);background:rgba(255,59,48,.12)}
.opt-box svg{width:12px;height:12px;stroke:var(--color-primary);stroke-width:2.4;fill:none;
  stroke-linecap:square;stroke-dasharray:20;stroke-dashoffset:20;
  transition:stroke-dashoffset 140ms var(--ease-snap)}
.opt.is-on .opt-box svg{stroke-dashoffset:0}
.opt-dot{width:18px;height:18px;border:var(--stroke-default) solid var(--border-default);border-radius:50%;
  display:grid;place-items:center;flex:none;transition:border-color var(--dur-instant) var(--ease-mech)}
.opt-dot i{width:8px;height:8px;border-radius:50%;background:var(--color-primary);
  transform:scale(0);transition:transform var(--dur-instant) var(--ease-snap)}
.opt.is-on .opt-dot{border-color:var(--color-primary)}
.opt.is-on .opt-dot i{transform:scale(1)}
.sw{width:46px;height:24px;border:var(--stroke-default) solid var(--border-default);
  border-radius:var(--radius-sm);background:var(--surface-2);position:relative;flex:none;cursor:pointer;
  transition:border-color var(--dur-fast) var(--ease-mech),background-color var(--dur-fast) var(--ease-mech),box-shadow var(--dur-base) var(--ease-mech)}
.sw i{position:absolute;top:3px;left:3px;width:18px;height:16px;border-radius:2px;background:var(--text-dim);
  transition:transform var(--dur-base) var(--ease-mech),background-color var(--dur-fast) var(--ease-mech)}
.sw.is-on{border-color:var(--color-primary);background:rgba(255,59,48,.1);box-shadow:var(--glow-primary)}
.sw.is-on i{transform:translateX(22px);background:var(--color-primary)}

/* ── 11. TABS ─────────────────────────────────────────────────────────── */
.tabs{position:relative;display:flex;gap:var(--space-4);border-bottom:var(--stroke-hairline) solid var(--border-hairline)}
.tab{font-family:var(--font-ui);font-weight:600;font-size:12px;letter-spacing:.12em;text-transform:uppercase;
  background:none;border:0;color:var(--text-dim);cursor:pointer;padding:10px var(--space-16);
  transition:color var(--dur-fast) var(--ease-mech)}
.tab:hover{color:var(--text-secondary)}
.tab.is-on{color:var(--color-primary)}
.tab-ink{position:absolute;bottom:-1px;left:0;width:0;height:var(--stroke-strong);
  background:var(--color-primary);box-shadow:var(--glow-primary);
  transition:transform var(--dur-base) var(--ease-mech),width var(--dur-base) var(--ease-mech)}
.tab-body{padding-top:var(--space-16);color:var(--text-secondary)}
.tab-body.is-anim{animation:drk-wipe-in var(--dur-base) var(--ease-mech) 60ms both}

/* ── 12. PANELS / CARDS ───────────────────────────────────────────────── */
.panel{position:relative;background:var(--surface-1);
  border:var(--stroke-hairline) solid var(--border-hairline);border-radius:var(--radius-md);
  padding:var(--space-24);overflow:hidden}
.panel::before{content:'';position:absolute;left:0;top:var(--space-24);
  width:var(--stroke-strong);height:18px;background:var(--color-primary)}
.panel>.panel-title{font-family:var(--font-display);font-weight:500;font-size:15px;
  letter-spacing:var(--tracking-label);text-transform:uppercase;color:var(--text-secondary);
  padding-left:var(--space-12);margin-bottom:var(--space-16)}
.panel--flush{padding:0}
.panel--flush::before{display:none}
.panel--l2{background:var(--surface-2)}
.panel--l3{background:var(--surface-3)}

/* Clickable card */
.card{position:relative;background:var(--surface-1);
  border:var(--stroke-hairline) solid var(--border-hairline);border-radius:var(--radius-md);
  overflow:hidden;display:flex;flex-direction:column;
  transition:border-color var(--dur-fast) var(--ease-mech),
             transform var(--dur-fast) var(--ease-mech),
             box-shadow var(--dur-fast) var(--ease-mech),
             background-color var(--dur-fast) var(--ease-mech)}
.card:hover{border-color:var(--border-accent);transform:translateY(-2px);
  box-shadow:var(--glow-primary-soft);background:var(--surface-2)}
.card-head{display:flex;align-items:center;gap:var(--space-8);
  padding:var(--space-8) var(--space-12);background:var(--surface-2);
  border-bottom:var(--stroke-hairline) solid var(--border-hairline)}
.card-head .sp{flex:1}
.card-code{font-family:var(--font-mono);font-size:12px;color:var(--color-primary)}
.card-code::before{content:'['}.card-code::after{content:']'}
.card-body{padding:var(--space-16);flex:1}
.card-title{font-family:var(--font-display);font-weight:500;font-size:var(--text-subhead);
  letter-spacing:var(--tracking-subhead);text-transform:uppercase;color:var(--text-primary);
  line-height:var(--lh-heading);margin-bottom:var(--space-4)}
.card-title em{display:block;font-style:normal;font-family:var(--font-ui);font-weight:500;
  font-size:var(--text-micro);letter-spacing:var(--tracking-micro);color:var(--color-primary);margin-top:var(--space-4)}
.card-text{font-family:var(--font-body);font-size:14px;color:var(--text-secondary);
  line-height:var(--lh-body);margin-top:var(--space-8)}
.card-foot{padding:var(--space-8) var(--space-12);background:var(--surface-2);
  border-top:var(--stroke-hairline) solid var(--border-hairline);
  font-family:var(--font-ui);font-size:var(--text-micro);letter-spacing:var(--tracking-micro);
  text-transform:uppercase;color:var(--text-dim);display:flex;align-items:center;gap:var(--space-8)}
.card-insignia{width:80px;height:80px;object-fit:contain;float:right;margin:0 0 var(--space-8) var(--space-12);
  transition:filter var(--dur-base) var(--ease-mech)}
.card:hover .card-insignia{filter:drop-shadow(0 0 10px rgba(255,59,48,.5))}
.card-tags{display:flex;flex-wrap:wrap;gap:var(--space-4);margin-top:var(--space-12)}

/* Decorative panel scanline (one per screen per spec) */
.scan-layer{position:absolute;left:0;right:0;height:var(--stroke-strong);pointer-events:none;z-index:5;
  background:linear-gradient(90deg,transparent,rgba(255,59,48,.55),transparent);
  animation:drk-scanline 8s var(--ease-linear) infinite}

/* ── 13. PROGRESS / METERS / GAUGES ───────────────────────────────────── */
.bar-row{margin-bottom:var(--space-16)}
.bar-head{display:flex;justify-content:space-between;align-items:baseline;margin-bottom:var(--space-4)}
.bar{height:8px;background:var(--surface-3);border-radius:2px;overflow:hidden}
.bar>i{display:block;height:100%;background:var(--color-primary);transform-origin:left;transform:scaleX(0);
  transition:transform var(--dur-deliberate) var(--ease-mech),background-color var(--dur-base) var(--ease-mech)}
.bar.is-in>i,.is-in .bar>i{transform:scaleX(var(--v,.5))}
.bar>i.is-warn{background:var(--color-warning)}
.bar>i.is-danger{background:var(--color-danger)}
.bar--indeterminate>i{transform:scaleX(1);
  background:repeating-linear-gradient(45deg,var(--color-primary) 0 8px,rgba(255,59,48,.25) 8px 16px);
  background-size:32px 32px;animation:drk-stripes 700ms var(--ease-linear) infinite}

.seg{display:flex;gap:3px;height:14px}
.seg>s{flex:1;background:var(--color-primary);border-radius:1px;opacity:.12;
  transform:scaleY(.5);transform-origin:bottom;text-decoration:none}
.is-in .seg>s.is-on{animation:drk-segment-on 200ms var(--ease-snap) both}
.is-in .seg>s.is-on:nth-child(1){animation-delay:0ms}
.is-in .seg>s.is-on:nth-child(2){animation-delay:25ms}
.is-in .seg>s.is-on:nth-child(3){animation-delay:50ms}
.is-in .seg>s.is-on:nth-child(4){animation-delay:75ms}
.is-in .seg>s.is-on:nth-child(5){animation-delay:100ms}
.is-in .seg>s.is-on:nth-child(6){animation-delay:125ms}
.is-in .seg>s.is-on:nth-child(7){animation-delay:150ms}
.is-in .seg>s.is-on:nth-child(8){animation-delay:175ms}
.is-in .seg>s.is-on:nth-child(9){animation-delay:200ms}
.is-in .seg>s.is-on:nth-child(10){animation-delay:225ms}
.is-in .seg>s.is-on:nth-child(11){animation-delay:250ms}
.is-in .seg>s.is-on:nth-child(12){animation-delay:275ms}
.is-in .seg>s.is-on:nth-child(n+13){animation-delay:300ms}

/* Numeric readout */
.readout{font-family:var(--font-display);font-weight:900;font-size:clamp(28px,4vw,44px);
  letter-spacing:.02em;line-height:1;color:var(--color-primary);text-shadow:var(--glow-primary-soft)}
.readout.is-tick{animation:drk-tick var(--dur-base) var(--ease-mech)}
.readout--sm{font-size:20px}

/* Stat block */
.stat{position:relative;background:var(--surface-1);
  border:var(--stroke-hairline) solid var(--border-hairline);border-radius:var(--radius-md);overflow:hidden;
  transition:border-color var(--dur-fast) var(--ease-mech),background-color var(--dur-fast) var(--ease-mech)}
.stat:hover{border-color:var(--border-accent);background:var(--surface-2)}
.stat-body{padding:var(--space-16)}
.stat-lbl{display:block;font-family:var(--font-ui);font-weight:600;font-size:var(--text-micro);
  letter-spacing:var(--tracking-micro);text-transform:uppercase;color:var(--text-secondary);margin-top:var(--space-8)}
.stat-sub{display:block;font-family:var(--font-mono);font-size:12px;color:var(--text-dim);margin-top:var(--space-2)}

/* Traitement console des quatre cartes de chiffres.
   Elles étaient un aplat rouge : un grand nombre rouge, une jauge pleine
   rouge, douze blocs rouges — et cela quatre fois de suite. À cette dose,
   l'accent cesse d'être un accent et devient un fond.

   Rien n'est remplacé : .readout, .bar et .seg restent les composants du
   design system, qui servent aussi au HUD du hero et aux consoles de
   l'armurerie. Ils sont seulement rhabillés ICI, sous .stat.

   Le principe : le rouge marque le NIVEAU ATTEINT, pas la surface. */

/* Le nombre revient à l'os — c'est une donnée, pas une alarme. Le rouge
   se réduit à un tiret sous le chiffre, comme un souligné d'instrument. */
.stat .readout{color:var(--text-primary);text-shadow:none;
  display:inline-block;position:relative;padding-bottom:var(--space-8)}
.stat .readout::after{content:'';position:absolute;left:0;bottom:0;
  width:28px;height:var(--stroke-strong);background:var(--color-primary);
  box-shadow:var(--glow-primary-soft)}

/* Deux jauges empilées pour la même valeur, c'était une de trop : la
   barre et les segments disaient la même chose, en rouge, l'une sous
   l'autre. Elles se partagent désormais le travail — la barre devient un
   filet d'activité, mince et animé ; les témoins portent le niveau. */
.stat .bar{position:relative;height:3px;background:var(--surface-3)}
.stat .bar>i{background:var(--color-primary);opacity:.45}

/* Un balayage lent traverse la jauge : la console respire au lieu de
   poser une image fixe. Il est clipé par l'overflow de .bar. */
.stat .bar::after{content:'';position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(90deg,transparent 42%,rgba(255,59,48,.30) 50%,transparent 58%);
  transform:translateX(-100%);
  animation:drk-scan-x 5.5s var(--ease-linear) infinite}

/* Les segments deviennent un rang de témoins : éteints, ils gardent leur
   contour ; allumés, ils restent sourds. */
.stat .seg{height:18px;gap:5px}
.stat .seg>s{background:transparent;opacity:1;
  border:var(--stroke-hairline) solid var(--border-default)}
.stat .seg>s.is-on{background:rgba(255,59,48,.34);border-color:rgba(255,59,48,.42)}

/* Le dernier témoin allumé — celui que suit un éteint — est le niveau
   courant : lui seul brille, et il clignote. C'est ce qui fait qu'une
   carte a l'air branchée sur quelque chose. */
.stat .seg>s.is-on:has(+ s:not(.is-on)){
  background:var(--color-primary);border-color:var(--color-primary);
  box-shadow:var(--glow-primary);
  animation:drk-pulse 1.8s var(--ease-hold) infinite}

/* Le libellé porte désormais un exposant (4e trimestre) : on l'empêche de
   décaler la ligne de base. */
.stat-lbl sup{font-size:.75em;line-height:0;vertical-align:super}

/* ── 14. STATUS / BADGES / PILLS ──────────────────────────────────────── */
.st{display:inline-flex;align-items:center;gap:var(--space-8);font-family:var(--font-ui);
  font-size:12px;letter-spacing:.12em;text-transform:uppercase;color:var(--text-secondary)}
.st>b{width:8px;height:8px;border-radius:50%;display:block;flex:none}
.st--on>b{background:var(--color-success);color:var(--color-success);animation:drk-pulse var(--dur-loop-fast) var(--ease-hold) infinite}
.st--warn>b{background:var(--color-warning);color:var(--color-warning);animation:drk-pulse var(--dur-loop-fast) var(--ease-hold) infinite}
.st--error>b{background:var(--color-primary);color:var(--color-primary);animation:drk-pulse .6s var(--ease-hold) infinite}
.st--off>b{background:var(--text-dim)}

.pill{display:inline-flex;align-items:center;gap:var(--space-4);font-family:var(--font-ui);
  font-size:var(--text-micro);letter-spacing:.12em;text-transform:uppercase;
  padding:var(--space-4) 10px;border-radius:var(--radius-sm);
  border:var(--stroke-default) solid var(--border-default);color:var(--text-secondary);
  background:transparent;white-space:nowrap;
  transition:transform var(--dur-fast) var(--ease-mech),box-shadow var(--dur-fast) var(--ease-mech),
             border-color var(--dur-fast) var(--ease-mech),color var(--dur-fast) var(--ease-mech)}
.pill:hover{transform:translateY(-1px)}
.pill--on{border-color:var(--color-success);color:var(--color-success)}
.pill--warn{border-color:var(--color-warning);color:var(--color-warning)}
.pill--error{border-color:var(--color-primary);color:var(--color-primary);box-shadow:var(--glow-primary-soft)}
.pill--accent{border-color:var(--color-primary);color:var(--color-primary)}
.pill--danger{border-color:var(--color-danger);color:var(--color-danger-fg)}

.badge{display:inline-flex;align-items:center;justify-content:center;min-width:20px;height:20px;
  padding:0 var(--space-4);border-radius:var(--radius-sm);background:var(--color-primary);
  color:var(--text-on-primary);font-family:var(--font-ui);font-weight:700;font-size:var(--text-micro);
  letter-spacing:.06em;animation:drk-hud-in var(--dur-fast) var(--ease-snap) both}

/* ── 15. ALERTS / TOASTS ──────────────────────────────────────────────── */
.alert{display:flex;gap:var(--space-12);align-items:flex-start;
  padding:var(--space-12) var(--space-16);border:var(--stroke-default) solid var(--border-default);
  border-radius:var(--radius-sm);margin-bottom:var(--space-12);background:var(--surface-2)}
.alert-title{display:block;font-family:var(--font-ui);font-weight:700;font-size:12px;
  letter-spacing:.12em;text-transform:uppercase;margin-bottom:var(--space-2)}
.alert p{margin:0;color:var(--text-secondary);font-size:13px}
.alert--critical{border-color:var(--color-danger);animation:drk-alarm var(--dur-loop-slow) var(--ease-hold) infinite}
.alert--critical .alert-title{color:var(--color-primary)}
.alert--warn{border-color:rgba(255,176,32,.5)}
.alert--warn .alert-title{color:var(--color-warning)}
.alert--ok{border-color:rgba(34,197,94,.5)}
.alert--ok .alert-title{color:var(--color-success)}
.alert--info{border-color:rgba(59,130,246,.5)}
.alert--info .alert-title{color:var(--color-info)}

.toast-host{position:fixed;right:var(--space-24);bottom:var(--space-24);display:flex;
  flex-direction:column;gap:var(--space-12);z-index:70;pointer-events:none}
.toast{min-width:280px;max-width:380px;background:var(--surface-3);
  border:var(--stroke-default) solid var(--border-default);border-radius:var(--radius-sm);
  padding:var(--space-12) var(--space-16);position:relative;overflow:hidden;pointer-events:auto;
  animation:drk-toast-in var(--dur-base) var(--ease-snap) both}
.toast.is-out{animation:drk-toast-in var(--dur-fast) var(--ease-in) reverse both}
.toast-title{font-family:var(--font-ui);font-weight:700;font-size:12px;letter-spacing:.12em;
  text-transform:uppercase;color:var(--color-success)}
.toast--error .toast-title{color:var(--color-danger-fg)}
.toast--warn .toast-title{color:var(--color-warning)}
.toast-msg{font-size:13px;color:var(--text-secondary)}
.toast-timer{position:absolute;left:0;bottom:0;height:var(--stroke-strong);width:100%;
  background:var(--color-primary);transform-origin:left;animation:drk-toast-timer 5s var(--ease-linear) forwards}
.toast:hover .toast-timer{animation-play-state:paused}

/* ── 16. MODAL / DRAWER ───────────────────────────────────────────────── */
.scrim{position:fixed;inset:0;background:var(--surface-scrim);backdrop-filter:blur(2px);
  display:grid;place-items:center;z-index:80;opacity:0;padding:var(--space-24);
  transition:opacity var(--dur-base) var(--ease-mech)}
.scrim.is-show{opacity:1}
.scrim[hidden]{display:none}
.modal{width:min(480px,92vw);background:var(--surface-4);
  border:var(--stroke-default) solid var(--color-primary);border-radius:var(--radius-lg);
  padding:var(--space-32);animation:drk-modal-in var(--dur-deliberate) var(--ease-snap) both}
.modal-title{font-family:var(--font-display);font-weight:500;font-size:14px;letter-spacing:.14em;
  text-transform:uppercase;color:var(--color-primary);margin-bottom:var(--space-16)}
.modal p{color:var(--text-secondary);font-size:14px;margin-bottom:var(--space-24)}
.modal-actions{display:flex;gap:var(--space-12);justify-content:flex-end}

.drawer{position:fixed;top:0;right:0;bottom:0;width:min(420px,92vw);background:var(--surface-2);
  border-left:var(--stroke-default) solid var(--border-default);z-index:85;
  animation:drk-drawer-in var(--dur-deliberate) var(--ease-mech) both;overflow-y:auto;padding:var(--space-24)}

/* ── 17. ACCORDION ────────────────────────────────────────────────────── */
.acc{border:var(--stroke-hairline) solid var(--border-hairline);border-radius:var(--radius-sm);
  margin-bottom:var(--space-8);background:var(--surface-2);overflow:hidden}
.acc>button{width:100%;display:flex;align-items:center;justify-content:space-between;
  background:none;border:0;border-left:var(--stroke-strong) solid transparent;color:var(--text-primary);
  cursor:pointer;padding:var(--space-12) var(--space-16);font-family:var(--font-ui);font-weight:600;
  font-size:12px;letter-spacing:.12em;text-transform:uppercase;
  transition:border-color var(--dur-fast) var(--ease-mech),background-color var(--dur-fast) var(--ease-mech),color var(--dur-fast) var(--ease-mech)}
.acc>button:hover{background:var(--surface-3)}
.acc.is-on>button{border-left-color:var(--color-primary);color:var(--color-primary)}
.acc-chev{transition:transform var(--dur-base) var(--ease-mech);font-size:10px}
.acc.is-on .acc-chev{transform:rotate(180deg)}
.acc-panel{display:grid;grid-template-rows:0fr;transition:grid-template-rows var(--dur-slow) var(--ease-mech)}
.acc.is-on .acc-panel{grid-template-rows:1fr}
.acc-inner{overflow:hidden}
.acc-inner>div{padding:0 var(--space-16) var(--space-16);font-size:13px;color:var(--text-secondary);
  opacity:0;transform:translateY(var(--shift-sm));
  transition:opacity var(--dur-base) var(--ease-mech) 100ms,transform var(--dur-base) var(--ease-mech) 100ms}
.acc.is-on .acc-inner>div{opacity:1;transform:none}

/* ── 18. TABLES ───────────────────────────────────────────────────────── */
.tbl{width:100%;border-collapse:collapse;font-size:13px}
.tbl th{font-family:var(--font-ui);font-weight:600;font-size:var(--text-micro);letter-spacing:.12em;
  text-transform:uppercase;color:var(--text-secondary);text-align:left;
  padding:var(--space-8) var(--space-12);border-bottom:var(--stroke-default) solid var(--border-default)}
.tbl td{padding:var(--space-12);border-bottom:var(--stroke-hairline) solid var(--border-hairline);
  font-family:var(--font-mono);color:var(--text-secondary)}
.tbl tbody tr{position:relative;transition:background-color var(--dur-fast) var(--ease-mech)}
.tbl tbody tr:hover{background:var(--surface-2)}
.tbl tbody td:first-child{position:relative}
.tbl tbody td:first-child::before{content:'';position:absolute;left:0;top:var(--space-8);bottom:var(--space-8);
  width:var(--stroke-strong);background:var(--color-primary);transform:scaleY(0);transform-origin:center;
  transition:transform var(--dur-fast) var(--ease-snap)}
.tbl tbody tr:hover td:first-child::before{transform:scaleY(1)}
.tbl th.is-sortable{cursor:pointer;user-select:none;transition:color var(--dur-fast) var(--ease-mech)}
.tbl th.is-sortable:hover{color:var(--color-primary)}

/* ── 19. CHARTS ───────────────────────────────────────────────────────── */
.chart{background:var(--surface-2);border:var(--stroke-hairline) solid var(--border-hairline);
  border-radius:var(--radius-sm);padding:var(--space-12)}
.chart-line path,.chart-spark path{stroke-dasharray:var(--path-length,1000);stroke-dashoffset:var(--path-length,1000)}
.is-in .chart-line path{animation:drk-draw var(--dur-boot) var(--ease-mech) both}
.is-in .chart-spark path{animation:drk-draw var(--dur-slow) var(--ease-mech) both}
.chart-donut circle.val-arc{stroke-dasharray:var(--circ,220);stroke-dashoffset:var(--circ,220)}
.is-in .chart-donut circle.val-arc{animation:drk-draw var(--dur-deliberate) var(--ease-mech) both}
.chart-bars{display:flex;align-items:flex-end;gap:var(--space-8);height:96px}
.chart-bars>i{flex:1;background:var(--color-primary);border-radius:1px 1px 0 0;transform-origin:bottom;
  transform:scaleY(0);transition:transform var(--dur-deliberate) var(--ease-mech)}
.is-in .chart-bars>i{transform:scaleY(1)}
.is-in .chart-bars>i:nth-child(1){transition-delay:0ms}
.is-in .chart-bars>i:nth-child(2){transition-delay:60ms}
.is-in .chart-bars>i:nth-child(3){transition-delay:120ms}
.is-in .chart-bars>i:nth-child(4){transition-delay:180ms}
.is-in .chart-bars>i:nth-child(5){transition-delay:240ms}
.is-in .chart-bars>i:nth-child(n+6){transition-delay:300ms}

/* ── 20. TERMINAL / LOG ───────────────────────────────────────────────── */
.term{background:#060708;border:var(--stroke-hairline) solid var(--border-hairline);
  border-radius:var(--radius-sm);padding:var(--space-12);font-family:var(--font-mono);
  font-size:13px;line-height:1.7;position:relative;overflow:hidden}
.term::after{content:'';position:absolute;inset:0;pointer-events:none;
  background:repeating-linear-gradient(0deg,transparent 0 2px,rgba(0,0,0,.28) 2px 3px)}
.term-ln{color:var(--text-secondary);white-space:nowrap;overflow:hidden;position:relative;z-index:1}
.term-ln.is-ok{color:var(--color-success)}
.term-ln.is-err{color:var(--color-danger-fg)}
.term-ln.is-warn{color:var(--color-warning)}
.term-caret{display:inline-block;width:8px;height:14px;background:var(--color-primary);
  vertical-align:-2px;animation:drk-caret 1s steps(1) infinite}

/* ── 21. LOADING / EMPTY ──────────────────────────────────────────────── */
.spinner{width:32px;height:32px;border-radius:50%;border:2px solid var(--surface-3);
  border-top-color:var(--color-primary);animation:drk-spin 900ms var(--ease-linear) infinite}
.spinner--sm{width:24px;height:24px}
.skel{height:12px;border-radius:2px;margin-bottom:var(--space-8);
  background:linear-gradient(90deg,var(--surface-2) 25%,var(--surface-3) 50%,var(--surface-2) 75%);
  background-size:200% 100%;animation:drk-skeleton 1.6s var(--ease-linear) infinite}
.empty{text-align:center;padding:var(--space-24);border:1px dashed var(--border-default);
  border-radius:var(--radius-sm);color:var(--text-secondary);font-size:13px}
.empty-ico{font-size:22px;color:var(--text-dim);display:block;margin-bottom:var(--space-8)}
.is-in .empty-ico{animation:drk-flicker var(--dur-deliberate) var(--ease-linear) both}
.radar{width:96px;height:96px;border-radius:50%;border:var(--stroke-default) solid var(--border-default);
  position:relative;overflow:hidden;margin:0 auto}
.radar::after{content:'';position:absolute;inset:0;
  background:conic-gradient(from 0deg,rgba(255,59,48,.55),transparent 25%);
  animation:drk-sweep 2.4s var(--ease-linear) infinite}

/* ── 22. NAVIGATION ───────────────────────────────────────────────────── */
.topnav{position:fixed;top:0;left:0;right:0;z-index:50;background:rgba(10,10,10,.92);
  backdrop-filter:blur(16px);border-bottom:var(--stroke-hairline) solid var(--border-hairline);
  transition:background-color var(--dur-base) var(--ease-mech),
             border-color var(--dur-base) var(--ease-mech)}
.topnav::after{content:'';position:absolute;bottom:0;left:0;right:0;height:var(--stroke-hairline);
  background:linear-gradient(90deg,transparent,var(--color-primary),transparent);opacity:.4;
  transition:opacity var(--dur-base) var(--ease-mech)}
.topnav-inner{max-width:var(--grid-max-width);margin:0 auto;display:flex;align-items:center;
  justify-content:flex-start;padding:0 var(--grid-margin);height:64px;gap:var(--space-16);
  transition:margin var(--dur-base) var(--ease-mech),padding var(--dur-base) var(--ease-mech),
             width var(--dur-base) var(--ease-mech),max-width var(--dur-base) var(--ease-mech),
             background-color var(--dur-base) var(--ease-mech),
             border-color var(--dur-base) var(--ease-mech),
             border-radius var(--dur-base) var(--ease-mech),
             box-shadow var(--dur-base) var(--ease-mech)}

/* Passé le premier écran, la barre décolle : elle quitte le bord et
   devient un îlot posé sur la page. Elle ne disparaît plus en descendant
   — c'était l'ancien comportement, et une barre qui s'en va n'est pas une
   barre flottante : le menu doit rester joignable à tout moment.

   Le cadre fixe couvre encore toute la largeur de l'écran ; en mode
   flottant il ne porte plus rien, donc il laisse passer les clics et
   seul l'îlot les reçoit. Sans cela, une bande de 88 px avalerait tout
   ce qui se trouve dessous. */
.topnav.is-float{background:transparent;backdrop-filter:none;border-bottom-color:transparent;
  pointer-events:none}
.topnav.is-float::after{opacity:0}
.topnav.is-float .topnav-inner{pointer-events:auto;
  width:calc(100% - var(--space-32));max-width:calc(var(--grid-max-width) - var(--space-32));
  margin:var(--space-12) auto;padding:0 var(--space-16);
  background:rgba(10,10,10,.94);backdrop-filter:blur(16px);
  border:var(--stroke-hairline) solid var(--border-hairline);border-radius:var(--radius-md);
  box-shadow:0 10px 30px rgba(0,0,0,.6)}

/* Le menu se cale à droite ; le bouton de coupure le suit, puis le
   hamburger. Seul l'ordre visuel est réarrangé : dans le DOM le bouton
   de coupure précède le menu, pour rester atteignable au clavier avant
   la liste des sections. */
.topnav-links{margin-left:auto;order:2}
.nav-mute{order:3}
.topnav-toggle{order:4}
.topnav-brand{display:flex;align-items:center;gap:var(--space-12);flex-shrink:0}
.topnav-brand img{width:34px;height:34px;object-fit:contain}
.topnav-brand-txt{display:flex;flex-direction:column;line-height:1.1}
.topnav-brand-txt strong{font-family:var(--font-display);font-weight:700;font-size:13px;
  letter-spacing:.10em;text-transform:uppercase;color:var(--text-primary)}
.topnav-links{display:flex;align-items:center;gap:0;position:relative}
.topnav-links>a{font-family:var(--font-ui);font-weight:600;font-size:12px;letter-spacing:.12em;
  text-transform:uppercase;color:var(--text-dim);padding:0 var(--space-12);height:64px;
  display:flex;align-items:center;transition:color var(--dur-fast) var(--ease-mech)}
.topnav-links>a:hover{color:var(--text-secondary)}
.topnav-links>a.is-active{color:var(--color-primary)}

/* Les boutons placés dans la nav ne doivent pas hériter du height:64px
   des liens de navigation, qui l'emporte sur .btn par spécificité et les
   étirait sur toute la hauteur de la barre. */
.topnav-links>a.btn{height:36px;align-self:center;padding:0 var(--space-16);
  font-size:var(--text-label);letter-spacing:var(--tracking-label)}
.topnav-links>a.btn.btn--sm{height:28px;padding:0 var(--space-12);font-size:var(--text-micro)}
/* La couleur de .topnav-links>a l'emporte sur celle des variantes .btn--*
   par spécificité : sans ces règles, « Rejoindre » héritait de --text-dim
   sur fond rouge, soit 1,5:1 de contraste — illisible.
   « Le Roman » utilise la variante destructive pour son cadre rouge, mais
   ce n'est pas une action destructive : texte blanc plutôt que saumon,
   comme demandé. Les variantes restent inchangées ailleurs. */
.topnav-links>a.btn--primary,
.topnav-links>a.btn--primary:hover,
.topnav-links>a.btn--destructive,
.topnav-links>a.btn--destructive:hover{color:var(--btn-primary-fg)}
.topnav-ink{position:absolute;bottom:0;left:0;width:0;height:var(--stroke-strong);
  background:var(--color-primary);box-shadow:var(--glow-primary);
  transition:transform var(--dur-base) var(--ease-mech),width var(--dur-base) var(--ease-mech)}
/* Coupure du son — bouton animé de la barre de navigation.

   Il commande la MÊME chose que la pause de la console et que la touche M :
   la lecture s'arrête vraiment, le mp3 cesse d'être téléchargé et la
   préférence est retenue d'une visite à l'autre. Un vrai muet laisserait
   le flux courir en silence, ce qui coûte de la bande passante pour rien
   et donnerait deux notions d'« éteint » au lieu d'une.

   L'icône se transforme par transitions et non par @keyframes : le geste
   doit savoir revenir en arrière quand on relance. Les ondes rentrent
   dans le haut-parleur, la croix s'ouvre à leur place ; en sens inverse,
   la croix se referme et les ondes ressortent. Quand ça joue, les ondes
   respirent — c'est le seul témoin de lecture visible depuis le bas de
   la page, où la console du hero n'est plus à l'écran. */
.nav-mute{flex:none;width:36px;height:36px;display:grid;place-items:center;cursor:pointer;
  background:transparent;color:var(--text-dim);
  border:var(--stroke-default) solid var(--border-default);border-radius:var(--radius-sm);
  transition:color var(--dur-fast) var(--ease-mech),border-color var(--dur-fast) var(--ease-mech),
             box-shadow var(--dur-fast) var(--ease-mech)}
.nav-mute[hidden]{display:none}
.nav-mute:hover{color:var(--color-primary);border-color:var(--color-primary);
  box-shadow:var(--glow-primary-soft)}
.nav-mute svg{width:18px;height:18px;display:block;overflow:visible}
.nav-mute .nm-spk{fill:currentColor}
.nav-mute .nm-w1,.nav-mute .nm-w2,.nav-mute .nm-x{fill:none;stroke:currentColor;stroke-width:1.6;
  stroke-linecap:round;transform-box:view-box;transform-origin:8px 10px;
  transition:opacity var(--dur-base) var(--ease-snap),transform var(--dur-base) var(--ease-snap)}
.nav-mute .nm-w2{transition-delay:50ms}
.nav-mute .nm-x{opacity:0;transform:scale(.4)}
.nav-mute.is-on{color:var(--color-primary);border-color:rgba(255,59,48,.38)}
.nav-mute.is-on .nm-w1{animation:drk-onde 1.7s var(--ease-hold) infinite}
.nav-mute.is-on .nm-w2{animation:drk-onde 1.7s var(--ease-hold) infinite;animation-delay:.22s}
.nav-mute.is-muted .nm-w1{opacity:0;transform:translateX(-3px) scale(.55);animation:none}
.nav-mute.is-muted .nm-w2{opacity:0;transform:translateX(-5px) scale(.4);animation:none}
.nav-mute.is-muted .nm-x{opacity:1;transform:scale(1);transition-delay:110ms}

.topnav-toggle{display:none;background:none;border:0;cursor:pointer;padding:var(--space-8)}
.topnav-toggle span{display:block;width:20px;height:2px;background:var(--color-primary);margin:4px 0;
  transition:transform var(--dur-base) var(--ease-mech),opacity var(--dur-fast)}

/* 1240 et non 1100 : la barre porte un neuvième lien depuis l'ajout de
   « Chaîne ». Mesuré, la rangée complète — écusson, neuf liens, coupure
   du son et deux boutons — demande 1237 px de cadre ; en dessous de
   1260 px de fenêtre, barre de défilement comprise, elle débordait au
   lieu de se replier sous le hamburger. Le seuil est repris à l'identique dans le curseur
   de la barre (index.html, moveInk). */
@media(max-width:1260px){
  /* top:100% et non 64px : en mode flottant la barre mesure 88 px avec
     ses marges, et le menu déroulant doit tomber sous l'îlot, pas dedans. */
  .topnav-links{display:none;position:absolute;top:100%;left:0;right:0;flex-direction:column;
    background:var(--surface-1);border-bottom:var(--stroke-default) solid var(--border-default);padding:var(--space-8) 0}
  .topnav.is-float .topnav-links{left:var(--space-16);right:var(--space-16);
    border:var(--stroke-hairline) solid var(--border-hairline);border-radius:var(--radius-md)}
  .nav-mute{margin-left:auto}
  .topnav-links.is-open{display:flex;animation:drk-wipe-down var(--dur-base) var(--ease-mech) both}
  .topnav-links>a{height:44px;width:100%;padding:0 var(--grid-margin);
    border-left:var(--stroke-strong) solid transparent}
  .topnav-links>a:hover{border-left-color:var(--color-primary);background:var(--surface-2)}
  .topnav-ink{display:none}
  .topnav-toggle{display:block}
}

/* Sidebar nav item */
.nav-i{display:flex;align-items:center;gap:var(--space-12);padding:10px var(--space-12);
  border-left:var(--stroke-strong) solid transparent;border-radius:var(--radius-sm);cursor:pointer;
  font-family:var(--font-ui);font-size:14px;letter-spacing:.06em;color:var(--text-secondary);
  text-decoration:none;
  transition:background-color var(--dur-fast) var(--ease-mech),color var(--dur-fast) var(--ease-mech),
             border-color var(--dur-fast) var(--ease-mech),box-shadow var(--dur-fast) var(--ease-mech)}
.nav-i .ic{width:16px;text-align:center;flex:none;transition:transform var(--dur-fast) var(--ease-mech)}
.nav-i:hover{color:var(--text-primary);background:var(--surface-2)}
.nav-i:hover .ic{transform:translateX(2px)}
.nav-i.is-active{color:var(--color-primary);background:rgba(255,59,48,.08);
  border-left-color:var(--color-primary);box-shadow:var(--glow-primary-soft)}

/* Breadcrumb */
.crumbs{display:flex;align-items:center;gap:var(--space-8);font-family:var(--font-ui);
  font-size:12px;letter-spacing:.08em;text-transform:uppercase;color:var(--text-dim)}
.crumbs>a{color:var(--text-secondary)}
.crumbs>span:last-child{color:var(--color-primary)}

/* ── 23. SITE COMPONENTS ──────────────────────────────────────────────── */

/* Hero */
.hero{min-height:100vh;position:relative;display:flex;align-items:center;overflow:hidden}
.hero-canvas{position:absolute;inset:0;z-index:1;background:var(--surface-0)}
.hero-canvas canvas{display:block;width:100%;height:100%;cursor:grab}
.hero-canvas canvas:active{cursor:grabbing}
.hero-status{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);
  font-family:var(--font-mono);font-size:13px;color:var(--color-primary);text-align:center;pointer-events:none}
.hero-canvas canvas+.hero-status{display:none}
.hero::after{content:'';position:absolute;inset:0;z-index:2;pointer-events:none;
  background:radial-gradient(ellipse at 20% 60%,rgba(255,59,48,.07),transparent 60%),
             linear-gradient(180deg,transparent 55%,var(--surface-0) 100%)}
.hero-inner{position:relative;z-index:3;max-width:var(--grid-max-width);margin:0 auto;width:100%;
  padding:var(--space-96) var(--grid-margin) var(--space-64)}
.hero-text{max-width:640px}
.hero-tag{display:inline-flex;align-items:center;gap:var(--space-8);font-family:var(--font-ui);
  font-weight:600;font-size:var(--text-micro);letter-spacing:var(--tracking-micro);text-transform:uppercase;
  color:var(--color-primary);margin-bottom:var(--space-24);padding:var(--space-4) 10px;
  background:var(--surface-1);border:var(--stroke-default) solid var(--color-primary);border-radius:var(--radius-sm)}
.hero-les{display:block;font-family:var(--font-display);font-weight:400;
  font-size:clamp(14px,2vw,24px);letter-spacing:.4em;text-transform:uppercase;color:var(--text-secondary);line-height:1}
.hero-loups{display:block;font-family:var(--font-display);font-weight:900;
  font-size:clamp(56px,11vw,150px);letter-spacing:-.02em;text-transform:uppercase;
  color:var(--text-primary);line-height:.9;position:relative}
.hero-loups::before,.hero-loups::after{content:attr(data-text);position:absolute;top:0;left:0;
  width:100%;height:100%;pointer-events:none}
.hero-loups::before{color:var(--color-primary);opacity:.55;transform:translateX(-2px);
  animation:drk-glitch 8s var(--ease-hold) infinite}
.hero-loups::after{color:var(--color-accent);opacity:.35;transform:translateX(2px);
  animation:drk-glitch 8s var(--ease-hold) infinite reverse}
.hero-deyela{display:flex;align-items:baseline;gap:.35em;margin-bottom:var(--space-24)}
.hero-de{font-family:var(--font-display);font-weight:400;font-size:clamp(14px,2vw,24px);
  letter-spacing:.35em;text-transform:uppercase;color:var(--text-secondary)}
.hero-yela{font-family:var(--font-display);font-weight:900;font-size:clamp(32px,5vw,72px);
  letter-spacing:.04em;text-transform:uppercase;color:var(--color-primary);text-shadow:var(--glow-primary)}
.hero-tagline{font-family:var(--font-prose);font-style:italic;font-weight:300;font-size:17px;
  color:var(--text-primary);line-height:1.7;padding:var(--space-12) var(--space-16);
  border-left:var(--stroke-strong) solid var(--color-primary);
  background:linear-gradient(90deg,rgba(255,59,48,.06),transparent);
  max-width:520px;margin-bottom:var(--space-24)}
.hero-tagline em{color:var(--color-primary)}
/* Colonne d'instruments du hero : console audio au-dessus, HUD de
   statut en dessous. Les deux étaient posés séparément en absolu ; à
   deux, ils se marchaient dessus dès qu'une fenêtre était courte. */
.hero-rail{position:absolute;right:var(--grid-margin);bottom:var(--space-32);z-index:5;
  width:288px;max-width:calc(100% - var(--grid-margin)*2);
  display:flex;flex-direction:column;gap:var(--space-12)}
.hero-hud{width:auto}
@media(max-width:1000px){.hero-hud{display:none}}

/* Le HUD de statut portait trois nombres rouges et trois jauges pleines
   rouges dans un panneau de 288 px, sous un code rouge et une pastille
   rouge. Même remède que les cartes de chiffres (§ 13) et même principe :
   le rouge marque le NIVEAU ATTEINT, pas la surface.

   Comme là-bas, rien n'est remplacé : .val et .bar restent les composants
   du design system, ils sont seulement rhabillés ICI, sous .hero-hud.
   Élargir ces règles toucherait les cartes de chiffres, l'armurerie et
   les jauges de la page Outils. */
.hero-hud .val{color:var(--text-primary)}

/* La jauge devient un filet de 3 px : le remplissage recule à l'arrière-plan
   et c'est sa TÊTE qui porte l'information — un trait clair et vif posé au
   niveau atteint, qui bat lentement. Le pendant du dernier témoin allumé
   des cartes de chiffres, ramassé sur une seule barre faute de place. */
.hero-hud .bar{position:relative;height:3px;background:var(--surface-3);overflow:visible}
.hero-hud .bar>i{position:relative;background:var(--color-primary);opacity:.42}
.hero-hud .bar>i::after{content:'';position:absolute;right:0;top:-4px;width:2px;height:11px;
  /* drk-pulse pose son propre box-shadow en currentColor et écrase celui-ci ;
     d'où la couleur, qui rend le halo rouge. Le glow déclaré sert quand
     l'animation est coupée (prefers-reduced-motion). */
  background:var(--color-primary);color:var(--color-primary);box-shadow:var(--glow-primary);
  /* Le parent est mis à l'échelle en x par --v : la tête se dé-écrase
     d'autant, sinon elle maigrit à mesure que la jauge est courte. */
  transform-origin:right;transform:scaleX(calc(1 / var(--v,1)));
  animation:drk-pulse 1.8s var(--ease-hold) infinite}

/* Un balayage lent traverse le filet, comme dans les cartes de chiffres.
   Il déplace un fond et non un bloc : le filet n'a plus d'overflow pour
   le découper, puisque la tête de niveau en dépasse. */
.hero-hud .bar::after{content:'';position:absolute;inset:0;pointer-events:none;border-radius:2px;
  background:linear-gradient(90deg,transparent 40%,rgba(255,59,48,.30) 50%,transparent 60%);
  background-size:250% 100%;background-repeat:no-repeat;
  animation:drk-hud-sweep 5.5s var(--ease-linear) infinite}

/* Réticule de verrouillage — suit la position écran de l'os Head du
   modèle 3D. Uniquement des tokens existants : aucune couleur ni échelle
   nouvelle, conformément au brief. */
.reticle{position:absolute;top:0;left:0;z-index:4;pointer-events:none;
  opacity:0;transition:opacity var(--dur-base) var(--ease-mech);will-change:transform}
.reticle.is-on{opacity:1}
.reticle-mark{position:absolute;left:-26px;top:-26px;width:52px;height:52px}
.reticle-corner{position:absolute;width:10px;height:10px}
.reticle-corner::before,.reticle-corner::after{content:'';position:absolute;
  background:var(--color-primary);box-shadow:var(--glow-primary)}
.reticle-corner::before{width:100%;height:var(--stroke-strong)}
.reticle-corner::after{width:var(--stroke-strong);height:100%}
.reticle-corner.tl{top:0;left:0}
.reticle-corner.tr{top:0;right:0}
.reticle-corner.tr::before{right:0}
.reticle-corner.tr::after{right:0}
.reticle-corner.bl{bottom:0;left:0}
.reticle-corner.bl::before{bottom:0}
.reticle-corner.br{bottom:0;right:0}
.reticle-corner.br::before{bottom:0;right:0}
.reticle-corner.br::after{right:0}
.reticle-label{position:absolute;left:38px;top:-26px;display:flex;flex-direction:column;
  gap:var(--space-2);white-space:nowrap;padding:var(--space-8) var(--space-12);
  background:rgba(10,10,10,.72);backdrop-filter:blur(2px);
  border-left:var(--stroke-strong) solid var(--color-primary)}
/* Étiquette rabattue à gauche quand la colonne d'instruments occupe le
   bord droit — scene.js pose .is-flip. */
.reticle.is-flip .reticle-label{left:auto;right:38px;align-items:flex-end;text-align:right;
  border-left:0;border-right:var(--stroke-strong) solid var(--color-primary)}
.reticle-label .lbl{color:var(--text-primary)}
.reticle-label .micro{color:var(--text-secondary)}
.reticle-label .st{font-size:var(--text-micro)}
@media(max-width:900px){.reticle{display:none}}
@media (prefers-reduced-motion:reduce){.reticle{display:none}}

/* Les « yeux de LU-6 » (.lu6) ont été retirés : deux points rouges
   pulsants hérités de l'ancien hero, sans objet depuis que le hero
   affiche un personnage 3D. */

/* Timeline */
.tl{position:relative;display:flex;flex-direction:column;gap:var(--space-32);margin-top:var(--space-32)}
.tl::before{content:'';position:absolute;left:50%;top:0;bottom:0;width:var(--stroke-strong);
  transform:translateX(-50%);background:linear-gradient(180deg,transparent,var(--color-primary) 20%,var(--color-primary) 80%,transparent);opacity:.4}
.tl-item{position:relative;width:46%}
.tl-item:nth-child(odd){align-self:flex-start}
.tl-item:nth-child(even){align-self:flex-end}
.tl-node{position:absolute;top:var(--space-24);width:12px;height:12px;transform:rotate(45deg);
  background:var(--surface-0);border:var(--stroke-strong) solid var(--color-primary);z-index:3;
  transition:transform var(--dur-base) var(--ease-snap),box-shadow var(--dur-fast) var(--ease-mech),background-color var(--dur-fast)}
.tl-item:nth-child(odd) .tl-node{right:-8.7%;margin-right:-6px}
.tl-item:nth-child(even) .tl-node{left:-8.7%;margin-left:-6px}
.tl-item:hover .tl-node{background:var(--color-primary);box-shadow:var(--glow-primary);transform:rotate(45deg) scale(1.3)}
.tl-arm{position:absolute;top:calc(var(--space-24) + 5px);height:var(--stroke-strong);
  background:var(--color-primary);opacity:.4;transition:opacity var(--dur-fast) var(--ease-mech)}
.tl-item:nth-child(odd) .tl-arm{right:-8.7%;width:8.7%}
.tl-item:nth-child(even) .tl-arm{left:-8.7%;width:8.7%}
.tl-item:hover .tl-arm{opacity:1}
.tl-year{font-family:var(--font-display);font-weight:900;font-size:24px;
  color:var(--color-primary);letter-spacing:.04em;line-height:1}
.tl-loc{font-family:var(--font-mono);font-size:12px;color:var(--text-dim);margin-top:var(--space-4)}
@media(max-width:900px){
  .tl::before{left:12px}
  .tl-item,.tl-item:nth-child(odd),.tl-item:nth-child(even){width:auto;align-self:stretch;margin-left:var(--space-48)}
  .tl-arm{display:none}
  .tl-node{left:-38px!important;right:auto!important;margin:0!important}
}

/* Video */
.vid{position:relative;background:var(--surface-1);border:var(--stroke-hairline) solid var(--border-hairline);
  border-radius:var(--radius-md);overflow:hidden;transition:border-color var(--dur-fast) var(--ease-mech),box-shadow var(--dur-fast) var(--ease-mech)}
.vid:hover{border-color:var(--border-accent);box-shadow:var(--glow-primary-soft)}
.vid-frame{position:relative;padding-bottom:56.25%;height:0;background:var(--surface-0)}
.vid-frame iframe{position:absolute;inset:0;width:100%;height:100%;border:0}

/* Écran de consentement — aucune requête tierce avant clic.
   La vignette est auto-hébergée ; le 4:3 de YouTube est recadré en 16:9. */
.vid-consent{position:absolute;inset:0;width:100%;height:100%;padding:0;
  border:0;background:var(--surface-0);cursor:pointer;display:block;overflow:hidden;
  transition:box-shadow var(--dur-fast) var(--ease-mech)}
.vid-consent:hover{box-shadow:inset 0 0 0 var(--stroke-strong) var(--color-primary)}
.vid-thumb{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  opacity:.42;filter:saturate(.7);
  transition:opacity var(--dur-base) var(--ease-mech),filter var(--dur-base) var(--ease-mech)}
.vid-consent:hover .vid-thumb{opacity:.6;filter:saturate(.9)}
.vid-play{position:absolute;top:50%;left:50%;width:56px;height:56px;
  transform:translate(-50%,-50%);
  border:var(--stroke-strong) solid var(--color-primary);border-radius:50%;
  box-shadow:var(--glow-primary);
  transition:transform var(--dur-fast) var(--ease-mech),box-shadow var(--dur-fast) var(--ease-mech)}
.vid-play::before{content:'';position:absolute;top:50%;left:54%;transform:translate(-50%,-50%);
  border-style:solid;border-width:9px 0 9px 15px;
  border-color:transparent transparent transparent var(--color-primary)}
.vid-consent:hover .vid-play{transform:translate(-50%,-50%) scale(1.08);
  box-shadow:var(--glow-primary),var(--glow-primary-soft)}
.vid-consent-txt{position:absolute;left:0;right:0;bottom:var(--space-16);
  display:flex;flex-direction:column;align-items:center;gap:var(--space-2);text-align:center}
.vid-consent-txt .lbl{color:var(--text-primary)}
.vid-consent-txt .micro{color:var(--text-secondary)}

/* ── Flux de la chaîne — section « Chaîne YouTube » ────────────────────
   Une console de réception : en-tête d'appareil, relevés chiffrés, journal
   de synchronisation, filtres, puis les douze fiches.

   Rien n'est écrit en dur ici, contrairement aux cartes de la page Outils :
   le contenu vient de videos.php et change tout seul à chaque publication
   de la chaîne. C'est le JS qui pose les fiches, à l'approche de la
   section — jamais avant, comme les consoles de l'armurerie.

   Comme pour les vignettes de la page Outils, tout ce qui répond au survol
   est en TRANSITION et non en @keyframes : une transition sait revenir en
   arrière, et repart de la position courante si l'on ressort en plein
   mouvement. Les seules animations bouclées sont ambiantes — barres de
   signal, balayage de la grille — et ne dépendent d'aucun geste.

   La vignette, l'écran de consentement et le bouton de lecture sont ceux
   de la section « Nos Vidéos » (.vid-thumb, .vid-consent, .vid-play) :
   même composant, même promesse — aucune requête vers YouTube avant un
   clic. Le survol, lui, est repris au niveau de la CARTE entière : la
   fiche est plus grande que sa seule image. */
.flx{position:relative;background:var(--surface-2);
  border:var(--stroke-hairline) solid var(--border-hairline);border-radius:var(--radius-md);
  overflow:hidden;margin-top:var(--space-24)}

/* En-tête d'appareil : code, état, barres de signal, relevés. */
.flx-head{display:flex;align-items:center;gap:var(--space-12);flex-wrap:wrap;
  padding:var(--space-8) var(--space-12);background:var(--surface-1);
  border-bottom:var(--stroke-hairline) solid var(--border-hairline)}
.flx-head .sp{flex:1}
.flx-sig{display:flex;align-items:flex-end;gap:2px;width:30px;height:12px;flex:none}
.flx-sig>i{flex:1;height:100%;background:var(--color-primary);border-radius:1px;
  opacity:.16;transform-origin:bottom;transform:scaleY(.3);
  transition:opacity var(--dur-base) var(--ease-mech),transform var(--dur-base) var(--ease-mech)}
/* Le signal ne bat que pendant la synchronisation : une fois le flux reçu,
   il se pose au repos plutôt que de s'agiter dans le vide. */
.flx[data-etat="sync"] .flx-sig>i{opacity:1;animation:drk-vu 620ms var(--ease-hold) infinite alternate}
.flx[data-etat="sync"] .flx-sig>i:nth-child(2){animation-duration:940ms;animation-delay:80ms}
.flx[data-etat="sync"] .flx-sig>i:nth-child(3){animation-duration:520ms;animation-delay:160ms}
.flx[data-etat="sync"] .flx-sig>i:nth-child(4){animation-duration:1180ms;animation-delay:40ms}
.flx[data-etat="ok"] .flx-sig>i{opacity:.55;transform:scaleY(.55)}
.flx[data-etat="ok"] .flx-sig>i:nth-child(2){transform:scaleY(.75)}
.flx[data-etat="ok"] .flx-sig>i:nth-child(3){transform:scaleY(.45)}
.flx[data-etat="ok"] .flx-sig>i:nth-child(4){transform:scaleY(.9)}

/* L'appel à la chaîne se tient en haut à droite de la console, là où se
   trouvaient trois relevés chiffrés — nombre de fiches, vues cumulées,
   âge de la dernière. Ils redisaient ce que la grille montre déjà : les
   compteurs des filtres donnent le nombre, chaque fiche porte ses vues et
   sa date. Un bouton d'action y est plus utile qu'un tableau de bord.

   Le logogramme est en `currentColor` : sur l'aplat rouge il est blanc,
   comme l'exige la charte YouTube pour une pose sur fond de couleur. */
.flx-yt svg{width:18px;height:18px;display:block;fill:currentColor;flex:none}

/* Journal de synchronisation. Il ne s'affiche que pendant le relevé et
   s'en va une fois les fiches posées : un journal qui reste à l'écran
   après coup n'est plus une information, c'est du décor. */
.flx-log{margin:var(--space-12);padding:var(--space-8) var(--space-12);font-size:12px;line-height:1.6}
.flx-bar{margin:0 var(--space-12) var(--space-12)}
.flx[data-etat="ok"] .flx-log,.flx[data-etat="ok"] .flx-bar{display:none}

/* Filtres — le composant .tabs du design system, avec son curseur. */
.flx-filtres{position:relative;display:flex;align-items:center;gap:var(--space-4);flex-wrap:wrap;
  padding:0 var(--space-12);border-bottom:var(--stroke-hairline) solid var(--border-hairline)}
.flx-filtres .tab{display:flex;align-items:center;gap:var(--space-8)}
.flx-filtres .tab>b{font-family:var(--font-mono);font-weight:400;font-size:11px;
  padding:1px 5px;border-radius:var(--radius-sm);color:var(--text-dim);background:var(--surface-3);
  transition:color var(--dur-fast) var(--ease-mech),background-color var(--dur-fast) var(--ease-mech)}
.flx-filtres .tab.is-on>b{color:var(--btn-primary-fg);background:var(--btn-primary-bg)}
.flx-filtres .sp{flex:1}
/* Le curseur est posé par le haut : la rangée de filtres passe à la ligne
   sur les écrans étroits, et son bas n'est alors plus celui de l'onglet
   actif. C'est le JS qui donne le top, ligne par ligne. */
.flx-filtres .tab-ink{bottom:auto}
.flx-src{padding:10px 0;font-family:var(--font-mono);font-size:11px;color:var(--text-dim);white-space:nowrap}

/* Grille. Le nombre de colonnes est décidé, pas déduit de la place
   disponible : trois par rang tient les quatre rangs de douze fiches
   partout, plutôt que de recomposer le dernier rang à chaque largeur. */
.flx-grid{position:relative;display:grid;grid-template-columns:repeat(3,1fr);
  gap:var(--space-16);padding:var(--space-16)}
@media(max-width:1080px){.flx-grid{grid-template-columns:repeat(2,1fr)}}
@media(max-width:700px){.flx-grid{grid-template-columns:1fr}}

/* Un balayage traverse la grille une fois, à l'arrivée des fiches. Il ne
   boucle pas : c'est le geste d'un appareil qui vient de recevoir, pas un
   clignotant. */
.flx-grid::after{content:'';position:absolute;left:0;right:0;top:0;height:2px;pointer-events:none;
  background:linear-gradient(90deg,transparent,rgba(255,59,48,.55),transparent);opacity:0}
.flx.is-in .flx-grid::after{animation:drk-scanline 2.2s var(--ease-linear) 1 both}

/* Fiche. Elle reprend le vocabulaire de .card sans en hériter : le survol
   y déclenche plusieurs gestes à la fois, tous portés par la carte. */
.flx-c{position:relative;display:flex;flex-direction:column;overflow:hidden;
  background:var(--surface-1);border:var(--stroke-hairline) solid var(--border-hairline);
  border-radius:var(--radius-md);
  transition:border-color var(--dur-fast) var(--ease-mech),
             transform var(--dur-base) var(--ease-mech),
             box-shadow var(--dur-base) var(--ease-mech),
             background-color var(--dur-base) var(--ease-mech)}
.flx-c:hover,.flx-c:focus-within{border-color:var(--border-accent);background:var(--surface-2);
  transform:translateY(-3px);box-shadow:var(--glow-primary-soft)}
.flx-c[hidden]{display:none}

.flx-vue{position:relative;aspect-ratio:16/9;background:var(--surface-0);overflow:hidden}
.flx-vue iframe{position:absolute;inset:0;width:100%;height:100%;border:0}
.flx-vue .vid-thumb{transform:scale(1);
  transition:opacity var(--dur-base) var(--ease-mech),filter var(--dur-base) var(--ease-mech),
             transform var(--dur-slow) var(--ease-mech)}
.flx-c:hover .vid-thumb,.flx-c:focus-within .vid-thumb{opacity:.72;filter:saturate(1);transform:scale(1.06)}
.flx-c:hover .vid-play,.flx-c:focus-within .vid-play{transform:translate(-50%,-50%) scale(1.12);
  box-shadow:var(--glow-primary),var(--glow-primary-soft)}
.flx-vue .vid-consent-txt{bottom:var(--space-8);opacity:0;transform:translateY(6px);
  transition:opacity var(--dur-base) var(--ease-mech),transform var(--dur-base) var(--ease-mech)}
.flx-c:hover .vid-consent-txt,.flx-c:focus-within .vid-consent-txt{opacity:1;transform:none}

/* Deux coins de visée se referment sur l'image au survol. Deux et non
   quatre : la fiche porte déjà un cadre, quatre équerres redoubleraient
   ses angles au lieu de viser. */
.flx-vue::before,.flx-vue::after{content:'';position:absolute;z-index:3;width:16px;height:16px;
  pointer-events:none;border:0 solid var(--color-primary);opacity:0;
  transition:opacity var(--dur-base) var(--ease-mech),transform var(--dur-base) var(--ease-snap)}
.flx-vue::before{top:8px;left:8px;transform:translate(6px,6px);
  border-top-width:var(--stroke-strong);border-left-width:var(--stroke-strong)}
.flx-vue::after{bottom:8px;right:8px;transform:translate(-6px,-6px);
  border-bottom-width:var(--stroke-strong);border-right-width:var(--stroke-strong)}
.flx-c:hover .flx-vue::before,.flx-c:focus-within .flx-vue::before,
.flx-c:hover .flx-vue::after,.flx-c:focus-within .flx-vue::after{opacity:1;transform:none}
/* Une fois l'iframe posée, plus rien ne vise : la lecture a commencé. */
.flx-c.is-live .flx-vue::before,.flx-c.is-live .flx-vue::after{display:none}

/* Le balayage traverse l'image de haut en bas au survol, et revient sur
   ses pas quand on quitte la carte.

   C'est un FOND de 2 px qu'on déplace dans un calque plein cadre, et non
   un bloc de 2 px qu'on translate : translateY(100%) sur un bloc haut de
   2 px ne l'aurait fait descendre que de 2 px, et il aurait fallu
   mesurer la vignette en JS pour connaître la distance. background-position
   s'exprime, elle, en pourcentage de la place restante. */
.flx-scan{position:absolute;inset:0;z-index:3;pointer-events:none;opacity:0;
  background-image:linear-gradient(90deg,transparent,var(--color-primary),transparent);
  background-size:100% 2px;background-repeat:no-repeat;background-position:0 0;
  transition:opacity var(--dur-base) var(--ease-mech),
             background-position var(--dur-deliberate) var(--ease-mech)}
.flx-c:hover .flx-scan,.flx-c:focus-within .flx-scan{opacity:.85;background-position:0 100%}

.flx-dur{position:absolute;right:var(--space-8);bottom:var(--space-8);z-index:3;
  font-family:var(--font-mono);font-size:11px;color:var(--text-primary);
  background:rgba(10,10,10,.82);padding:2px 6px;border-radius:var(--radius-sm);
  border:var(--stroke-hairline) solid var(--border-default);
  transition:border-color var(--dur-fast) var(--ease-mech),color var(--dur-fast) var(--ease-mech)}
.flx-c:hover .flx-dur{border-color:var(--color-primary);color:var(--color-primary)}

.flx-body{flex:1;display:flex;flex-direction:column;gap:var(--space-4);padding:var(--space-12)}
/* Deux lignes au plus : les titres de la chaîne vont du mot unique à la
   phrase entière, et un rang de fiches doit garder ses pieds alignés. */
.flx-t{font-family:var(--font-display);font-weight:500;font-size:14px;
  letter-spacing:var(--tracking-subhead);text-transform:uppercase;color:var(--text-primary);
  line-height:var(--lh-heading);
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;
  transition:color var(--dur-fast) var(--ease-mech)}
.flx-c:hover .flx-t{color:var(--color-primary)}
.flx-d{font-family:var(--font-body);font-size:13px;line-height:var(--lh-body);color:var(--text-secondary);
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}

.flx-foot{display:flex;align-items:center;gap:var(--space-8);
  padding:var(--space-8) var(--space-12);background:var(--surface-2);
  border-top:var(--stroke-hairline) solid var(--border-hairline);
  font-family:var(--font-mono);font-size:11px;color:var(--text-dim)}
.flx-foot .sp{flex:1}
/* Jauge d'audience : les vues de la fiche rapportées à la meilleure des
   douze. Six témoins, décoratifs comme ceux des cartes de chiffres —
   aucune échelle absolue n'est prétendue. */
.flx-foot .seg{width:52px;height:10px;flex:none}

/* Squelettes d'attente. Ils occupent exactement la place des fiches à
   venir : sans eux la section se replierait sur trois lignes de texte,
   puis pousserait la page de mille pixels à l'arrivée du flux. */
.flx-sk{overflow:hidden;background:var(--surface-1);border-radius:var(--radius-md);
  border:var(--stroke-hairline) solid var(--border-hairline)}
.flx-sk>i,.flx-sk>u>s{background:linear-gradient(90deg,var(--surface-2) 25%,var(--surface-3) 50%,var(--surface-2) 75%);
  background-size:200% 100%;animation:drk-skeleton 1.6s var(--ease-linear) infinite}
.flx-sk>i{display:block;aspect-ratio:16/9}
.flx-sk>u{display:block;padding:var(--space-12)}
.flx-sk>u>s{display:block;height:10px;margin-bottom:var(--space-8);border-radius:2px;text-decoration:none}
.flx-sk>u>s:last-child{width:60%;margin-bottom:0}

/* Pied de console : la date du dernier relevé, seule. */
.flx-pied{display:flex;align-items:center;gap:var(--space-12);flex-wrap:wrap;
  padding:var(--space-8) var(--space-12);background:var(--surface-1);
  border-top:var(--stroke-hairline) solid var(--border-hairline);
  font-family:var(--font-mono);font-size:11px;color:var(--text-dim)}
.flx-pied .sp{flex:1}

/* Rien ne bouge tout seul, et le survol ne fait plus voyager les formes :
   c'est la pose d'arrivée qui est annulée, pas la durée — sans quoi le
   geste aurait lieu quand même, d'un coup. Aucun contenu n'est masqué. */
@media (prefers-reduced-motion:reduce){
  .flx-sig>i,.flx[data-etat="sync"] .flx-sig>i{animation:none;opacity:.55;transform:scaleY(.6)}
  .flx.is-in .flx-grid::after{animation:none}
  .flx-sk>i,.flx-sk>u>s{animation:none}
  .flx-c:hover,.flx-c:focus-within{transform:none}
  .flx-c:hover .vid-thumb,.flx-c:focus-within .vid-thumb{transform:none}
  .flx-c:hover .vid-play,.flx-c:focus-within .vid-play{transform:translate(-50%,-50%)}
  .flx-c:hover .flx-scan,.flx-c:focus-within .flx-scan{opacity:0;background-position:0 0}
}

/* Gallery */
.gal{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:var(--space-8)}
.gal-item{position:relative;aspect-ratio:16/9;overflow:hidden;cursor:pointer;
  border:var(--stroke-hairline) solid var(--border-hairline);background:var(--surface-1);
  transition:border-color var(--dur-fast) var(--ease-mech),transform var(--dur-fast) var(--ease-mech)}
.gal-item:hover{border-color:var(--color-primary);transform:translateY(-2px)}
.gal-item img{width:100%;height:100%;object-fit:cover;transition:transform var(--dur-slow) var(--ease-mech)}
.gal-item:hover img{transform:scale(1.06)}
.gal-item::after{content:'▣ SCAN';position:absolute;inset:0;display:grid;place-items:center;
  background:rgba(10,10,10,.68);font-family:var(--font-ui);font-weight:600;font-size:12px;
  letter-spacing:.2em;color:var(--color-primary);opacity:0;
  transition:opacity var(--dur-fast) var(--ease-mech);pointer-events:none}
.gal-item:hover::after{opacity:1}
.gal-idx{position:absolute;top:var(--space-4);left:var(--space-8);z-index:2;
  font-family:var(--font-mono);font-size:11px;color:var(--color-primary);
  background:var(--surface-0);padding:2px 5px;border:var(--stroke-hairline) solid var(--border-default)}

/* Lightbox */
.lb{position:fixed;inset:0;z-index:90;background:var(--surface-scrim);backdrop-filter:blur(8px);
  display:none;align-items:center;justify-content:center;flex-direction:column;gap:var(--space-16)}
.lb.is-open{display:flex}
.lb-img{max-width:90vw;max-height:80vh;border:var(--stroke-default) solid var(--border-default);
  background:var(--surface-1);cursor:zoom-in;animation:drk-modal-in var(--dur-deliberate) var(--ease-snap) both}
.lb-img.is-zoom{cursor:zoom-out;overflow:auto}
.lb-img img{display:block;max-width:90vw;max-height:80vh;object-fit:contain;
  transition:transform var(--dur-base) var(--ease-mech)}
.lb-img.is-zoom img{transform:scale(2)}
.lb-close,.lb-nav{position:absolute;background:var(--surface-2);
  border:var(--stroke-default) solid var(--border-default);color:var(--color-primary);
  cursor:pointer;display:grid;place-items:center;border-radius:var(--radius-sm);
  font-family:var(--font-mono);transition:all var(--dur-fast) var(--ease-mech)}
.lb-close{top:var(--space-24);right:var(--space-24);width:40px;height:40px;font-size:16px}
.lb-nav{top:50%;transform:translateY(-50%);width:44px;height:44px;font-size:18px}
.lb-nav.prev{left:var(--space-24)}
.lb-nav.next{right:var(--space-24)}
.lb-close:hover,.lb-nav:hover{background:var(--color-primary);color:var(--text-on-primary);border-color:var(--color-primary)}
.lb-count{font-family:var(--font-mono);font-size:13px;color:var(--color-primary);
  padding:var(--space-4) var(--space-12);background:var(--surface-1);
  border:var(--stroke-hairline) solid var(--border-default);border-radius:var(--radius-sm)}

/* Chain of command */
.chain{display:flex;flex-direction:column;gap:var(--space-8)}
.chain-node{background:var(--surface-1);border:var(--stroke-hairline) solid var(--border-hairline);
  border-left:var(--stroke-strong) solid transparent;border-radius:var(--radius-sm);
  padding:var(--space-12) var(--space-16);
  transition:border-color var(--dur-fast) var(--ease-mech),background-color var(--dur-fast) var(--ease-mech)}
.chain-node:hover{background:var(--surface-2);border-left-color:var(--color-primary)}
.chain-node.is-lead{border-left-color:var(--color-primary);background:rgba(255,59,48,.05)}
.chain-rank{font-family:var(--font-ui);font-weight:600;font-size:var(--text-micro);
  letter-spacing:var(--tracking-micro);text-transform:uppercase;color:var(--color-primary);margin-bottom:var(--space-4)}
.chain-node h4{font-family:var(--font-display);font-weight:500;font-size:14px;letter-spacing:.06em;
  text-transform:uppercase;color:var(--text-primary);margin-bottom:var(--space-4)}
.chain-node p{font-family:var(--font-body);font-size:13px;color:var(--text-secondary);line-height:var(--lh-body)}
.chain-arrow{text-align:center;color:var(--color-primary);opacity:.5;font-size:12px;line-height:1}

/* Grades table */
.grades{border:var(--stroke-hairline) solid var(--border-hairline);border-radius:var(--radius-md);
  overflow:hidden;background:var(--surface-1)}
.grades .g-num{font-family:var(--font-display);font-weight:700;font-size:14px;
  color:var(--color-primary);width:40px;text-align:center}
.grades .g-name{font-family:var(--font-ui);font-weight:500;font-size:14px;
  letter-spacing:.04em;color:var(--text-primary)}
.grades .g-code{font-family:var(--font-mono);font-size:12px;color:var(--text-dim)}
.grades tr.is-alpha .g-num{color:var(--color-accent)}
.grades tr.is-alpha .g-name{color:var(--color-accent)}
.grades-note{font-family:var(--font-prose);font-style:italic;font-size:14px;color:var(--text-secondary);
  margin-top:var(--space-12);padding:var(--space-8) var(--space-12);
  border-left:var(--stroke-strong) solid var(--color-primary);background:rgba(255,59,48,.04)}

/* Join steps */
/* ── Rejoindre ─────────────────────────────────────────────────────────
   Deux colonnes : l'appel à gauche, le protocole à droite. La version
   centrée d'avant empilait un titre, trois cartes égales et deux boutons
   sur l'axe — c'était lisible, mais ça ne ressemblait à rien d'autre sur
   la page. Ici, les trois étapes deviennent une chaîne : un rail, trois
   nœuds, un ordre. C'est le vocabulaire déjà employé par l'organigramme
   et par les consoles de l'armurerie. */
.join{display:grid;gap:var(--space-48);align-items:stretch;
  grid-template-columns:minmax(0,1.05fr) minmax(0,.95fr)}

/* L'écusson en filigrane. Il est déjà téléchargé — séquence de boot et
   barre de navigation le servent — donc il ne coûte pas une requête. */
/* La colonne est une pile : le titre en haut, l'appel en bas. Le bloc
   d'action est poussé au pied par margin-top:auto, ce qui fait finir
   les deux colonnes à la même ligne — sans cela la gauche s'arrêtait
   150 px plus haut que la droite et la section penchait. */
.join-call{position:relative;display:flex;flex-direction:column}
.join-call::before{content:'';position:absolute;right:0;top:50%;
  transform:translateY(-50%);
  width:clamp(180px,24vw,300px);height:clamp(180px,24vw,300px);
  background:url('../logo.png') center/contain no-repeat;
  opacity:.05;pointer-events:none}
.join-call>*{position:relative}

/* Le bloc d'action. Le ruban rouge le signale de loin, comme le pied de
   page ; le reste est un panneau ordinaire, pour que les deux boutons
   restent la seule chose qui brille. */
.join-act{margin-top:auto;padding-top:0;background:var(--surface-1);
  border:var(--stroke-hairline) solid var(--border-hairline);
  border-radius:var(--radius-md);overflow:hidden}
.join-act .drk-tape{opacity:.65}
.join-act-body{padding:var(--space-24)}
.join-act .lbl{display:block;margin-bottom:var(--space-16);color:var(--color-primary)}
/* Les deux boutons se partagent la largeur du panneau. Alignés à gauche,
   ils laissaient la moitié droite du bloc vide et l'appel final avait
   l'air d'une note de bas de page. */
.join-act .row .btn{flex:1 1 200px}

/* Le protocole. Repères d'angle comme les consoles de l'armurerie. */
.join-proc{position:relative;background:var(--surface-1);
  border:var(--stroke-hairline) solid var(--border-hairline);
  border-radius:var(--radius-md);
  padding:var(--space-16) var(--space-24) var(--space-16)}
.join-proc::before,.join-proc::after{content:'';position:absolute;
  width:14px;height:14px;border:0 solid var(--color-primary);
  opacity:.45;pointer-events:none}
.join-proc::before{top:8px;left:8px;
  border-top-width:var(--stroke-strong);border-left-width:var(--stroke-strong)}
.join-proc::after{bottom:8px;right:8px;
  border-bottom-width:var(--stroke-strong);border-right-width:var(--stroke-strong)}
.join-proc-head{display:flex;align-items:center;gap:var(--space-8);
  padding-bottom:var(--space-12);
  border-bottom:var(--stroke-hairline) solid var(--border-hairline)}
.join-proc-head .sp{flex:1}
.join-proc-title{margin:var(--space-16) 0 var(--space-8);color:var(--color-primary)}

.join-steps{list-style:none;position:relative;margin:0;padding:0}
/* Le rail. Il part du premier nœud et meurt au dernier : il relie, il ne
   déborde pas. */
.join-steps::before{content:'';position:absolute;left:19px;top:36px;bottom:36px;
  width:var(--stroke-strong);
  background:linear-gradient(180deg,var(--color-primary),rgba(255,59,48,.15))}
.join-step{position:relative;display:grid;grid-template-columns:40px minmax(0,1fr);
  gap:var(--space-16);padding:var(--space-16) 0;align-items:start}
.join-num{position:relative;width:40px;height:40px;border-radius:50%;
  display:grid;place-items:center;
  font-family:var(--font-mono);font-size:14px;line-height:1;color:var(--color-primary);
  background:var(--surface-0);
  border:var(--stroke-strong) solid var(--color-primary);
  box-shadow:var(--glow-primary-soft);
  transition:background-color var(--dur-fast) var(--ease-mech),
             box-shadow var(--dur-fast) var(--ease-mech),color var(--dur-fast) var(--ease-mech)}
.join-step:hover .join-num{background:var(--btn-primary-bg);color:var(--btn-primary-fg);
  box-shadow:var(--glow-primary)}
.join-step-t{font-family:var(--font-display);font-weight:500;font-size:15px;
  letter-spacing:var(--tracking-label);text-transform:uppercase;
  color:var(--text-primary);margin-bottom:var(--space-4)}
.join-step p{font-family:var(--font-body);font-size:14px;
  color:var(--text-secondary);line-height:var(--lh-body)}

@media(max-width:900px){
  .join{grid-template-columns:1fr;gap:var(--space-32)}
  .join-call::before{width:200px;height:200px;opacity:.04}
}

/* Page Outils — catalogue d'applications.
   Même vocabulaire que les cartes de détachements : .card, .card-head,
   .card-title, .card-tags. S'y ajoutent la vignette et la distinction
   entre les applications de la meute et celles de la communauté. */
.app-toolbar{display:flex;align-items:flex-start;gap:var(--space-16);flex-wrap:wrap;
  margin-bottom:var(--space-24)}
.app-filters{display:flex;flex-wrap:wrap;gap:var(--space-8);flex:1;min-width:260px}
button.pill{cursor:pointer;font-weight:600;font-family:var(--font-ui)}
button.pill[aria-pressed="true"]{border-color:var(--color-primary);color:var(--color-primary);
  background:rgba(255,59,48,.08);box-shadow:var(--glow-primary-soft)}
.app-count{font-family:var(--font-mono);font-size:12px;color:var(--text-dim);white-space:nowrap;
  padding-top:var(--space-4)}

.app-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));gap:var(--space-24)}
.app-card{text-decoration:none;color:inherit}
.app-card[hidden],.app-row[hidden]{display:none}
/* Les applications de la meute : fond teinté, bordure rouge, pastille
   LDY. Reconnaissables sans lire une seule étiquette. */
.app-card--ldy{border-color:rgba(255,59,48,.38);
  background:linear-gradient(180deg,rgba(255,59,48,.09),transparent 55%),var(--surface-1)}
.app-card--ldy:hover{border-color:var(--color-primary);
  background:linear-gradient(180deg,rgba(255,59,48,.14),transparent 55%),var(--surface-2)}

.app-vig{position:relative;aspect-ratio:16/9;background:var(--surface-2);overflow:hidden;
  border-bottom:var(--stroke-hairline) solid var(--border-hairline)}
.app-card--ldy .app-vig{background:var(--surface-0)}
.app-vig svg{position:absolute;inset:0;display:block;width:100%;height:100%}
.app-vig::after{content:'';position:absolute;inset:0;pointer-events:none;opacity:.5;
  background:repeating-linear-gradient(0deg,transparent 0 3px,rgba(0,0,0,.28) 3px 4px)}
.app-vig .vg{fill:none;stroke:var(--border-hairline);stroke-width:1}
.app-vig .vl{fill:none;stroke:var(--color-primary);stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
.app-vig .vd{fill:none;stroke:var(--border-strong);stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round}
.app-vig .vf{fill:var(--color-primary)}
.app-vig .vs{fill:var(--surface-3)}
.app-vig .vt{fill:var(--text-dim)}
.app-card:hover .app-vig .vl{filter:drop-shadow(0 0 6px rgba(255,59,48,.55))}

/* Micro-gestes des vignettes — au survol de la carte, chaque icône joue un
   geste court ; à la sortie, elle le rejoue à l'envers.

   D'où l'absence de @keyframes : une animation ne sait pas revenir en
   arrière, une transition ne sait faire que ça — et elle repart de la
   position courante si l'on ressort en plein geste, au lieu de sauter.

   Un seul mécanisme, deux classes, posées sur les formes du SVG :
     .ic  déplace, tourne, redimensionne, éclaircit  (--x --y --r --s/--sx/--sy --a)
     .fl  fait défiler des pointillés existants      (--o)
   Les paramètres sont en style inline : ils tiennent à la géométrie de la
   forme, qui est déjà écrite là. --d décale le départ, --t allonge la durée.
   Le pivot par défaut est le centre du viewBox ; --ox / --oy le déplacent.

   Tout est sous (hover:hover) : sur un écran tactile un :hover se colle et
   ne se décolle plus, et un geste qui ne revient jamais n'est plus un geste. */
@media (hover:hover){
  .app-vig .ic,.app-vig .fl{
    transform-box:view-box;transform-origin:var(--ox,50%) var(--oy,50%);
    transition:transform var(--t,var(--dur-slow)) var(--ease-snap) var(--d,0ms),
               opacity var(--t,var(--dur-slow)) var(--ease-snap) var(--d,0ms),
               stroke-dashoffset var(--t,var(--dur-slow)) var(--ease-snap) var(--d,0ms)}
  .app-vig .ic{transform:translate(0,0) rotate(0deg) scale(1,1)}
  .app-card:hover .app-vig .ic,.app-card:focus-visible .app-vig .ic{
    transform:translate(var(--x,0),var(--y,0)) rotate(var(--r,0deg))
              scale(var(--sx,var(--s,1)),var(--sy,var(--s,1)));
    opacity:var(--a,1)}
  .app-card:hover .app-vig .fl,.app-card:focus-visible .app-vig .fl{stroke-dashoffset:var(--o,-24px)}
}

.app-card .card-body{display:flex;flex-direction:column;gap:var(--space-8)}
.app-card .card-text{margin-top:0;flex:1}
.app-card .card-tags{margin-top:0}
.app-host{font-family:var(--font-mono);font-size:11px;color:var(--text-dim);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-transform:none;letter-spacing:0}
.app-go{margin-left:auto;color:var(--color-primary);flex:none}

.app-view[hidden]{display:none}
.app-tbl-wrap{border:var(--stroke-hairline) solid var(--border-hairline);
  border-radius:var(--radius-md);overflow-x:auto}
.app-tbl .app-nom{font-family:var(--font-ui);font-weight:600;font-size:14px;
  letter-spacing:.04em;color:var(--text-primary)}
.app-tbl tr.is-ldy .app-nom{color:var(--color-accent)}
.app-tbl tr.is-ldy td:first-child::before{transform:scaleY(1)}
.app-tbl .app-tags{display:flex;flex-wrap:wrap;gap:var(--space-4)}
.app-tbl td a{color:var(--color-primary);font-family:var(--font-mono);font-size:12px}
.app-note{font-family:var(--font-body);font-size:13px;color:var(--text-dim);
  margin-top:var(--space-24);padding-left:var(--space-12);
  border-left:var(--stroke-strong) solid var(--border-hairline)}

/* Footer */
.site-foot{position:relative;z-index:10;background:var(--surface-1);
  border-top:var(--stroke-hairline) solid var(--border-hairline)}
.site-foot-inner{max-width:var(--grid-max-width);margin:0 auto;padding:var(--space-32) var(--grid-margin);
  display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:var(--space-16)}
.site-foot-brand{font-family:var(--font-ui);font-weight:600;font-size:12px;letter-spacing:.12em;
  text-transform:uppercase;color:var(--text-secondary);display:flex;align-items:center;gap:var(--space-8)}
.site-foot-brand::before{content:'◆';color:var(--color-primary)}
.site-foot-links{display:flex;gap:var(--space-24);flex-wrap:wrap}
.site-foot-links a{font-family:var(--font-ui);font-weight:600;font-size:var(--text-micro);
  letter-spacing:var(--tracking-micro);text-transform:uppercase;color:var(--text-secondary)}
.site-foot-links a:hover{color:var(--color-primary)}
/* Mention légale. Style console : mono, gris sourd, un fond plus noir que
   le pied de page — c'est la dernière ligne de la machine, pas un contenu.
   Le code repris de .card-code lui met ses crochets tout seul.
   Le texte est en anglais : c'est la formule d'attribution de Cloud
   Imperium, reprise mot pour mot. D'où le lang="en" au milieu d'une page
   lang="fr" — sans lui, une synthèse vocale francophone la prononcerait à
   la française. */
.site-foot-legal{background:var(--surface-0);
  border-top:var(--stroke-hairline) solid var(--border-hairline)}
.site-foot-legal p{max-width:var(--grid-max-width);margin:0 auto;
  padding:var(--space-16) var(--grid-margin);
  font-family:var(--font-mono);font-size:11px;line-height:1.7;
  color:var(--text-dim)}
.site-foot-legal .card-code{margin-right:var(--space-8);white-space:nowrap}

/* Console audio — musique d'ambiance du hero.
   Posée en bas à gauche, en miroir du HUD de droite. Contrairement à lui
   elle reste visible sur mobile : c'est le seul moyen de couper le son,
   elle ne peut pas disparaître. Uniquement des tokens existants. */
.audio-deck{background:var(--surface-2);border:var(--stroke-hairline) solid var(--border-hairline);
  border-radius:var(--radius-md);overflow:hidden;box-shadow:0 8px 24px rgba(0,0,0,.55)}
.audio-deck[hidden]{display:none}

.audio-head{display:flex;align-items:center;gap:var(--space-8);
  padding:var(--space-8) var(--space-12);background:var(--surface-1);
  border-bottom:var(--stroke-hairline) solid var(--border-hairline)}
.audio-head .sp{flex:1}
.audio-head .st{font-size:var(--text-micro)}

.audio-body{display:flex;align-items:center;gap:var(--space-8);padding:var(--space-12)}
.audio-info{flex:1;min-width:0;display:flex;flex-direction:column;gap:var(--space-4)}
.audio-title{font-family:var(--font-ui);font-weight:600;font-size:13px;letter-spacing:.06em;
  text-transform:uppercase;color:var(--text-primary);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

/* Vumètre décoratif : il n'analyse rien, il indique seulement que ça
   joue. Une AnalyserNode obligerait à faire passer le flux par WebAudio,
   dont le contexte peut rester suspendu — le son serait muet. */
.audio-deck .seg{height:11px;margin-bottom:var(--space-2)}
.audio-deck .seg>s{transform-origin:bottom;transition:opacity var(--dur-fast) var(--ease-mech)}
.audio-deck.is-playing .seg>s{animation:drk-vu 620ms var(--ease-hold) infinite alternate}
.audio-deck.is-playing .seg>s:nth-child(2){animation-duration:940ms;animation-delay:80ms}
.audio-deck.is-playing .seg>s:nth-child(3){animation-duration:520ms;animation-delay:160ms}
.audio-deck.is-playing .seg>s:nth-child(4){animation-duration:1180ms;animation-delay:40ms}
.audio-deck.is-playing .seg>s:nth-child(5){animation-duration:760ms;animation-delay:220ms}
.audio-deck.is-playing .seg>s:nth-child(6){animation-duration:1020ms;animation-delay:120ms}
.audio-deck.is-playing .seg>s:nth-child(7){animation-duration:580ms;animation-delay:300ms}
.audio-deck.is-playing .seg>s:nth-child(8){animation-duration:860ms;animation-delay:20ms}
.audio-deck.is-playing .seg>s:nth-child(9){animation-duration:1260ms;animation-delay:180ms}
.audio-deck.is-playing .seg>s:nth-child(10){animation-duration:700ms;animation-delay:260ms}

.audio-btn{flex:none;width:34px;height:34px;display:grid;place-items:center;cursor:pointer;
  background:transparent;color:var(--text-secondary);
  border:var(--stroke-default) solid var(--border-default);border-radius:var(--radius-sm);
  transition:color var(--dur-fast) var(--ease-mech),border-color var(--dur-fast) var(--ease-mech),
             box-shadow var(--dur-fast) var(--ease-mech)}
.audio-btn:hover{color:var(--color-primary);border-color:var(--color-primary);box-shadow:var(--glow-primary-soft)}
.audio-btn svg{width:13px;height:13px;fill:currentColor;display:block}
.audio-btn .ic-pause,.audio-deck.is-playing .audio-btn .ic-play{display:none}
.audio-deck.is-playing .audio-btn .ic-pause{display:block}

/* Transport et volume. Le volume quitte le pied du panneau, où il occupait
   la place que prend maintenant la barre de progression : il se range au
   bout de la rangée de transport, séparé des trois boutons par le vide.
   Doser n'est pas commander la lecture, les deux ne se mélangent pas. */
.audio-transport{display:flex;align-items:center;gap:var(--space-8);padding:0 var(--space-12) var(--space-8)}
.audio-transport .sp{flex:1}
.audio-vol-ic{flex:none;width:14px;height:14px;display:block;color:var(--text-dim)}
.audio-vol-ic path{fill:currentColor}
.audio-vol-ic .w{fill:none;stroke:currentColor;stroke-width:1.4;stroke-linecap:round}
.audio-vol{flex:none;width:76px;height:16px;-webkit-appearance:none;appearance:none;
  background:transparent;cursor:pointer}
.audio-vol::-webkit-slider-runnable-track{height:4px;border-radius:2px;background:var(--surface-4)}
.audio-vol::-webkit-slider-thumb{-webkit-appearance:none;width:12px;height:12px;margin-top:-4px;
  border-radius:2px;background:var(--color-primary);box-shadow:var(--glow-primary)}
.audio-vol::-moz-range-track{height:4px;border-radius:2px;background:var(--surface-4)}
.audio-vol::-moz-range-thumb{width:12px;height:12px;border:0;border-radius:2px;
  background:var(--color-primary);box-shadow:var(--glow-primary)}

/* Barre de progression. C'est un input[type=range] et non un div : le
   glissement, les flèches du clavier, le tambour tactile et l'annonce de
   la position viennent avec, sans une ligne de JavaScript. Le remplissage
   passe par un dégradé posé sur la piste — --p est la seule chose que le
   JS écrit — parce que ::-moz-range-progress n'a pas d'équivalent WebKit. */
.audio-foot{display:flex;align-items:center;gap:var(--space-8);padding:0 var(--space-12) var(--space-12)}
.audio-time{flex:none;font-family:var(--font-mono);font-size:11px;color:var(--text-dim);
  min-width:32px;font-variant-numeric:tabular-nums}
.audio-time:last-child{text-align:right}
.audio-seek{flex:1;min-width:0;height:16px;-webkit-appearance:none;appearance:none;
  background:transparent;cursor:pointer}
.audio-seek::-webkit-slider-runnable-track{height:3px;border-radius:2px;
  background:linear-gradient(90deg,var(--color-primary) 0 var(--p,0%),var(--surface-4) var(--p,0%) 100%)}
.audio-seek::-webkit-slider-thumb{-webkit-appearance:none;width:3px;height:13px;margin-top:-5px;
  border-radius:1px;background:var(--color-primary);box-shadow:var(--glow-primary);
  transition:height var(--dur-fast) var(--ease-mech),margin-top var(--dur-fast) var(--ease-mech)}
.audio-seek:hover::-webkit-slider-thumb,
.audio-seek:focus-visible::-webkit-slider-thumb{height:17px;margin-top:-7px}
.audio-seek::-moz-range-track{height:3px;border-radius:2px;
  background:linear-gradient(90deg,var(--color-primary) 0 var(--p,0%),var(--surface-4) var(--p,0%) 100%)}
.audio-seek::-moz-range-thumb{width:3px;height:13px;border:0;border-radius:1px;
  background:var(--color-primary);box-shadow:var(--glow-primary)}
/* Tant que la durée est inconnue — ou que le serveur refuse les requêtes
   Range, auquel cas le média n'est pas déplaçable —, il n'y a rien à
   viser : la poignée s'efface et la barre n'est plus qu'une jauge
   d'avancement, plutôt qu'une commande qui ne répondrait pas. */
.audio-seek:disabled{cursor:default}
.audio-seek:disabled::-webkit-slider-thumb{opacity:0}
.audio-seek:disabled::-moz-range-thumb{opacity:0}

.audio-key{flex:none;font-family:var(--font-mono);font-size:11px;color:var(--text-dim);
  border:var(--stroke-hairline) solid var(--border-default);border-radius:var(--radius-sm);
  padding:0 var(--space-4);line-height:1.6}

/* Sous 1000px le HUD de statut disparaît, la console reste : c'est le
   seul moyen d'arrêter la musique, elle ne peut pas s'en aller. Elle
   prend alors toute la largeur, en bas du hero. Seul le vumètre saute :
   le transport, le volume et la barre de progression, eux, restent. */
@media(max-width:1000px){
  .hero-rail{left:var(--space-12);right:var(--space-12);bottom:var(--space-24);
    width:auto;max-width:none}
  .audio-deck .seg{display:none}
  .hero-inner{padding-bottom:192px}
}

/* ── Armurerie — consoles de visualisation 3D ──────────────────────────
   Les consoles se partagent UN SEUL canvas WebGL, posé en absolu sur la
   grille et découpé au ciseau (scissor) sur le rectangle de chaque
   .armr-slot. Le budget technique n'autorise pas un contexte par console :
   à cinq armures, ce serait cinq contextes, et les navigateurs en
   recyclent silencieusement les plus anciens.

   Conséquence sur l'empilement : le canvas est un FRÈRE des consoles, pas
   un enfant. L'ordre de peinture se joue donc dans le contexte de la
   section, et il tient à trois règles :
     .armr-scan  z-index 1 — la trame, sous le rendu ;
     .armr-canvas z-index 2 — le rendu lui-même ;
     .armr-hud   z-index 3 — les repères, par-dessus.
   Ne jamais poser transform, filter, opacity < 1 ni will-change sur .armr
   ni sur .armr-slot : chacun créerait un contexte d'empilement local et
   ferait passer le canvas devant, ou derrière, tout le HUD.            */

/* Une console large et basse noie la silhouette : un personnage debout
   fait 0,41 de large pour 1 de haut, il lui faut un cadre plutôt portrait.
   D'où le plafond de 400 px, posé sur la CARTE et non sur la colonne : la
   colonne s'étire, la carte se retient au milieu de la sienne.

   Le nombre de colonnes est DÉCIDÉ, pas déduit de la largeur. Un auto-fit
   suivait la place disponible et donnait 4 + 1 sur un grand écran, 3 + 1
   sur un petit : le rang du bas changeait de composition d'un écran à
   l'autre. Trois par rang tient le classement voulu — les trois Purgatory
   en haut, le reste en dessous — et le garde quel que soit l'écran. Une
   sixième pièce complétera la seconde rangée sans rien changer ici. */
.armr-grid{position:relative;display:grid;gap:var(--space-24);
  grid-template-columns:repeat(3,minmax(0,1fr))}
@media(max-width:1080px){
  .armr-grid{grid-template-columns:repeat(2,minmax(0,1fr))}
}
.armr-canvas{position:absolute;inset:0;width:100%;height:100%;z-index:2;pointer-events:none}
/* width/height explicites : un <canvas> est un élément remplaçable, il ne
   s'étire pas sur inset:0 comme le ferait une boîte ordinaire — sans elles
   il garderait sa taille intrinsèque de 300×150. */

.armr{position:relative;display:flex;flex-direction:column;
  background:var(--surface-1);border:var(--stroke-hairline) solid var(--border-hairline);
  border-radius:var(--radius-md);overflow:hidden}
.armr:focus-within{border-color:var(--border-default)}

/* Dans une console, l'état est une information de premier plan : le
   libellé prend donc la couleur de sa pastille, ce que .st ne fait pas
   ailleurs sur le site. */
.armr-head .st--warn{color:var(--color-warning)}
.armr-head .st--error{color:var(--color-primary)}
.armr-head{display:flex;align-items:center;gap:var(--space-8);
  padding:var(--space-8) var(--space-12);
  border-bottom:var(--stroke-hairline) solid var(--border-hairline);
  background:var(--surface-2)}
.armr-head .sp{flex:1}

/* La scène. Hauteur fixe, pas de ratio : la console doit garder la même
   stature quelle que soit la largeur de colonne, sinon deux consoles
   côte à côte n'ont pas la même hauteur de personnage. */
.armr-stage{position:relative;height:clamp(340px,54vh,470px);
  background:var(--surface-0);
  border-bottom:var(--stroke-hairline) solid var(--border-hairline);
  overflow:hidden}
.armr-slot{position:relative;width:100%;height:100%;
  cursor:grab;touch-action:pan-y;outline-offset:-2px}
.armr-slot:active{cursor:grabbing}
.armr-slot:focus-visible{outline:var(--stroke-strong) solid var(--color-primary)}

/* Trame de fond : grille technique + halo rouge, sous le rendu. */
.armr-scan{position:absolute;inset:0;z-index:1;pointer-events:none;
  background:
    radial-gradient(ellipse at 50% 62%,rgba(255,59,48,.10),transparent 62%),
    linear-gradient(var(--border-hairline) var(--stroke-hairline),transparent var(--stroke-hairline)) 0 0/100% 32px,
    linear-gradient(90deg,var(--border-hairline) var(--stroke-hairline),transparent var(--stroke-hairline)) 0 0/32px 100%,
    var(--surface-0)}
.armr-scan::after{content:'';position:absolute;inset:0;
  background:radial-gradient(ellipse at 50% 50%,transparent 45%,rgba(10,10,10,.85) 100%)}

/* Repères d'angle. Quatre coins tracés en pur CSS, à l'échelle de la
   console. La fenêtre en portait autrefois quatre du même genre ; ils ont
   été retirés, ceux-ci restent — ils cadrent une pièce, pas la page. */
.armr-hud{position:absolute;inset:var(--space-8);z-index:3;pointer-events:none}
.armr-hud>i{position:absolute;width:14px;height:14px;
  border:0 solid var(--color-primary);opacity:.45}
.armr-hud>i:nth-child(1){top:0;left:0;border-top-width:var(--stroke-strong);border-left-width:var(--stroke-strong)}
.armr-hud>i:nth-child(2){top:0;right:0;border-top-width:var(--stroke-strong);border-right-width:var(--stroke-strong)}
.armr-hud>i:nth-child(3){bottom:0;left:0;border-bottom-width:var(--stroke-strong);border-left-width:var(--stroke-strong)}
.armr-hud>i:nth-child(4){bottom:0;right:0;border-bottom-width:var(--stroke-strong);border-right-width:var(--stroke-strong)}

/* État de chargement, au centre de la scène. Retiré une fois le GLB posé. */
.armr-load{position:absolute;inset:0;z-index:3;display:grid;place-items:center;
  align-content:center;gap:var(--space-8);padding:var(--space-24);text-align:center}
.armr-load .bar{width:min(200px,70%)}
.armr-load p{font-family:var(--font-mono);font-size:12px;color:var(--text-secondary)}
.armr.is-ready .armr-load{display:none}

/* Barre de commande sous la scène. */
.armr-ctrl{display:flex;align-items:center;gap:var(--space-8);
  padding:var(--space-8) var(--space-12);
  border-bottom:var(--stroke-hairline) solid var(--border-hairline);
  background:var(--surface-2)}
.armr-ctrl .sp{flex:1}
.armr-hint{font-family:var(--font-mono);font-size:11px;color:var(--text-dim)}
.armr-btn{font-family:var(--font-ui);font-weight:600;font-size:var(--text-micro);
  letter-spacing:var(--tracking-micro);text-transform:uppercase;
  color:var(--text-secondary);background:var(--surface-3);
  border:var(--stroke-hairline) solid var(--border-default);border-radius:var(--radius-sm);
  padding:var(--space-4) var(--space-8);cursor:pointer;
  transition:color var(--dur-fast) var(--ease-mech),border-color var(--dur-fast) var(--ease-mech)}
.armr-btn:hover{color:var(--text-primary);border-color:var(--border-strong)}
.armr-btn[aria-pressed="true"]{color:var(--color-primary);border-color:var(--color-primary)}
.armr-btn:focus-visible{outline:var(--stroke-strong) solid var(--color-primary);outline-offset:2px}

.armr-body{padding:var(--space-16);flex:1}
.armr-sub{font-family:var(--font-mono);font-size:12px;color:var(--text-dim);
  margin-bottom:var(--space-12)}
.armr-tags{display:flex;flex-wrap:wrap;gap:var(--space-4);margin-top:var(--space-16)}

/* Repli sans WebGL. La scène cède la place à un rendu fixe de la même
   pièce, au même cadrage : la trame et les repères d'angle restent, seule
   la barre de commande s'en va — il n'y a plus rien à faire tourner. */
.armr-grid[data-fallback] .armr-ctrl{display:none}
.armr-poster{position:absolute;inset:0;z-index:2;
  width:100%;height:100%;object-fit:contain;object-position:center bottom;
  padding:var(--space-16) var(--space-16) 0;pointer-events:none}

@media(max-width:700px){
  /* Sous 700 px la colonne unique prend toute la largeur : le plafond de
     400 px laisserait une carte étroite au milieu d'un vide. */
  .armr-grid{grid-template-columns:1fr}
}
@media(max-width:640px){
  .armr-stage{height:clamp(320px,62vh,420px)}
  .armr-hint{display:none}
}

/* Sur téléphone, le chapeau du hero est retiré — la pastille d'organisation
   comme la phrase d'accroche. Entre le titre, les deux boutons et la console
   audio posée en bas, il ne restait plus de hauteur pour voir le personnage
   — or c'est lui qu'on vient regarder ; la pastille lui barrait le torse.
   Les deux propos sont repris tels quels dans le <title> et la meta
   description de la page, rien ne se perd pour les moteurs. Au-dessus de
   640 px ils restent affichés l'un et l'autre. */
@media(max-width:640px){
  .hero-tag,.hero-tagline{display:none}
}

/* ── 24. BOOT SEQUENCE ────────────────────────────────────────────────── */
.boot{position:fixed;inset:0;z-index:100;background:var(--surface-0);
  display:grid;place-items:center;gap:var(--space-16)}
.boot.is-done{animation:drk-fade-out var(--dur-base) var(--ease-in) forwards}
.boot-inner{display:flex;flex-direction:column;align-items:center;gap:var(--space-16);width:min(340px,80vw)}
/* L'écusson ouvre la séquence. Il est servi en dur dans le HTML, pas en
   fond CSS : c'est la première image de la page, elle doit partir avec le
   document et non attendre que la feuille de style soit analysée. */
.boot-mark{width:112px;height:112px;object-fit:contain;
  filter:drop-shadow(0 0 12px rgba(255,59,48,.35));
  animation:drk-flicker var(--dur-deliberate) var(--ease-linear) both}
.boot-logo{font-family:var(--font-display);font-weight:900;font-size:22px;letter-spacing:.22em;
  text-transform:uppercase;color:var(--color-primary);animation:drk-flicker var(--dur-deliberate) var(--ease-linear) both;
  animation-delay:120ms}
.boot-bar{width:100%;height:var(--stroke-strong);background:var(--surface-3);overflow:hidden}
.boot-bar>i{display:block;height:100%;background:var(--color-primary);box-shadow:var(--glow-primary);
  transform-origin:left;animation:drk-boot-bar var(--dur-boot) var(--ease-mech) forwards}
.boot-txt{font-family:var(--font-mono);font-size:12px;color:var(--text-secondary);min-height:1.4em}

/* ── 25. REDUCED MOTION ───────────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce){
  *,*::before,*::after{
    animation-duration:.01ms!important;
    animation-iteration-count:1!important;
    transition-duration:.01ms!important;
    scroll-behavior:auto!important}
  .drk-anim-pulse,.drk-anim-alarm,.scan-layer,.radar::after,.st>b,
  .alert--critical,.hero-loups::before,.hero-loups::after,
  .bar--indeterminate>i,.term-caret,.skel,.spinner{animation:none!important}
  .drk-reveal{opacity:1;transform:none}
  /* L'icône de coupure change d'état sans respirer ni glisser. */
  .nav-mute .nm-w1,.nav-mute .nm-w2{animation:none!important}
  .hero-hud .bar::after,.hero-hud .bar>i::after{animation:none!important}
  /* Vignettes : le geste n'a pas lieu, mais le dessin reste entier. */
  .app-card:hover .app-vig .ic,.app-card:focus-visible .app-vig .ic{transform:none}
  .app-card:hover .app-vig .fl,.app-card:focus-visible .app-vig .fl{stroke-dashoffset:0}
  /* Le vumètre ne bouge plus, mais reste lisible : allumé si ça joue. */
  .audio-deck .seg>s{animation:none!important;transform:none}
  .audio-deck.is-playing .seg>s{opacity:.5}
  .boot{display:none}
}
