/* ==========================================================================
   Plateforme Hackathon, système visuel
   Deux couleurs pilotent l'intégralité de l'interface : --brand et --accent,
   injectées par l'instance de hackathon. Tout le reste est dérivé en CSS, ce
   qui laisse le thème fonctionner en clair comme en sombre, en pastel comme
   en saturé, sans retoucher une seule règle.
   ========================================================================== */

/* ------------------------------------------------------------------ Polices */
@font-face { font-family: 'Archivo'; font-style: normal; font-weight: 500; font-display: swap;
  src: url('../fonts/archivo-500-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD; }
@font-face { font-family: 'Archivo'; font-style: normal; font-weight: 500; font-display: swap;
  src: url('../fonts/archivo-500-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF; }
@font-face { font-family: 'Archivo'; font-style: normal; font-weight: 600; font-display: swap;
  src: url('../fonts/archivo-600-latin.woff2') format('woff2'); }
@font-face { font-family: 'Archivo'; font-style: normal; font-weight: 700; font-display: swap;
  src: url('../fonts/archivo-700-latin.woff2') format('woff2'); }
@font-face { font-family: 'Archivo'; font-style: normal; font-weight: 800; font-display: swap;
  src: url('../fonts/archivo-800-latin.woff2') format('woff2'); }
@font-face { font-family: 'Archivo Ext'; font-style: normal; font-weight: 600; font-display: swap;
  src: url('../fonts/archivo-600-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA,U+1E00-1E9F,U+2C60-2C7F,U+A720-A7FF; }

@font-face { font-family: 'Plex'; font-style: normal; font-weight: 400; font-display: swap;
  src: url('../fonts/plexsans-400-latin.woff2') format('woff2'); }
@font-face { font-family: 'Plex'; font-style: normal; font-weight: 500; font-display: swap;
  src: url('../fonts/plexsans-500-latin.woff2') format('woff2'); }
@font-face { font-family: 'Plex'; font-style: normal; font-weight: 600; font-display: swap;
  src: url('../fonts/plexsans-600-latin.woff2') format('woff2'); }
@font-face { font-family: 'Plex'; font-style: normal; font-weight: 400; font-display: swap;
  src: url('../fonts/plexsans-400-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA,U+1E00-1E9F,U+2C60-2C7F,U+A720-A7FF; }
@font-face { font-family: 'Plex Mono'; font-style: normal; font-weight: 400; font-display: swap;
  src: url('../fonts/plexmono-400-latin.woff2') format('woff2'); }
@font-face { font-family: 'Plex Mono'; font-style: normal; font-weight: 500; font-display: swap;
  src: url('../fonts/plexmono-500-latin.woff2') format('woff2'); }
@font-face { font-family: 'Plex Mono'; font-style: normal; font-weight: 600; font-display: swap;
  src: url('../fonts/plexmono-600-latin.woff2') format('woff2'); }

/* ------------------------------------------------------------------- Jetons */
:root {
  --brand: #4432b0;
  --accent: #00bfa6;

  --display: 'Archivo', 'Archivo Ext', system-ui, sans-serif;
  --body: 'Plex', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --mono: 'Plex Mono', ui-monospace, 'SFMono-Regular', Menlo, monospace;

  --r: 4px;            /* rayon serré : plaques d'équipement, pas de bulles */
  --r-lg: 8px;
  --gap: 1.15rem;
  --plate-offset: 7px; /* décalage de la sous-plaque, signature du thème */
  --rail: 15.25rem;
  --wrap: 78rem;       /* largeur utile : suit la taille du texte, pas le pixel */

  /* Échelle de texte. Les libellés en capitales espacées ont besoin d'un
     plancher plus haut que le texte courant : sous 12 px, étirés et affichés en
     couleur douce, ils ne se lisent plus à distance normale d'un écran. */
  --t-micro: 0.76rem;
  --t-small: 0.875rem;

  --ok: oklch(0.60 0.15 152);
  --ko: oklch(0.58 0.20 25);
  --warn: oklch(0.72 0.16 72);
}

/* Repli pour les moteurs sans syntaxe de couleur relative. */
[data-mode='light'] {
  --brand-ui: var(--brand);
  --accent-ui: var(--accent);
  --canvas: color-mix(in oklab, var(--brand) 5%, #fff);
  --plate: color-mix(in oklab, var(--brand) 1.5%, #fff);
  --plate-2: color-mix(in oklab, var(--brand) 6%, #fff);
  --under: color-mix(in oklab, var(--brand) 34%, #fff);
  --ink: color-mix(in oklab, var(--brand) 22%, #0a0b10);
  --ink-soft: color-mix(in oklab, var(--brand) 26%, #5b6070);
  --hair: color-mix(in oklab, var(--brand) 20%, #dcdde6);
  --hair-strong: color-mix(in oklab, var(--brand) 38%, #c3c5d4);
  --on-brand: #fff;
  --on-accent: #0a0b10;
  --shadow: 0 1px 0 color-mix(in oklab, var(--brand) 12%, transparent);
  --grid: color-mix(in oklab, var(--brand) 8%, transparent);
}
[data-mode='dark'] {
  --brand-ui: color-mix(in oklab, var(--brand) 78%, #fff);
  --accent-ui: var(--accent);
  --canvas: color-mix(in oklab, var(--brand) 12%, #07080c);
  --plate: color-mix(in oklab, var(--brand) 13%, #101219);
  --plate-2: color-mix(in oklab, var(--brand) 18%, #141721);
  --under: color-mix(in oklab, var(--brand) 40%, #0b0d13);
  --ink: color-mix(in oklab, var(--brand) 8%, #f2f3f8);
  --ink-soft: color-mix(in oklab, var(--brand) 14%, #a3a8bb);
  --hair: color-mix(in oklab, var(--brand) 26%, #2a2e3c);
  --hair-strong: color-mix(in oklab, var(--brand) 40%, #3c4152);
  --on-brand: #fff;
  --on-accent: #0a0b10;
  --shadow: 0 1px 0 rgba(0, 0, 0, 0.5);
  --grid: color-mix(in oklab, var(--brand) 22%, transparent);
}

/* Version fine : la couleur relative normalise n'importe quel couple saisi par
   une école et calcule un texte lisible sur les aplats, clair ou foncé. */
@supports (color: oklch(from red l c h)) {
  [data-mode='light'] {
    --brand-ui: oklch(from var(--brand) clamp(0.2, l, 0.68) c h);
    --accent-ui: oklch(from var(--accent) clamp(0.3, l, 0.74) c h);
    --canvas: oklch(from var(--brand) 0.975 calc(c * 0.14) h);
    --plate: oklch(from var(--brand) 0.995 calc(c * 0.04) h);
    --plate-2: oklch(from var(--brand) 0.962 calc(c * 0.12) h);
    --under: oklch(from var(--brand) 0.845 calc(c * 0.55) h);
    --ink: oklch(from var(--brand) 0.19 calc(c * 0.4) h);
    --ink-soft: oklch(from var(--brand) 0.47 calc(c * 0.22) h);
    --hair: oklch(from var(--brand) 0.885 calc(c * 0.22) h);
    --hair-strong: oklch(from var(--brand) 0.76 calc(c * 0.3) h);
    --grid: oklch(from var(--brand) 0.9 calc(c * 0.3) h / 0.55);
  }
  [data-mode='dark'] {
    --brand-ui: oklch(from var(--brand) clamp(0.52, l, 0.86) c h);
    --accent-ui: oklch(from var(--accent) clamp(0.58, l, 0.9) c h);
    --canvas: oklch(from var(--brand) 0.145 calc(c * 0.26) h);
    --plate: oklch(from var(--brand) 0.196 calc(c * 0.2) h);
    --plate-2: oklch(from var(--brand) 0.235 calc(c * 0.24) h);
    --under: oklch(from var(--brand) 0.36 calc(c * 0.55) h);
    --ink: oklch(from var(--brand) 0.955 calc(c * 0.06) h);
    --ink-soft: oklch(from var(--brand) 0.73 calc(c * 0.12) h);
    --hair: oklch(from var(--brand) 0.32 calc(c * 0.28) h);
    --hair-strong: oklch(from var(--brand) 0.45 calc(c * 0.34) h);
    --grid: oklch(from var(--brand) 0.4 calc(c * 0.4) h / 0.5);
  }
  /* Bascule de contraste : au-delà de 62 % de clarté, le texte passe en foncé. */
  :root {
    --on-brand: oklch(from var(--brand-ui) clamp(0, calc((0.62 - l) * 100), 1) calc(c * 0.05) h);
    --on-accent: oklch(from var(--accent-ui) clamp(0, calc((0.62 - l) * 100), 1) calc(c * 0.05) h);
  }
}

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

/* Toute l'interface, texte, gouttières, marges intérieures, largeurs, est
   exprimée en rem. Cette seule déclaration règle donc l'échelle générale : sur un
   écran de bureau large, l'ensemble grandit ensemble au lieu de laisser un texte
   fixe flotter dans des blocs trop grands.
   Le calcul part de 1rem, c'est-à-dire de la taille choisie par le lecteur dans
   son navigateur, au lieu de la remplacer par une valeur en pixels : quelqu'un
   qui a augmenté sa police garde son réglage, majoré. */
html {
  font-size: clamp(1rem, 0.72rem + 0.35vw, 1.16rem);
  -webkit-text-size-adjust: 100%;
}
body {
  margin: 0;
  min-height: 100vh;
  background: var(--canvas);
  color: var(--ink);
  font-family: var(--body);
  font-size: 1rem;
  line-height: 1.58;
  font-feature-settings: 'kern' 1;
  -webkit-font-smoothing: antialiased;
}

/* Couches d'ambiance : plans géométriques francs, empilés, jamais flous. */
.ambient { position: fixed; inset: 0; z-index: 0; overflow: hidden; pointer-events: none; }
.ambient::before {
  content: ''; position: absolute; top: -14vh; right: -6vw; width: 62vw; height: 58vh;
  background:
    linear-gradient(146deg, color-mix(in oklab, var(--brand) 9%, transparent) 0 46%, transparent 46%),
    linear-gradient(196deg, color-mix(in oklab, var(--accent) 8%, transparent) 0 30%, transparent 30%);
  transform: skewY(-5deg);
}
.ambient::after {
  content: ''; position: absolute; inset: 0;
  background-image:
    linear-gradient(to right, var(--grid) 1px, transparent 1px),
    linear-gradient(to bottom, var(--grid) 1px, transparent 1px);
  background-size: 74px 74px;
  mask-image: linear-gradient(to bottom, #000 0, transparent 62%);
  opacity: 0.35;
}

a { color: inherit; }
h1, h2, h3, h4 { font-family: var(--display); margin: 0; letter-spacing: -0.02em; line-height: 1.1; }
h1 { font-size: clamp(1.7rem, 1.2rem + 1.8vw, 2.5rem); font-weight: 800; }
h2 { font-size: 1.34rem; font-weight: 700; }
h3 { font-size: 1.06rem; font-weight: 700; }
p { margin: 0 0 0.85em; }
code, kbd, pre, .mono { font-family: var(--mono); }

.eyebrow {
  font-family: var(--display); font-size: var(--t-micro); font-weight: 700;
  letter-spacing: 0.16em; text-transform: uppercase; color: var(--ink-soft);
}
.muted { color: var(--ink-soft); }
.small { font-size: var(--t-small); }
.num { font-family: var(--mono); font-variant-numeric: tabular-nums; }

:focus-visible {
  outline: 2px solid var(--accent-ui);
  outline-offset: 2px;
  border-radius: 2px;
}

/* ------------------------------------------------------------------- Coquille */
.shell { position: relative; z-index: 1; display: grid; grid-template-columns: var(--rail) 1fr; min-height: 100vh; }

/* Le rail ne défile jamais dans son ensemble : c'est la seule liste de liens qui
   défile, entre un en-tête et un pied restés en place. Un administrateur a une
   quinzaine d'entrées de menu, ce qui dépasse un écran de 1080 px de haut : sans
   cela, le bouton de déconnexion tomberait sous la ligne de flottaison. */
.rail {
  position: sticky; top: 0; align-self: start; height: 100vh;
  display: flex; flex-direction: column;
  background: var(--brand-ui); color: var(--on-brand);
  border-right: 1px solid color-mix(in oklab, var(--brand-ui) 60%, #000);
  overflow: hidden;
}
.rail__brand { flex: none; padding: 1.2rem 1.25rem 1rem;
  border-bottom: 1px solid color-mix(in oklab, var(--on-brand) 18%, transparent); }
.rail__mark {
  display: flex; align-items: center; gap: 10px;
  font-family: var(--display); font-weight: 800; font-size: 1.1rem; letter-spacing: -0.03em;
  text-decoration: none;
}
.rail__glyph {
  width: 1.9rem; height: 1.9rem; flex: none; display: grid; place-items: center;
  background: var(--accent-ui); color: var(--on-accent);
  clip-path: polygon(0 0, 100% 0, 100% 72%, 72% 100%, 0 100%);
  font-size: 0.9rem; font-weight: 800;
}
/* Logo choisi par l'administrateur. Sans nom à côté, il occupe l'essentiel de la
   largeur du menu (≈ 90 % du contenu, soit ~75 % du rail) et se centre. La hauteur
   est plafonnée pour qu'un logo très carré ne fasse pas exploser l'en-tête ;
   object-fit garde les proportions dans tous les cas. */
.rail__logo { width: 92%; max-width: 13rem; max-height: 5rem; height: auto;
  object-fit: contain; display: block; }
.rail__mark--logo { justify-content: center; }
.rail__event { margin-top: 0.75rem; font-size: var(--t-small); opacity: 0.78; line-height: 1.35; }
.rail__nav { padding: 0.85rem 0.75rem; display: flex; flex-direction: column; gap: 2px;
  flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain;
  scrollbar-width: thin; scrollbar-color: color-mix(in oklab, var(--on-brand) 34%, transparent) transparent; }
.rail__group { margin: 0.7rem 0.5rem 0.3rem; font-size: 0.72rem; letter-spacing: 0.18em; text-transform: uppercase;
  font-family: var(--display); font-weight: 700; opacity: 0.6; }
.rail__link {
  display: flex; align-items: center; gap: 0.7rem; padding: 0.46rem 0.75rem;
  text-decoration: none; border-radius: var(--r); font-size: 0.95rem; font-weight: 500;
  color: color-mix(in oklab, var(--on-brand) 82%, transparent);
  border-left: 2px solid transparent;
  transition: background 0.14s ease, color 0.14s ease;
}
.rail__link:hover { background: color-mix(in oklab, var(--on-brand) 10%, transparent); color: var(--on-brand); }
.rail__link.is-active {
  background: color-mix(in oklab, var(--on-brand) 14%, transparent);
  color: var(--on-brand); border-left-color: var(--accent-ui); font-weight: 600;
}
.rail__link svg { width: 1.1rem; height: 1.1rem; flex: none; }
.rail__badge {
  margin-left: auto; background: var(--accent-ui); color: var(--on-accent);
  font-size: 0.74rem; font-weight: 700; padding: 1px 0.4rem; border-radius: 2px; font-family: var(--mono);
}
.rail__foot { flex: none; padding: 0.85rem;
  border-top: 1px solid color-mix(in oklab, var(--on-brand) 18%, transparent); }
.rail__me { display: flex; align-items: center; gap: 0.62rem; margin-bottom: 0.62rem; }
.rail__me strong { display: block; font-size: 0.92rem; line-height: 1.2; }
.rail__me span { font-size: 0.8rem; opacity: 0.75; }

.avatar {
  width: 2rem; height: 2rem; flex: none; display: grid; place-items: center;
  background: color-mix(in oklab, var(--on-brand) 18%, transparent);
  font-family: var(--display); font-weight: 700; font-size: 0.8rem;
  clip-path: polygon(0 0, 100% 0, 100% 72%, 72% 100%, 0 100%);
}
.avatar--ink { background: var(--under); color: var(--ink); }

/* En thème sombre, un bandeau saturé écraserait le reste : le rail devient une
   plaque et la couleur principale ne sert plus qu'à marquer la page courante. */
[data-mode='dark'] .rail { background: var(--plate); color: var(--ink);
  border-right-color: var(--hair); }
[data-mode='dark'] .rail__brand, [data-mode='dark'] .rail__foot { border-color: var(--hair); }
[data-mode='dark'] .rail__link { color: var(--ink-soft); }
[data-mode='dark'] .rail__link:hover { background: var(--plate-2); color: var(--ink); }
[data-mode='dark'] .rail__link.is-active {
  background: color-mix(in oklab, var(--brand-ui) 26%, transparent); color: var(--ink); }
[data-mode='dark'] .rail .avatar { background: var(--plate-2); color: var(--ink); }

.main { min-width: 0; padding: 1.85rem clamp(1rem, 2.6vw, 2.4rem) 4.5rem; }
.wrap { max-width: var(--wrap); margin: 0 auto; }

.page-head { display: flex; flex-wrap: wrap; gap: 1.1rem; align-items: flex-end;
  justify-content: space-between; margin-bottom: 1.6rem; }
.page-head__actions { display: flex; gap: 0.5rem; flex-wrap: wrap; }
.page-head h1 { margin-top: 4px; }
.page-head p { margin: 0.4rem 0 0; max-width: 62ch; color: var(--ink-soft); }

/* --------------------------------------------------------------- Les plaques */
/* Chaque bloc est une plaque posée sur une sous-plaque teintée qui dépasse en
   bas à droite. C'est ce décalage, répété, qui donne la profondeur. */
.plate {
  position: relative;
  background: var(--plate);
  border: 1px solid var(--hair);
  border-radius: var(--r);
  padding: 1.2rem;
}
.plate::before {
  content: ''; position: absolute; z-index: -1;
  left: var(--plate-offset); top: var(--plate-offset); right: calc(var(--plate-offset) * -1);
  bottom: calc(var(--plate-offset) * -1);
  background: var(--under);
  border-radius: var(--r);
  transition: transform 0.18s ease;
}
.plate > * { position: relative; }
.plate--flat::before { display: none; }
.plate--accent::before { background: color-mix(in oklab, var(--accent-ui) 40%, var(--under)); }
.plate--tight { padding: 0.85rem 1rem; }
.plate--pad { padding: 1.55rem; }

.plate__head {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  margin: -1.2rem -1.2rem 1.1rem; padding: 0.8rem 1.2rem;
  border-bottom: 1px solid var(--hair); background: var(--plate-2);
  border-radius: var(--r) var(--r) 0 0;
}
.plate--pad .plate__head { margin: -1.55rem -1.55rem 1.35rem; padding: 0.9rem 1.55rem; }

.stack { display: grid; gap: calc(var(--gap) + var(--plate-offset)); }
.grid { display: grid; gap: calc(var(--gap) + var(--plate-offset)); }
.grid--2 { grid-template-columns: repeat(auto-fit, minmax(19rem, 1fr)); }
/* Le plafond de piste évite qu'une liste courte, deux catégories, deux équipes,
   ne s'étire en bandeaux sur un écran large. Le nombre de colonnes ne dépend que
   du minimum : il ne change pas, seule la croissance est bornée. */
.grid--3 { grid-template-columns: repeat(auto-fit, minmax(15.6rem, 24rem)); }
.grid--4 { grid-template-columns: repeat(auto-fit, minmax(11.9rem, 1fr)); }
/* La colonne latérale porte un formulaire ou un rappel : elle a une largeur
   confortable connue et n'a pas besoin de grandir au-delà. Tout le reste va à la
   colonne principale, qui contient les tableaux, c'est là que le manque de place
   coûte une colonne tronquée. */
.grid--sidebar { grid-template-columns: minmax(0, 1fr) minmax(17rem, 21rem); align-items: start; }

/* ----------------------------------------------------------------- Statistiques */
.stat { display: flex; flex-direction: column; gap: 0.2rem; }
.stat__label { font-family: var(--display); font-size: var(--t-micro); letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--ink-soft); font-weight: 700; }
.stat__value { font-family: var(--display); font-size: 2.15rem; font-weight: 800;
  letter-spacing: -0.035em; font-variant-numeric: tabular-nums; line-height: 1; }
.stat__value small { font-size: 0.9rem; font-weight: 600; color: var(--ink-soft); letter-spacing: 0; }
.stat__note { font-size: var(--t-small); color: var(--ink-soft); }

/* --------------------------------------------------- Dorsale de progression */
/* Une encoche par challenge de la catégorie : le pourcentage et le détail
   se lisent d'un seul coup d'œil. */
.spine { display: flex; flex-direction: column; gap: 3px; width: 9px; flex: none; }
.spine__seg {
  flex: 1; min-height: 6px; background: var(--hair);
  border-radius: 1px;
  transition: background 0.3s ease;
}
.spine__seg.is-on { background: var(--accent-ui); }
.spine--h { flex-direction: row; width: auto; height: 8px; }

.bar { height: 8px; background: var(--hair); border-radius: 1px; overflow: hidden; }
.bar__fill { height: 100%; background: var(--accent-ui); border-radius: 1px;
  transition: width 0.5s cubic-bezier(0.2, 0.8, 0.2, 1); }
.bar--brand .bar__fill { background: var(--brand-ui); }

/* -------------------------------------------------------- Cartes catégories */
.cat-card {
  display: flex; gap: 1rem; text-decoration: none; color: inherit;
  transition: transform 0.16s ease;
}
.cat-card:hover { transform: translate(-2px, -2px); }
.cat-card:hover::before { transform: translate(2px, 2px); }
.cat-card__body { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.cat-card__icon {
  width: 2.6rem; height: 2.6rem; display: grid; place-items: center; flex: none;
  background: color-mix(in oklab, var(--brand-ui) 12%, transparent);
  color: var(--brand-ui);
  clip-path: polygon(0 0, 100% 0, 100% 74%, 74% 100%, 0 100%);
  margin-bottom: 0.75rem;
}
.cat-card__icon svg { width: 1.3rem; height: 1.3rem; }
.cat-card h3 { font-size: 1.12rem; }
.cat-card__meta { margin-top: auto; padding-top: 0.85rem; display: flex; align-items: baseline;
  justify-content: space-between; gap: 10px; }
.cat-card__pct { font-family: var(--display); font-size: 1.6rem; font-weight: 800;
  letter-spacing: -0.03em; font-variant-numeric: tabular-nums; }

/* ------------------------------------------------------------ Difficultés */
.diff { display: inline-flex; align-items: center; gap: 7px; }
.diff__meter { display: inline-flex; gap: 2px; }
.diff__meter i { width: 5px; height: 0.85rem; background: var(--hair-strong); border-radius: 1px; display: block; }
.diff__meter i.is-on { background: var(--brand-ui); }
.diff[data-level='4'] .diff__meter i.is-on { background: var(--accent-ui); }
.diff__label { font-size: var(--t-small); color: var(--ink-soft); }

/* ------------------------------------------------------------------ Éléments */
.chip {
  display: inline-flex; align-items: center; gap: 0.35rem; padding: 0.2rem 0.55rem;
  font-size: 0.8rem; font-weight: 600; border-radius: 2px;
  background: var(--plate-2); border: 1px solid var(--hair); color: var(--ink-soft);
  font-family: var(--display); letter-spacing: 0.02em; white-space: nowrap;
}
.chip--ok { background: color-mix(in oklab, var(--ok) 14%, var(--plate)); color: var(--ok);
  border-color: color-mix(in oklab, var(--ok) 35%, transparent); }
.chip--ko { background: color-mix(in oklab, var(--ko) 12%, var(--plate)); color: var(--ko);
  border-color: color-mix(in oklab, var(--ko) 32%, transparent); }
.chip--warn { background: color-mix(in oklab, var(--warn) 16%, var(--plate)); color: var(--warn);
  border-color: color-mix(in oklab, var(--warn) 38%, transparent); }
.chip--brand { background: var(--brand-ui); color: var(--on-brand); border-color: transparent; }
.chip--accent { background: var(--accent-ui); color: var(--on-accent); border-color: transparent; }
.chip--dot::before { content: ''; width: 6px; height: 6px; border-radius: 50%; background: currentColor; }

.tick {
  width: 1.4rem; height: 1.4rem; flex: none; display: grid; place-items: center; border-radius: 2px;
  border: 1px solid var(--hair-strong); color: var(--ink-soft);
}
.tick svg { width: 0.82rem; height: 0.82rem; }
/* La coche est toujours dans le DOM pour que la bascule sans rechargement puisse
   l'allumer ; elle n'est visible qu'à l'état actif. */
.tick:not(.is-done) svg { display: none; }
.tick.is-done { background: var(--ok); border-color: var(--ok); color: #fff; }

/* -------------------------------------------------------------------- Boutons */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 0.5rem;
  padding: 0.55rem 1rem; border-radius: var(--r); border: 1px solid var(--hair-strong);
  background: var(--plate); color: var(--ink); cursor: pointer;
  font-family: var(--display); font-size: 0.92rem; font-weight: 600; letter-spacing: 0.01em;
  text-decoration: none; transition: transform 0.12s ease, background 0.12s ease, border-color 0.12s ease;
}
.btn:hover { border-color: var(--brand-ui); transform: translateY(-1px); }
.btn:active { transform: translateY(0); }
.btn svg { width: 0.95rem; height: 0.95rem; }
.btn--primary { background: var(--brand-ui); border-color: var(--brand-ui); color: var(--on-brand); }
.btn--primary:hover { background: color-mix(in oklab, var(--brand-ui) 86%, var(--ink)); }
.btn--accent { background: var(--accent-ui); border-color: var(--accent-ui); color: var(--on-accent); }
.btn--accent:hover { background: color-mix(in oklab, var(--accent-ui) 88%, var(--ink)); }
.btn--ghost { background: transparent; }
.btn--danger { color: var(--ko); border-color: color-mix(in oklab, var(--ko) 40%, transparent); }
.btn--danger:hover { background: color-mix(in oklab, var(--ko) 12%, transparent); border-color: var(--ko); }
.btn--sm { padding: 0.35rem 0.65rem; font-size: 0.84rem; }
.btn--block { width: 100%; }
.btn[disabled], .btn.is-disabled { opacity: 0.5; pointer-events: none; }

.btn-row { display: flex; gap: 0.5rem; flex-wrap: wrap; align-items: center; }

/* ----------------------------------------------------------------- Formulaires */
.field { display: flex; flex-direction: column; gap: 0.38rem; margin-bottom: 1rem; }
.field > label, .label {
  font-family: var(--display); font-size: var(--t-micro); font-weight: 700;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-soft);
}
.field__hint { font-size: var(--t-small); color: var(--ink-soft); }
input[type='text'], input[type='email'], input[type='number'], input[type='password'],
input[type='date'], input[type='datetime-local'], input[type='search'], select, textarea {
  width: 100%; padding: 0.55rem 0.75rem; font: inherit; font-size: 0.96rem;
  color: var(--ink); background: var(--plate-2);
  border: 1px solid var(--hair-strong); border-radius: var(--r);
  transition: border-color 0.12s ease, background 0.12s ease;
}
input:focus, select:focus, textarea:focus { border-color: var(--brand-ui); background: var(--plate); }
textarea { min-height: 7rem; resize: vertical; font-family: var(--body); }
textarea.mono, input.mono { font-family: var(--mono); font-size: 0.9rem; }
select { appearance: none;
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%),
                    linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: right 0.9rem center, right 0.62rem center;
  background-size: 5px 5px, 5px 5px; background-repeat: no-repeat; padding-right: 1.9rem; }
input[type='color'] { width: 100%; height: 2.6rem; padding: 3px; cursor: pointer; }
.check { display: flex; align-items: flex-start; gap: 0.55rem; margin-bottom: 0.75rem; font-size: 0.95rem; }
.check input { width: 1rem; height: 1rem; margin-top: 2px; accent-color: var(--brand-ui); flex: none; }
.field-row { display: grid; gap: 0.85rem; grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr)); }

fieldset { border: 1px solid var(--hair); border-radius: var(--r); padding: 1rem; margin: 0 0 1.1rem; }
legend { font-family: var(--display); font-size: var(--t-micro); font-weight: 700; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--ink-soft); padding: 0 0.5rem; }

/* --------------------------------------------------------------------- Tables */
.table-wrap { overflow-x: auto; margin: 0 -1.2rem -1.2rem; padding: 0 1.2rem 1.2rem; }
table { width: 100%; border-collapse: collapse; font-size: 0.94rem; }
th {
  text-align: left; font-family: var(--display); font-size: var(--t-micro); font-weight: 700;
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-soft);
  padding: 0.5rem 0.75rem; border-bottom: 1px solid var(--hair-strong); white-space: nowrap;
}
td { padding: 0.62rem 0.75rem; border-bottom: 1px solid var(--hair); vertical-align: middle; }
tbody tr:last-child td { border-bottom: none; }
tbody tr:hover td { background: var(--plate-2); }
td.num, th.num { text-align: right; font-variant-numeric: tabular-nums; }
.row-link { text-decoration: none; font-weight: 600; }
.row-link:hover { color: var(--brand-ui); text-decoration: underline; }
.is-me td { background: color-mix(in oklab, var(--accent-ui) 12%, transparent); }
.is-me td:first-child { box-shadow: inset 3px 0 0 var(--accent-ui); }

/* ---------------------------------------------------------------- Challenges */
.ch-row {
  display: flex; align-items: center; gap: 0.85rem; padding: 0.8rem 1rem;
  border-bottom: 1px solid var(--hair); text-decoration: none; color: inherit;
  transition: background 0.12s ease;
}
.ch-row:last-child { border-bottom: none; }
.ch-row:hover { background: var(--plate-2); }
.ch-row__title { font-weight: 600; font-size: 1.02rem; }
.ch-row__body { flex: 1; min-width: 0; }
.ch-row__meta { display: flex; gap: 0.85rem; align-items: center; flex-wrap: wrap; margin-top: 0.25rem; }
.ch-row__rate { text-align: right; flex: none; width: 6rem; }
.ch-row__rate b { font-family: var(--display); font-size: 1.05rem; font-variant-numeric: tabular-nums; }

.rate-mini { display: block; height: 4px; background: var(--hair-strong); border-radius: 1px;
  margin-top: 5px; overflow: hidden; }
.rate-mini i { display: block; height: 100%; background: var(--brand-ui); border-radius: 1px; }

/* --------------------------------------------------------------------- Divers */
.flash-zone { display: grid; gap: 0.5rem; margin-bottom: 1.35rem; }
.flash {
  display: flex; gap: 0.62rem; align-items: flex-start; padding: 0.7rem 0.95rem;
  border: 1px solid var(--hair-strong); border-left-width: 3px; border-radius: var(--r);
  background: var(--plate); font-size: 0.95rem;
}
.flash--success { border-left-color: var(--ok); }
.flash--error { border-left-color: var(--ko); }
.flash--info { border-left-color: var(--accent-ui); }

.kv { display: grid; grid-template-columns: auto 1fr; gap: 0.5rem 1.1rem; font-size: 0.95rem; align-items: baseline; }
.kv dt { font-family: var(--display); font-size: var(--t-micro); letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--ink-soft); font-weight: 700; white-space: nowrap; }
.kv dd { margin: 0; }

.prose { max-width: 72ch; }
.prose p { margin-bottom: 0.9em; }
.prose ul, .prose ol { margin: 0 0 1em; padding-left: 1.3em; }
.prose li { margin-bottom: 0.3em; }
.prose code { background: var(--plate-2); padding: 1px 5px; border-radius: 2px; font-size: 0.86em;
  border: 1px solid var(--hair); }
.prose h3 { margin: 1.4em 0 0.5em; }

pre.code {
  margin: 0; padding: 0.85rem 1rem; overflow-x: auto; font-size: 0.88rem; line-height: 1.6;
  background: var(--plate-2); border: 1px solid var(--hair); border-radius: var(--r);
  color: var(--ink);
}

.info-grid { display: grid; gap: 0.62rem; grid-template-columns: repeat(auto-fit, minmax(12.5rem, 1fr)); }
.info-cell { padding: 0.75rem 0.9rem; background: var(--plate-2); border: 1px solid var(--hair);
  border-radius: var(--r); border-left: 3px solid var(--accent-ui); }
.info-cell dt { font-family: var(--display); font-size: var(--t-micro); letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--ink-soft); font-weight: 700; }
.info-cell dd { margin: 0.2rem 0 0; font-family: var(--mono); font-size: 1rem; font-weight: 500;
  word-break: break-all; }

.empty { padding: 2.5rem 1.25rem; text-align: center; color: var(--ink-soft); }
.empty h3 { color: var(--ink); margin-bottom: 0.4rem; }
.empty svg { width: 1.9rem; height: 1.9rem; opacity: 0.4; margin-bottom: 0.62rem; }

.tabs { display: flex; gap: 0.25rem; flex-wrap: wrap; margin-bottom: calc(var(--gap) + var(--plate-offset)); }
.tabs a {
  padding: 0.45rem 0.85rem; text-decoration: none; border-radius: var(--r); font-size: 0.92rem;
  font-family: var(--display); font-weight: 600; color: var(--ink-soft);
  border: 1px solid transparent;
}
.tabs a:hover { background: var(--plate-2); color: var(--ink); }
.tabs a.is-active { background: var(--plate); border-color: var(--hair-strong); color: var(--ink); }

/* ------------------------------------------------------------------- Modale
   Ouverte par l'ancre de l'URL (:target), sans JavaScript : la fiche machine
   sort ainsi de la mise en page, ce qui rend au tableau toute sa largeur. */
.modal { position: fixed; inset: 0; z-index: 60; display: none; }
.modal:target { display: grid; place-items: center; padding: 1.5rem; }
.modal__backdrop { position: absolute; inset: 0;
  background: color-mix(in oklab, #05060a 62%, transparent); }
.modal__panel { position: relative; z-index: 1; width: min(37rem, 100%);
  max-height: 88vh; overflow-y: auto; }
.modal__panel .plate__head { position: sticky; top: 0; z-index: 1; }
@media (prefers-reduced-motion: no-preference) {
  .modal:target .modal__panel { animation: rise 0.22s cubic-bezier(0.2, 0.8, 0.2, 1); }
}

.timeline { border-left: 2px solid var(--hair); padding-left: 18px; display: grid; gap: 16px; }
.timeline__item { position: relative; }
.timeline__item::before {
  content: ''; position: absolute; left: -24px; top: 6px; width: 9px; height: 9px;
  background: var(--accent-ui); border-radius: 50%;
  box-shadow: 0 0 0 3px var(--canvas);
}

.sparkbars { display: flex; align-items: flex-end; gap: 3px; height: 3.9rem; }
.sparkbars i { flex: 1; background: var(--brand-ui); border-radius: 1px 1px 0 0; min-height: 2px;
  opacity: 0.85; }
.sparkbars i:hover { opacity: 1; background: var(--accent-ui); }

.split { display: flex; align-items: center; justify-content: space-between; gap: 0.75rem; }
.stackline { display: grid; gap: 0.75rem; }
.rank-big { font-family: var(--display); font-weight: 800; letter-spacing: -0.04em;
  font-size: clamp(2.4rem, 1.6rem + 2.6vw, 3.4rem); line-height: 0.9; font-variant-numeric: tabular-nums; }
.rank-big span { font-size: 0.4em; color: var(--ink-soft); letter-spacing: 0; }

.badge-rank { display: inline-grid; place-items: center; width: 1.65rem; height: 1.65rem;
  font-family: var(--display); font-weight: 800; font-size: 0.86rem; background: var(--plate-2);
  border: 1px solid var(--hair-strong); border-radius: 2px; }
.badge-rank[data-top='1'] { background: var(--accent-ui); color: var(--on-accent); border-color: transparent; }
.badge-rank[data-top='2'], .badge-rank[data-top='3'] {
  background: color-mix(in oklab, var(--accent-ui) 30%, var(--plate)); border-color: transparent; }

/* --------------------------------------------------------------- Connexion */
.auth { display: grid; grid-template-columns: 1.05fr 1fr; min-height: 100vh; position: relative; z-index: 1; }
.auth__side {
  background: var(--brand-ui); color: var(--on-brand); padding: clamp(28px, 5vw, 64px);
  display: flex; flex-direction: column; justify-content: space-between; position: relative; overflow: hidden;
}
/* Décor du panneau : le motif de plaque du reste du site, une plaque à coin
   biseauté posée sur une sous-plaque décalée en bas à droite. Rien qu'des aplats.
   L'ancien cadre au trait fin, découpé par le clip-path, ne montrait que des bouts
   de bordure et se lisait comme une image cassée. */
.auth__side::before,
.auth__side::after {
  content: ''; position: absolute; aspect-ratio: 1; pointer-events: none;
  width: min(42%, 300px);
  clip-path: polygon(0 0, 100% 0, 100% 70%, 70% 100%, 0 100%);
}
/* La sous-plaque, en accent, dépasse d'un cran en bas à droite. */
.auth__side::before {
  right: calc(14% - 14px); bottom: calc(15% - 14px);
  background: color-mix(in oklab, var(--accent-ui) 78%, transparent);
}
/* La plaque de dessus, teinte claire, laisse voir l'accent au coin décalé. */
.auth__side::after {
  right: 14%; bottom: 15%;
  background: color-mix(in oklab, var(--on-brand) 15%, var(--brand-ui));
}
/* Logo sur la page de connexion : mis en avant, nettement plus grand que dans le
   rail. Il domine le panneau d'accueil. */
.auth__logo { height: clamp(4.5rem, 9vw, 7.5rem); width: auto; max-width: 100%;
  object-fit: contain; display: block; }
.auth__pitch { position: relative; z-index: 1; max-width: 30ch; }
.auth__pitch h1 { font-size: clamp(2rem, 1.4rem + 2.4vw, 3.1rem); margin-bottom: 14px; }
.auth__pitch p { opacity: 0.85; }
.auth__form { display: grid; place-items: center; padding: clamp(28px, 5vw, 64px); }
.auth__box { width: min(25rem, 100%); }
.otp-input {
  font-family: var(--mono); font-size: 1.7rem; letter-spacing: 0.5em; text-align: center;
  padding: 0.85rem 0.75rem 0.85rem 1.4rem;
}

/* ------------------------------------------------------------------ Animation */
@keyframes rise { from { opacity: 0; transform: translateY(9px); } to { opacity: 1; transform: none; } }
.anim > * { animation: rise 0.4s cubic-bezier(0.2, 0.8, 0.2, 1) backwards; }
.anim > *:nth-child(1) { animation-delay: 0.02s; }
.anim > *:nth-child(2) { animation-delay: 0.06s; }
.anim > *:nth-child(3) { animation-delay: 0.1s; }
.anim > *:nth-child(4) { animation-delay: 0.14s; }
.anim > *:nth-child(5) { animation-delay: 0.18s; }
.anim > *:nth-child(n + 6) { animation-delay: 0.22s; }

/* ----------------------------------------------------------------- Responsive */
@media (max-width: 1020px) {
  .shell { grid-template-columns: 1fr; }
  .rail { position: static; height: auto; flex-direction: column; border-right: none;
    border-bottom: 1px solid color-mix(in oklab, var(--brand-ui) 60%, #000); }
  .rail__brand { display: flex; align-items: center; justify-content: space-between; gap: 1rem;
    border-bottom: none; padding-bottom: 0.75rem; }
  .rail__event { margin: 0; text-align: right; }
  .rail__nav { flex-direction: row; gap: 0.25rem; padding: 0 0.75rem 0.75rem; }
  .rail__group { display: none; }
  .rail__link { white-space: nowrap; border-left: none; border-bottom: 2px solid transparent; }
  .rail__link.is-active { border-bottom-color: var(--accent-ui); }
  .rail__foot { display: flex; align-items: center; justify-content: space-between; gap: 0.75rem; }
  .rail__me { margin-bottom: 0; }
  .grid--sidebar { grid-template-columns: 1fr; }
  .auth { grid-template-columns: 1fr; }
  .auth__side { min-height: 230px; }
}
@media (max-width: 620px) {
  :root { --plate-offset: 5px; }
  .main { padding: 1.35rem 0.85rem 3.5rem; }
  .plate { padding: 1rem; }
  .plate__head { margin: -1rem -1rem 0.85rem; padding: 0.7rem 1rem; }
  .table-wrap { margin: 0 -1rem -1rem; padding: 0 1rem 1rem; }
  .ch-row { flex-wrap: wrap; }
  .ch-row__rate { width: auto; text-align: left; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important; }
}

@media print {
  .rail, .page-head__actions, .flash-zone { display: none; }
  .shell { grid-template-columns: 1fr; }
  .plate::before, .ambient { display: none; }
}
