/* SyncLift — FORGE × CARNET.
   Source de vérité des tokens : design/SyncLift 2a.dc.html (:root).
   Aucune valeur de couleur/rayon/police ne doit être écrite ailleurs. */
@import url('https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600&display=swap');

:root{
  /* Le thème est sombre de bout en bout : sans cette déclaration, les contrôles natifs
     (`<select>` et sa liste déroulante, cases, barres de défilement) gardent les couleurs
     système claires et `--ink` devient illisible dessus. */
  color-scheme:dark;

  --bg:#121110;
  --panel:#1d1b19;
  /* Fond de champ opaque : l'ancien blanc à 5% se composait sur le fond blanc natif d'un
     `<select>` et redonnait du blanc. Valeur = --panel + 5% de --ink, aplatis. */
  --field:#26231f;
  --ink:#f2efec;
  --mut:rgba(242,239,236,.5);
  --mut2:rgba(242,239,236,.35);
  --bd:rgba(242,239,236,.12);
  --acc:#ff3b1f;
  --grn:#3ddc84;
  --gk:'JetBrains Mono',ui-monospace,monospace;
  --gs:'Space Grotesk',system-ui,sans-serif;

  --r-card:16px;
  --r-dialog:18px;
  --r-field:8px;
  --r-pill:99px;
  --r-badge:4px;
  --r-sheet:24px;

  --gap:18px;
  --pad-card:22px;
  --pad-page:34px 32px 40px;

  --ease:cubic-bezier(.22,1,.36,1);
}

*{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{margin:0;background:var(--bg);color:var(--ink);font-family:var(--gs);font-size:14px;line-height:1.5;-webkit-font-smoothing:antialiased}
a{color:var(--ink);text-decoration:none;transition:color .15s}
a:hover{color:var(--acc)}
h1,h2,h3{margin:0;font-weight:600}
p{margin:0}
:focus-visible{outline:2px solid var(--acc);outline-offset:2px}

/* ─── Animations ────────────────────────────────────────────── */
@keyframes fadeUp{from{opacity:0;transform:translateY(14px)}to{opacity:1;transform:none}}
@keyframes rowIn{from{opacity:0;transform:translateX(-8px)}to{opacity:1;transform:none}}
@keyframes sweepX{from{transform:scaleX(0)}to{transform:scaleX(1)}}
@keyframes growBar{from{transform:scaleY(0)}to{transform:scaleY(1)}}
@keyframes drawLine{to{stroke-dashoffset:0}}
@keyframes popDot{from{opacity:0;transform:scale(0)}to{opacity:1;transform:scale(1)}}
@keyframes blink{0%,100%{opacity:1}50%{opacity:.2}}
@keyframes pulse{0%,100%{box-shadow:0 0 0 0 rgba(255,59,31,.5)}70%{box-shadow:0 0 0 9px rgba(255,59,31,0)}}
@keyframes sheetUp{from{transform:translateY(100%)}to{transform:none}}
@keyframes fadeIn{from{opacity:0}to{opacity:1}}
@keyframes spin{to{transform:rotate(360deg)}}

.stg>*{animation:fadeUp .5s var(--ease) both}
.stg>*:nth-child(1){animation-delay:.04s}
.stg>*:nth-child(2){animation-delay:.1s}
.stg>*:nth-child(3){animation-delay:.16s}
.stg>*:nth-child(4){animation-delay:.22s}
.stg>*:nth-child(5){animation-delay:.28s}
.stg>*:nth-child(6){animation-delay:.34s}
.stg>*:nth-child(n+7){animation-delay:.4s}

.rowstg tr{animation:rowIn .4s ease both}
.rowstg tr:nth-child(1){animation-delay:.05s}
.rowstg tr:nth-child(2){animation-delay:.1s}
.rowstg tr:nth-child(3){animation-delay:.15s}
.rowstg tr:nth-child(4){animation-delay:.2s}
.rowstg tr:nth-child(5){animation-delay:.25s}
.rowstg tr:nth-child(6){animation-delay:.3s}
.rowstg tr:nth-child(7){animation-delay:.35s}
.rowstg tr:nth-child(n+8){animation-delay:.4s}

/* ─── Shell ─────────────────────────────────────────────────── */
.topnav{display:flex;align-items:center;gap:20px;padding:18px 32px;border-bottom:1px solid var(--bd);position:sticky;top:0;background:rgba(18,17,16,.85);backdrop-filter:blur(10px);z-index:20}
.brand{font:700 17px var(--gs);letter-spacing:-.01em}
.brand span{color:var(--acc)}
/* Le logo est un lien vers l'accueil, mais garde ses deux couleurs au survol : la règle
   `a:hover` repeindrait « SYNC » en accent, et un lockup qui change de teinte au passage
   de la souris se lit comme un défaut. Le curseur suffit à signaler le lien. */
a.brand:hover{color:var(--ink)}
.topnav-links{display:flex;gap:4px;margin-left:auto}
.navlink{font:500 13px var(--gs);padding:7px 14px;border-radius:var(--r-pill);color:var(--mut);cursor:pointer;transition:background .15s,color .15s}
.navlink:hover{background:rgba(242,239,236,.08);color:var(--ink)}
.navlink[aria-current="page"]{background:var(--acc);color:var(--bg)}
.appmain{padding:var(--pad-page);max-width:1080px;margin:0 auto;display:flex;flex-direction:column;gap:var(--gap)}
.tabbar{display:none;position:fixed;bottom:0;left:0;right:0;background:rgba(18,17,16,.92);backdrop-filter:blur(12px);border-top:1px solid var(--bd);padding:8px 6px 10px;z-index:20}
.tabbar a{flex:1;text-align:center;padding:6px 0;min-height:44px;font:600 10px var(--gk);letter-spacing:.08em;text-transform:uppercase;color:var(--mut);border-top:3px solid transparent}
.tabbar a[aria-current="page"]{color:var(--acc);border-top-color:var(--acc)}

/* ─── Typographie ───────────────────────────────────────────── */
.kicker{font:600 10px var(--gk);letter-spacing:.12em;text-transform:uppercase;color:var(--mut);display:block}
.kicker--acc{color:var(--acc)}
.h1big{font:600 40px/1.1 var(--gs);letter-spacing:-.02em;margin:10px 0 18px}
.h2{font:600 20px var(--gs);letter-spacing:-.01em}
.mono{font-family:var(--gk)}
.num{font:500 13px var(--gk);text-align:right}
.num--acc{color:var(--acc)}
.muted{color:var(--mut)}
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
.txt-sm{font-size:13px}
.txt-xs{font-size:12.5px}

/* ─── Surfaces publiques (connexion) ────────────────────────── */
/* Composition fer à gauche, calée sur la hauteur d'écran : une carte centrée serait le
   réflexe, et c'est précisément le cliché de l'écran de connexion. */
/* Le cadre porte la composition : marque en haut, contenu au centre, mentions en pied.
   Une pile unique flotterait au milieu du vide sans jamais s'appuyer sur l'écran. */
body.public{min-height:100vh;min-height:100svh;display:grid;grid-template-rows:auto 1fr auto;
  gap:32px;padding:30px 32px 26px;max-width:720px;margin:0 auto}
.public-main{display:flex;flex-direction:column;align-items:flex-start;justify-content:center;gap:26px}
/* Le titre et son filet forment un bloc : resserrés entre eux, détachés du reste. */
.login-titre .h1big{margin:12px 0 0}
.rule{display:block;height:3px;width:88px;margin-top:20px;background:var(--acc);border-radius:var(--r-pill);transform-origin:left;animation:sweepX .8s .3s cubic-bezier(.4,0,.2,1) both}
.public-foot{padding-top:22px;border-top:1px solid var(--bd)}

/* ─── Cartes ────────────────────────────────────────────────── */
.hcard{background:var(--panel);border:1px solid var(--bd);border-radius:var(--r-card);padding:var(--pad-card);display:flex;flex-direction:column;gap:10px;transition:transform .18s,border-color .18s,box-shadow .25s}
.hcard:hover{transform:translateY(-2px);border-color:rgba(242,239,236,.28)}
.hcard--alert{border-color:rgba(255,59,31,.4)}
.hcard--ok{border-color:rgba(61,220,132,.4)}
.hcard--accent{background:var(--acc);color:var(--bg);border-color:transparent}
/* Encre pleine, pas atténuée : sur l'aplat accent ce kicker porte le nom de l'exercice,
   et rgba(18,17,16,.8) ne mesurait que 4,29:1 pour du 10px en majuscules. */
.hcard--accent .kicker,.hcard--accent .muted{color:var(--bg)}
.hcard--muted{opacity:.55}
.bar{flex:1;border-radius:3px 3px 0 0;background:rgba(18,17,16,.55);transform-origin:bottom}
.hcard-title{font:600 20px var(--gs);letter-spacing:-.01em}

.g-split{display:grid;gap:var(--gap);grid-template-columns:1fr 1fr}
.g-2{display:grid;gap:var(--gap);grid-template-columns:1fr 1fr}
.g-3{display:grid;gap:var(--gap);grid-template-columns:1fr 1fr 1fr}

/* ─── Hero ──────────────────────────────────────────────────── */
.hero-bar{height:4px;background:rgba(242,239,236,.12);border-radius:var(--r-pill);overflow:hidden}
.hero-bar>i{display:block;height:100%;background:var(--acc);transform-origin:left;animation:sweepX 1s .5s cubic-bezier(.4,0,.2,1) both}

/* ─── Tables ────────────────────────────────────────────────── */
.tblwrap{margin-top:14px;border:1px solid var(--bd);border-radius:12px;overflow:hidden}
table{width:100%;border-collapse:collapse;font:400 13px var(--gs)}
thead tr{font:600 10px var(--gk);letter-spacing:.1em;text-transform:uppercase;color:var(--mut)}
th{text-align:left;padding:10px 22px;font-weight:600}
th.num,td.num{text-align:right}
tbody tr{border-top:1px solid var(--bd)}
td{padding:12px 22px}
td.sub,th.sub{padding:12px;color:var(--mut)}

/* ─── Pills, badges, pastilles ──────────────────────────────── */
.pill{display:inline-flex;align-items:center;gap:5px;font:600 10px var(--gk);letter-spacing:.06em;text-transform:uppercase;padding:4px 9px;border-radius:var(--r-pill);border:1px solid transparent;white-space:nowrap}
.pill--ok{background:rgba(61,220,132,.16);color:var(--grn)}
.pill--alert{border-color:rgba(255,59,31,.5);color:var(--acc)}
.pill--neutral{border-color:var(--bd);color:var(--mut)}
.pill--solid{background:var(--acc);color:var(--bg);font-size:9px;padding:3px 8px}
.badge-key{font:600 8px var(--gk);letter-spacing:.06em;text-transform:uppercase;border:1px solid rgba(255,59,31,.5);color:var(--acc);padding:1px 4px;border-radius:var(--r-badge)}
.dot{width:8px;height:8px;border-radius:50%;flex:none;display:inline-block;background:var(--mut2)}
.dot--ok{background:var(--grn)}
.dot--alert{background:var(--acc)}
.dot--blink{animation:blink 1.4s infinite}

/* ─── Boutons & champs ──────────────────────────────────────── */
.cta{display:inline-flex;align-items:center;justify-content:center;gap:8px;cursor:pointer;border:1px solid transparent;font:700 13px var(--gs);padding:11px 18px;border-radius:var(--r-pill);min-height:44px;transition:transform .15s,background .15s,color .15s,box-shadow .2s}
.cta:hover{transform:translateY(-1px)}
.cta--primary{background:var(--acc);color:var(--bg)}
.cta--primary:hover{background:var(--ink);color:var(--bg)}
.cta--ghost{background:transparent;border-color:var(--bd);color:var(--ink)}
.cta--ghost:hover{border-color:rgba(242,239,236,.32);color:var(--ink)}
.cta--pulse{animation:pulse 2s 1.2s infinite}
.cta--block{flex:1;text-align:center;padding:12px}
.cta[disabled]{opacity:.5;cursor:progress;transform:none}
.tap{cursor:pointer;transition:transform .12s}
.tap:active{transform:scale(.97)}

.field{background:var(--field);border:1px solid var(--bd);border-radius:var(--r-field);color:var(--ink);font:400 13px var(--gs);padding:10px 12px;min-height:44px;width:100%}
/* Une `<option>` n'hérite ni du fond ni de l'encre de son `<select>` : sans cette règle, la
   liste déroulante reste aux couleurs système sur les navigateurs qui ignorent color-scheme. */
.field option{background:var(--panel);color:var(--ink)}
/* Sur l'aplat accent (mini-graphe), le champ garde le fond des autres écrans : --bg y était
   plus sombre que partout ailleurs et cognait avec le rouge. */
.hcard--accent .field{color:var(--ink);border-color:transparent}
.field::placeholder{color:var(--mut2)}
.field:focus{border-color:var(--acc)}
.field:focus-visible{outline:2px solid var(--acc);outline-offset:2px}
label.kicker{margin-bottom:6px}

.toggle{width:36px;height:20px;border-radius:var(--r-pill);background:rgba(242,239,236,.15);position:relative;flex:none;cursor:pointer;border:0;transition:background .18s}
.toggle::before{content:'';position:absolute;inset:-12px}
/* L'état vient de la case cochée, pas d'un attribut rendu par le serveur : le bouton
   doit bouger au clic, sans attendre l'aller-retour HTMX. */
.toggle:has(input:checked){background:var(--acc)}
.toggle>i{position:absolute;top:2px;left:2px;width:15px;height:15px;border-radius:50%;background:var(--ink);transition:transform .18s}
.toggle:has(input:checked)>i{transform:translateX(17px)}
.toggle:focus-within{outline:2px solid var(--acc);outline-offset:2px}

.spinner{display:none;width:12px;height:12px;border:2px solid rgba(18,17,16,.3);border-top-color:currentColor;border-radius:50%;animation:spin .7s linear infinite}
.cta[disabled] .spinner{display:inline-block}
/* Message d'attente : masqué au repos, révélé le temps de la requête HTMX. Deux sélecteurs
   car htmx pose .htmx-request sur l'élément déclencheur (message imbriqué) ou sur la cible
   d'un hx-indicator explicite (message voisin du bouton). */
.htmx-indicator{display:none}
.htmx-request .htmx-indicator,.htmx-request.htmx-indicator{display:inline-flex;align-items:center;gap:8px}
.htmx-indicator .spinner{display:inline-block}

/* ─── Dialog ────────────────────────────────────────────────── */
/* `<dialog>` ouvert par showModal() : le voile est le ::backdrop natif, le centrage vient des
   marges auto par défaut. Le padding est porté par .dialog-inner pour que la zone cliquable
   « hors contenu » du dialogue reste le voile et non une bordure du panneau. */
.dialog{background:var(--panel);color:var(--ink);border:1px solid var(--bd);border-radius:var(--r-dialog);padding:0;width:min(560px,100%);max-height:86vh;overflow:auto;animation:fadeUp .35s var(--ease) both}
.dialog::backdrop{background:rgba(8,7,6,.7);animation:fadeIn .2s both}
.dialog-inner{padding:26px;display:flex;flex-direction:column;gap:14px}
.dialog-title{font:600 20px var(--gs);letter-spacing:-.01em}
.dialog-actions{display:flex;gap:10px;margin-top:4px}
.sheet-handle{display:none}

/* ─── Accordéons ────────────────────────────────────────────── */
/* Le repli est porté par <details> natif : il fonctionne sans JavaScript et
   n'a pas besoin d'animer une hauteur. */
summary::-webkit-details-marker{display:none}
.acc-chevron{display:inline-block;transition:transform .3s;color:var(--mut)}
details[open] .acc-chevron{transform:rotate(180deg)}

/* ─── États vides ───────────────────────────────────────────── */
.empty{border:1px dashed var(--bd);border-radius:var(--r-card);padding:26px;display:flex;flex-direction:column;gap:10px;align-items:flex-start;color:var(--mut)}

/* ─── Responsive ────────────────────────────────────────────── */
@media(max-width:760px){
  :root{--gap:12px;--pad-card:18px;--pad-page:22px 18px 96px}
  .topnav{padding:16px 18px}
  .topnav-links{display:none}
  .tabbar{display:flex}
  .g-split,.g-2,.g-3{grid-template-columns:1fr}
  .h1big{font-size:26px}
  .hidesm{display:none}
  .tblwrap{overflow-x:auto}
  th,td{padding:10px 14px}
  /* Bottom sheet : les marges auto du dialogue le collent en bas plutôt que de le centrer. */
  .dialog{width:100%;max-width:100%;max-height:82vh;margin:auto auto 0;border-radius:var(--r-sheet) var(--r-sheet) 0 0;border-left:0;border-right:0;border-bottom:0;animation:sheetUp .35s var(--ease) both}
  .dialog-inner{padding:22px 18px}
  .sheet-handle{display:block;width:40px;height:4px;border-radius:var(--r-pill);background:var(--bd);margin:0 auto 6px}
  .hcard:hover{transform:none}
}

/* ─── Accessibilité motion ──────────────────────────────────── */
@media(prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.001ms!important;animation-iteration-count:1!important;transition-duration:.001ms!important;animation-delay:0s!important}
  .hero-bar>i{transform:none}
}
