/* ============================================================================
   FleetDeck — Design System (monochrome / black & white)
   Chargé UNE fois depuis base.html. Tokens sous namespace --ds-*.
   Porte l'identité même si le CDN Tailwind est bloqué (dégradation gracieuse).
   ========================================================================== */
@layer tokens, base, components, pages;

@layer tokens {
  :root {
    /* Encre & papier + MARQUE (indigo primaire, cyan télémétrie/live) */
    --ds-black: #000000;
    --ds-ink: hsl(224 32% 13%);
    --ds-ink-2: hsl(224 18% 32%);
    --ds-ink-soft: hsl(220 12% 46%);
    --ds-paper: #ffffff;
    --ds-surface: hsl(222 24% 98%);
    --ds-surface-2: hsl(220 20% 95.5%);
    --ds-line: hsl(222 20% 90%);
    --ds-line-2: hsl(222 20% 88%);
    --ds-on-primary: #ffffff;             /* texte sur surfaces de marque (indigo/cyan) */

    /* Marque (charpente façon shadcn, teinte Fleetdeck) */
    --ds-primary: hsl(245 66% 60%);       /* indigo */
    --ds-primary-strong: hsl(245 66% 54%);
    --ds-accent: hsl(190 82% 42%);        /* cyan — télémétrie / live */
    --ds-ring: hsl(245 66% 60%);          /* focus + glow alignés sur la marque */
    --ds-destructive: hsl(0 74% 52%);
    --ds-success: hsl(152 48% 40%);
    --ds-warning: hsl(36 92% 44%);

    /* États de flotte — colorés (indigo/cyan/rouge/ambre) */
    --ds-state-running: hsl(190 82% 42%);  /* live = cyan */
    --ds-state-stopped: hsl(222 16% 80%);
    --ds-state-error: hsl(0 74% 52%);
    --ds-state-unknown: hsl(220 20% 95.5%);
    --ds-state-rebooting: hsl(36 92% 44%);

    /* Typo */
    --ds-font-sans: "Inter", ui-sans-serif, system-ui, -apple-system, sans-serif;
    --ds-font-mono: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;

    /* Rythme (base 4/8) */
    --ds-r1: 0.25rem; --ds-r2: 0.5rem; --ds-r3: 0.75rem; --ds-r4: 1rem;
    --ds-r6: 1.5rem; --ds-r8: 2rem; --ds-r12: 3rem;
    --ds-radius: 8px;
    --ds-radius-sm: 6px;

    /* ---- Échelle typographique — SOURCE UNIQUE, éditable ----
       `--ds-fs` = facteur global. 1 = tailles nominales ; 0.75 = −25% (défaut demandé).
       Change UNE valeur ici pour rescaler toute la typo du site. Aucun composant ne
       déclare de font-size en dur : tout référence ces tokens (ou les classes .fs-*). */
    --ds-fs: 0.75;
    --ds-text-2xs:  calc(0.68rem   * var(--ds-fs));
    --ds-text-xs:   calc(0.75rem   * var(--ds-fs));
    --ds-text-sm:   calc(0.85rem   * var(--ds-fs));
    --ds-text-base: calc(0.9375rem * var(--ds-fs));
    --ds-text-md:   calc(1.0625rem * var(--ds-fs));
    --ds-text-lg:   calc(1.2rem    * var(--ds-fs));
    --ds-text-xl:   calc(1.6rem    * var(--ds-fs));
    --ds-text-2xl:  calc(2rem      * var(--ds-fs));
    --ds-text-3xl:  calc(2.6rem    * var(--ds-fs));

    --ds-sidebar-w: 248px;
    --ds-topbar-h: 60px;

    /* Motion — courbes & durées partagées (source unique). */
    --ds-ease-out: cubic-bezier(0.25, 1, 0.5, 1);
    --ds-ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
    --ds-motion-page: 300ms;   /* transition d'écran (slide horizontal) */
    --ds-motion-card: 260ms;   /* entrée des cartes (slide-up + fade)  */
    --ds-motion-glow: 4s;      /* orbite du glow d'invitation           */
  }

  @media (prefers-color-scheme: dark) {
    :root {
      --ds-black: #ffffff;
      --ds-ink: hsl(220 22% 94%);
      --ds-ink-2: hsl(220 16% 70%);
      --ds-ink-soft: hsl(220 12% 60%);
      --ds-paper: hsl(224 28% 10.5%);
      --ds-surface: hsl(224 32% 8%);
      --ds-surface-2: hsl(223 22% 16%);
      --ds-line: hsl(223 20% 20%);
      --ds-line-2: hsl(223 20% 24%);
      --ds-on-primary: #ffffff;
      --ds-primary: hsl(245 78% 70%);
      --ds-primary-strong: hsl(245 78% 64%);
      --ds-accent: hsl(190 78% 54%);
      --ds-ring: hsl(245 78% 70%);
      --ds-destructive: hsl(0 72% 60%);
      --ds-success: hsl(152 46% 52%);
      --ds-warning: hsl(38 92% 58%);
      --ds-state-running: hsl(190 78% 54%);
      --ds-state-stopped: hsl(223 20% 34%);
      --ds-state-error: hsl(0 72% 60%);
      --ds-state-unknown: hsl(223 22% 16%);
      --ds-state-rebooting: hsl(38 92% 58%);
    }
  }
}

@layer base {
  * { box-sizing: border-box; }
  html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }
  body {
    margin: 0;
    font-family: var(--ds-font-sans);
    font-size: var(--ds-text-base);
    line-height: 1.5;
    color: var(--ds-ink);
    background: var(--ds-paper);
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
  }
  a { color: inherit; text-decoration: none; }
  h1, h2, h3 { margin: 0; font-weight: 600; letter-spacing: -0.02em; line-height: 1.15; }
  h1 { font-size: var(--ds-text-xl); }
  h2 { font-size: var(--ds-text-lg); }
  code, .mono { font-family: var(--ds-font-mono); font-feature-settings: "tnum" 1; }
  :focus-visible { outline: 2px solid var(--ds-ring); outline-offset: 2px; border-radius: 3px; }
  @media (prefers-reduced-motion: reduce) {
    * { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; }
  }
}

@layer components {
  /* ---- Shell : sidebar + topbar + content ------------------------------ */
  .app {
    display: grid;
    grid-template-columns: var(--ds-sidebar-w) 1fr;
    grid-template-rows: var(--ds-topbar-h) 1fr;
    grid-template-areas: "sidebar topbar" "sidebar main";
    min-height: 100vh;
  }
  .sidebar {
    grid-area: sidebar;
    border-right: 1px solid var(--ds-line);
    background: var(--ds-paper);
    display: flex; flex-direction: column;
    position: sticky; top: 0; height: 100vh;
  }
  .topbar {
    grid-area: topbar;
    border-bottom: 1px solid var(--ds-line);
    background: color-mix(in srgb, var(--ds-paper) 88%, transparent);
    backdrop-filter: saturate(120%) blur(6px);
    display: flex; align-items: center; gap: var(--ds-r4);
    padding: 0 var(--ds-r6);
    position: sticky; top: 0; z-index: 20;
  }
  #app-main { grid-area: main; padding: var(--ds-r8) var(--ds-r6); max-width: 1180px; view-transition-name: ds-content; }

  /* ---- Brand ----------------------------------------------------------- */
  .brand { display: flex; align-items: center; gap: var(--ds-r3); padding: var(--ds-r6); }
  .brand__mark {
    width: 30px; height: 30px; border-radius: 8px;
    background: var(--ds-primary); color: var(--ds-on-primary);
    display: grid; place-items: center; font-weight: 700; font-size: var(--ds-text-base);
    font-family: var(--ds-font-mono);
  }
  .brand__name { font-weight: 650; letter-spacing: -0.02em; }
  .brand__name span { color: var(--ds-ink-soft); font-weight: 500; }

  /* ---- Nav ------------------------------------------------------------- */
  .nav { display: flex; flex-direction: column; gap: 2px; padding: var(--ds-r2) var(--ds-r3); }
  .nav__label {
    font-size: var(--ds-text-2xs); text-transform: uppercase; letter-spacing: 0.08em;
    color: var(--ds-ink-soft); padding: var(--ds-r4) var(--ds-r3) var(--ds-r2);
  }
  .nav a {
    display: flex; align-items: center; gap: var(--ds-r3);
    padding: var(--ds-r2) var(--ds-r3); border-radius: var(--ds-radius-sm);
    color: var(--ds-ink-2); font-size: var(--ds-text-base); font-weight: 500;
    transition: background 0.12s ease, color 0.12s ease;
    min-height: 40px;
  }
  .nav a:hover { background: var(--ds-surface-2); color: var(--ds-ink); }
  .nav a.is-active { background: var(--ds-primary); color: var(--ds-on-primary); }
  .nav__icon { width: 17px; height: 17px; stroke-width: 1.8; flex: none; }
  .sidebar__foot { margin-top: auto; padding: var(--ds-r4); border-top: 1px solid var(--ds-line); }

  /* ---- Buttons --------------------------------------------------------- */
  .btn {
    display: inline-flex; align-items: center; justify-content: center; gap: var(--ds-r2);
    height: 38px; padding: 0 var(--ds-r4); border-radius: var(--ds-radius-sm);
    border: 1px solid var(--ds-line-2); background: var(--ds-paper); color: var(--ds-ink);
    font: inherit; font-size: var(--ds-text-base); font-weight: 550; cursor: pointer;
    transition: background 0.12s ease, border-color 0.12s ease, transform 0.06s ease;
    touch-action: manipulation; -webkit-tap-highlight-color: transparent;
  }
  .btn:hover { background: var(--ds-surface-2); border-color: var(--ds-ink-soft); }
  .btn:active { transform: translateY(1px); }
  .btn--primary { background: var(--ds-primary); color: var(--ds-on-primary); border-color: var(--ds-primary); }
  .btn--primary:hover { background: var(--ds-primary-strong); border-color: var(--ds-primary-strong); }
  .btn--sm { height: 32px; padding: 0 var(--ds-r3); font-size: var(--ds-text-sm); }
  .btn[disabled] { opacity: 0.45; cursor: not-allowed; }

  /* ---- Cards / surfaces ------------------------------------------------ */
  .card {
    border: 1px solid var(--ds-line); border-radius: var(--ds-radius);
    background: var(--ds-paper);
  }
  .card__pad { padding: var(--ds-r6); }
  .grid { display: grid; gap: var(--ds-r4); }
  .grid--stats { grid-template-columns: repeat(4, 1fr); }
  .stat { padding: var(--ds-r6); }
  .stat__num { font-family: var(--ds-font-mono); font-size: var(--ds-text-2xl); font-weight: 600; letter-spacing: -0.03em; }
  .stat__label { color: var(--ds-ink-soft); font-size: var(--ds-text-sm); margin-top: var(--ds-r1); }
  .stat--accent { background: var(--ds-primary); color: var(--ds-on-primary); border-color: var(--ds-primary); }
  .stat--accent .stat__label { color: color-mix(in srgb, var(--ds-on-primary) 70%, transparent); }

  /* ---- Section headers ------------------------------------------------- */
  .page-head { display: flex; align-items: flex-end; justify-content: space-between; gap: var(--ds-r4); margin-bottom: var(--ds-r6); }
  .eyebrow { font-family: var(--ds-font-mono); font-size: var(--ds-text-xs); text-transform: uppercase; letter-spacing: 0.1em; color: var(--ds-ink-soft); }
  .muted { color: var(--ds-ink-soft); }

  /* ---- Fleet strip (SIGNATURE) : cellules d'instances par état, en gris - */
  .strip {
    display: grid; grid-template-columns: repeat(auto-fill, minmax(30px, 1fr));
    gap: 6px; padding: var(--ds-r6);
  }
  .cell {
    aspect-ratio: 3 / 4; border-radius: 4px; border: 1px solid var(--ds-line-2);
    position: relative; background: var(--ds-state-unknown);
    transition: transform 0.1s ease;
  }
  .cell:hover { transform: translateY(-2px) scale(1.04); z-index: 2; }
  .cell[data-state="running"]  { background: var(--ds-state-running); border-color: var(--ds-state-running); }
  .cell[data-state="stopped"]  { background: var(--ds-state-stopped); }
  .cell[data-state="rebooting"]{ background: var(--ds-state-rebooting); }
  .cell[data-state="error"]    { background: var(--ds-state-error); border-color: var(--ds-state-error); }
  /* erreur = hachures diagonales pour se distinguer sans couleur (color-not-only) */
  .cell[data-state="error"]::after {
    content: ""; position: absolute; inset: 0; border-radius: 3px;
    background: repeating-linear-gradient(45deg, transparent 0 3px, var(--ds-paper) 3px 4px);
    opacity: 0.5;
  }

  .legend { display: flex; flex-wrap: wrap; gap: var(--ds-r4); padding: 0 var(--ds-r6) var(--ds-r6); }
  .legend__item { display: flex; align-items: center; gap: var(--ds-r2); font-size: var(--ds-text-xs); color: var(--ds-ink-soft); }
  .legend__swatch { width: 12px; height: 14px; border-radius: 3px; border: 1px solid var(--ds-line-2); }

  /* ---- Table ----------------------------------------------------------- */
  .table { width: 100%; border-collapse: collapse; font-size: var(--ds-text-base); }
  .table th {
    text-align: left; font-weight: 550; color: var(--ds-ink-soft);
    font-size: var(--ds-text-xs); text-transform: uppercase; letter-spacing: 0.05em;
    padding: var(--ds-r3) var(--ds-r4); border-bottom: 1px solid var(--ds-line);
  }
  .table td { padding: var(--ds-r3) var(--ds-r4); border-bottom: 1px solid var(--ds-line); }
  .table tr:hover td, .row-link:hover td { background: var(--ds-surface); cursor: pointer; }
  .table .mono { color: var(--ds-ink-2); }

  /* ---- Badge d'état (texte, pas que la couleur) ------------------------ */
  .badge {
    display: inline-flex; align-items: center; gap: 6px;
    font-family: var(--ds-font-mono); font-size: var(--ds-text-xs); letter-spacing: 0.02em;
    padding: 3px 8px; border-radius: 999px; border: 1px solid var(--ds-line-2);
    color: var(--ds-ink-2); text-transform: uppercase;
  }
  .badge::before { content: ""; width: 7px; height: 7px; border-radius: 999px; background: var(--ds-ink-soft); }
  .badge[data-state="running"]::before { background: var(--ds-state-running); }
  .badge[data-state="stopped"]::before { background: var(--ds-state-stopped); }
  .badge[data-state="error"]::before { background: var(--ds-state-error); box-shadow: 0 0 0 2px var(--ds-paper), 0 0 0 3px var(--ds-state-error); }

  /* ---- Forms ----------------------------------------------------------- */
  .field { display: flex; flex-direction: column; gap: var(--ds-r2); margin-bottom: var(--ds-r4); }
  .field label { font-size: var(--ds-text-sm); font-weight: 550; }
  .input {
    height: 42px; padding: 0 var(--ds-r3); border: 1px solid var(--ds-line-2);
    border-radius: var(--ds-radius-sm); background: var(--ds-paper); color: var(--ds-ink);
    font: inherit; font-size: var(--ds-text-base); width: 100%;
  }
  .input:focus { outline: none; border-color: var(--ds-ring); box-shadow: 0 0 0 3px color-mix(in srgb, var(--ds-ring) 18%, transparent); }
  .field__error { color: var(--ds-ink); font-size: var(--ds-text-sm); font-weight: 550; }
  .field__error::before { content: "→ "; }

  /* ---- Toasts ---------------------------------------------------------- */
  #toasts {
    position: fixed; right: var(--ds-r6); bottom: var(--ds-r6); z-index: 60;
    display: flex; flex-direction: column; gap: var(--ds-r2); max-width: 360px;
  }
  .toast {
    background: var(--ds-ink); color: var(--ds-paper);
    padding: var(--ds-r3) var(--ds-r4); border-radius: var(--ds-radius-sm);
    font-size: var(--ds-text-base); box-shadow: 0 6px 24px rgba(0,0,0,0.18);
    animation: toast-in 0.18s ease;
  }
  .toast--error { background: var(--ds-ink); border: 1px solid var(--ds-destructive); }
  .toast--warning { border: 1px solid var(--ds-paper); }
  .toast--persist { display: flex; align-items: flex-start; gap: .6rem; }
  .toast__close {
    margin-left: auto; background: transparent; border: 0; color: inherit;
    opacity: .7; cursor: pointer; padding: 0; display: inline-flex; line-height: 1;
  }
  .toast__close:hover { opacity: 1; }
  @keyframes toast-in { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }

  /* ---- Drawer ---------------------------------------------------------- */
  .drawer__scrim {
    position: fixed; inset: 0; background: rgba(0,0,0,0.5); z-index: 40;
  }
  .drawer__panel {
    position: fixed; top: 0; right: 0; height: 100vh; width: min(440px, 92vw);
    background: var(--ds-paper); border-left: 1px solid var(--ds-line); z-index: 50;
    padding: var(--ds-r8); overflow-y: auto;
    animation: drawer-in 0.2s ease;
  }
  @keyframes drawer-in { from { transform: translateX(100%); } to { transform: none; } }

  /* ---- Login ----------------------------------------------------------- */
  .auth { min-height: 100vh; display: grid; place-items: center; padding: var(--ds-r6); }
  .auth__card { width: 100%; max-width: 380px; }
}

@layer pages {
  /* Mobile-first : sous 900px la sidebar devient une barre de nav en bas */
  @media (max-width: 900px) {
    .app {
      grid-template-columns: 1fr;
      grid-template-rows: var(--ds-topbar-h) 1fr auto;
      grid-template-areas: "topbar" "main" "sidebar";
    }
    .sidebar {
      position: sticky; bottom: 0; top: auto; height: auto;
      flex-direction: row; border-right: 0; border-top: 1px solid var(--ds-line);
      overflow-x: auto; z-index: 30;
    }
    .brand, .nav__label, .sidebar__foot { display: none; }
    .nav { flex-direction: row; padding: var(--ds-r2); }
    .nav a { flex-direction: column; gap: 3px; font-size: var(--ds-text-2xs); min-width: 68px; text-align: center; }
    .nav__icon { width: 20px; height: 20px; }
    #app-main { padding: var(--ds-r6) var(--ds-r4); }
    .grid--stats { grid-template-columns: repeat(2, 1fr); }
  }
  @media (max-width: 560px) {
    .page-head { flex-direction: column; align-items: flex-start; }
  }
}

/* --- Anti-double-clic / état de chargement (htmx) -----------------------
   Pendant une requête htmx, le formulaire initiateur reçoit .htmx-request :
   on désactive visuellement son bouton de soumission et on bloque les clics,
   ce qui évite les doubles soumissions sur les actions longues (IA, génération). */
form.htmx-request button[type="submit"],
button.htmx-request[type="submit"] {
  opacity: 0.55;
  pointer-events: none;
  cursor: progress;
}

/* =======================================================================
   Passe de raffinement UX (motion) — atmosphère préservée, monochrome.
   Tout est désactivé sous prefers-reduced-motion.
   ======================================================================= */

/* --- Icônes Lucide (SVG inline, currentColor) --- */
.lucide { vertical-align: -2px; flex: 0 0 auto; }

/* --- Transitions de page « sur rails » (View Transitions API + HTMX) ----
   La zone #app-main (ds-content) glisse : l'ancien sort à gauche, le nouveau
   entre par la droite. Retour arrière (.nav-back sur <html>) : sens inversé.
   Sidebar/topbar restent fixes (hors #app-main). */
@keyframes ds-shell-exit-left  { to   { transform: translateX(-22%); opacity: 0; } }
@keyframes ds-shell-enter-right{ from { transform: translateX(22%);  opacity: 0; } }
@keyframes ds-shell-exit-right { to   { transform: translateX(22%);  opacity: 0; } }
@keyframes ds-shell-enter-left { from { transform: translateX(-22%); opacity: 0; } }

::view-transition-old(ds-content){ animation: ds-shell-exit-left  var(--ds-motion-page) var(--ds-ease-out) both; }
::view-transition-new(ds-content){ animation: ds-shell-enter-right var(--ds-motion-page) var(--ds-ease-out) both; }
.nav-back::view-transition-old(ds-content){ animation-name: ds-shell-exit-right; }
.nav-back::view-transition-new(ds-content){ animation-name: ds-shell-enter-left; }

/* --- Entrée des cartes (slide-up + fade, cascade légère) ----------------
   CSS pur via @starting-style : fonctionne aussi sur les fragments injectés
   par HTMX, sans JS. Le stagger est plafonné pour ne pas faire attendre. */
.card-enter{
  transition: opacity var(--ds-motion-card) var(--ds-ease-out),
              transform var(--ds-motion-card) var(--ds-ease-out);
  transition-delay: calc(min(var(--stagger, 0), 8) * 40ms);
}
@starting-style{
  .card-enter{ opacity: 0; transform: translateY(10px); }
}

/* --- Glow d'invitation (étapes de profil/onboarding non remplies) --------
   Bordure conique qui circule, discrète (teinte encre, faible intensité). */
@property --ds-glow-angle{ syntax: "<angle>"; inherits: false; initial-value: 0deg; }
.attn-glow{ position: relative; isolation: isolate; }
.attn-glow::before{
  content: ""; position: absolute; inset: -1.5px; padding: 1.5px;
  border-radius: inherit; pointer-events: none; z-index: -1;
  background: conic-gradient(from var(--ds-glow-angle),
      color-mix(in srgb, var(--ds-primary) 0%, transparent) 0deg,
      color-mix(in srgb, var(--ds-primary) 0%, transparent) 60deg,
      color-mix(in srgb, var(--ds-accent) 70%, transparent) 120deg,
      color-mix(in srgb, var(--ds-primary) 90%, transparent) 150deg,
      color-mix(in srgb, var(--ds-accent) 70%, transparent) 180deg,
      color-mix(in srgb, var(--ds-primary) 0%, transparent) 250deg,
      color-mix(in srgb, var(--ds-primary) 0%, transparent) 360deg);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
          mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
          mask-composite: exclude;
  animation: ds-glow-orbit var(--ds-motion-glow) linear infinite;
}
@keyframes ds-glow-orbit{ to { --ds-glow-angle: 360deg; } }

/* --- Repli / accessibilité ---------------------------------------------- */
@media (prefers-reduced-motion: reduce){
  ::view-transition-old(ds-content),
  ::view-transition-new(ds-content){ animation: none; }
  .card-enter{ transition: none; }
  .attn-glow::before{ animation: none; }
  /* respiration douce à la place de l'orbite */
  .attn-glow{ animation: ds-attn-breathe 2.6s var(--ds-ease-in-out) infinite; }
  @keyframes ds-attn-breathe{
    0%,100%{ box-shadow: 0 0 0 0 color-mix(in srgb, var(--ds-ring) 0%, transparent); }
    50%    { box-shadow: 0 0 0 3px color-mix(in srgb, var(--ds-ring) 16%, transparent); }
  }
}

/* ============================================================
   Skeletons & progression — chargement des wizards (CLS-safe)
   Affichés uniquement pendant une requête htmx (form.htmx-request).
   Monochrome : tokens --ds-*. Repli statique en reduced-motion.
   ============================================================ */
.ds-loading{ display:none; }
form.htmx-request .ds-loading{ display:block; }

.ds-sk{ position:relative; overflow:hidden; background:var(--ds-surface-2);
  border-radius:var(--ds-r2); }
.ds-sk::after{ content:""; position:absolute; inset:0; transform:translateX(-100%);
  background:linear-gradient(90deg, transparent, rgba(255,255,255,.55), transparent);
  animation:ds-shimmer 1.5s infinite; }
@media (prefers-color-scheme: dark){
  .ds-sk::after{ background:linear-gradient(90deg, transparent, rgba(255,255,255,.08), transparent); }
}
::selection{ background: color-mix(in srgb, var(--ds-primary) 22%, transparent); }
.ds-sk--line{ height:11px; margin:8px 0; }
.ds-sk--title{ height:15px; width:42%; margin:2px 0 14px; }
.ds-sk--block{ height:84px; border-radius:var(--ds-radius); }
.ds-sk--pill{ height:22px; width:72px; border-radius:999px; }
@keyframes ds-shimmer{ to{ transform:translateX(100%); } }

.ds-think{ display:inline-flex; gap:5px; align-items:center; }
.ds-think span{ width:7px; height:7px; border-radius:50%; background:var(--ds-ink-soft);
  animation:ds-think 1.2s var(--ds-ease-in-out) infinite; }
.ds-think span:nth-child(2){ animation-delay:.18s; }
.ds-think span:nth-child(3){ animation-delay:.36s; }
@keyframes ds-think{ 0%,100%{ transform:translateY(0); opacity:.4; } 50%{ transform:translateY(-4px); opacity:1; } }

.ds-progress{ height:5px; border-radius:999px; background:var(--ds-line);
  overflow:hidden; position:relative; }
.ds-progress::after{ content:""; position:absolute; top:0; height:100%; width:40%;
  border-radius:inherit; background:var(--ds-primary); animation:ds-progress-slide 1.3s var(--ds-ease-in-out) infinite; }
@keyframes ds-progress-slide{ 0%{ left:-40%; } 100%{ left:100%; } }

@media (prefers-reduced-motion: reduce){
  .ds-sk::after, .ds-think span, .ds-progress::after{ animation:none; }
  .ds-progress::after{ left:0; width:100%; opacity:.35; }
}

/* ============================================================
   Utilitaires typographiques — taille de police UNIQUEMENT via
   les tokens root (--ds-text-*), donc éditable centralement et
   réduite de 25% par --ds-fs. Aucun font-size en dur ailleurs.
   ============================================================ */
.fs-2xs{ font-size:var(--ds-text-2xs); }
.fs-xs{  font-size:var(--ds-text-xs); }
.fs-sm{  font-size:var(--ds-text-sm); }
.fs-base{ font-size:var(--ds-text-base); }
.fs-md{  font-size:var(--ds-text-md); }
.fs-lg{  font-size:var(--ds-text-lg); }
.fs-xl{  font-size:var(--ds-text-xl); }
.fs-2xl{ font-size:var(--ds-text-2xl); }
.fs-3xl{ font-size:var(--ds-text-3xl); }
.fw-400{ font-weight:400; }
.fw-500{ font-weight:500; }
.fw-600{ font-weight:600; }
.fw-650{ font-weight:650; }

/* ---- Champs déplacés depuis les templates (plus de <style> inline) ---- */
.dna-f{ display:flex; flex-direction:column; gap:var(--ds-r1); font-size:var(--ds-text-sm); color:var(--ds-ink-soft); }
.dna-f input, .dna-f textarea{ color:var(--ds-ink); }
#app-main form .input,
#app-main form input[type="password"],
#app-main form input[type="text"]{
  width:100%; height:42px; padding:0 var(--ds-r3); border:1px solid var(--ds-line-2);
  border-radius:var(--ds-radius-sm); background:var(--ds-paper); color:var(--ds-ink);
  font:inherit; font-size:var(--ds-text-base);
}

/* ============================================================
   Assistant permanent — drawer droite (voix + écrit, rendu progressif)
   Additif : position fixe, n'affecte pas le flux des pages.
   ============================================================ */
#assistant-toggle{
  position:fixed; right:var(--ds-r4); bottom:var(--ds-r4); z-index:69;
  width:48px; height:48px; border-radius:999px; border:none; cursor:pointer;
  background:var(--ds-primary); color:var(--ds-on-primary);
  display:grid; place-items:center; box-shadow:0 8px 24px rgba(0,0,0,.18);
  transition:transform var(--ds-motion-card) var(--ds-ease-out);
}
#assistant-toggle:hover{ transform:translateY(-2px); }

#assistant-panel{
  position:fixed; top:0; right:0; height:100dvh; width:min(370px, 94vw); z-index:70;
  background:var(--ds-paper); border-left:1px solid var(--ds-line);
  display:flex; flex-direction:column;
  transform:translateX(100%); transition:transform var(--ds-motion-page) var(--ds-ease-out);
  box-shadow:-14px 0 44px rgba(0,0,0,.10);
}
#assistant-panel.is-open{ transform:translateX(0); }

.assistant__head{ display:flex; align-items:center; justify-content:space-between;
  padding:var(--ds-r3) var(--ds-r4); border-bottom:1px solid var(--ds-line); }
.assistant__title{ display:flex; align-items:center; gap:var(--ds-r2);
  font-weight:600; font-size:var(--ds-text-md); }

.assistant__log{ flex:1; overflow-y:auto; padding:var(--ds-r4);
  display:flex; flex-direction:column; gap:var(--ds-r3); scroll-behavior:smooth; }
.amsg{ display:flex; max-width:92%; }
.amsg--user{ align-self:flex-end; }
.amsg--ai{ align-self:flex-start; }
.abub{ padding:var(--ds-r2) var(--ds-r3); border-radius:var(--ds-radius);
  font-size:var(--ds-text-base); line-height:1.5; word-wrap:break-word; }
.amsg--user .abub{ background:var(--ds-primary); color:var(--ds-on-primary);
  border-bottom-right-radius:var(--ds-r1); }
.amsg--ai .abub{ background:var(--ds-surface-2); color:var(--ds-ink);
  border:1px solid var(--ds-line); border-bottom-left-radius:var(--ds-r1); }
.abub code{ font-family:var(--ds-font-mono); font-size:var(--ds-text-xs);
  background:var(--ds-surface); padding:1px 4px; border-radius:var(--ds-radius-sm); }
.abub.typing::after{ content:""; display:inline-block; width:6px; height:1em; vertical-align:-2px;
  margin-left:2px; background:var(--ds-primary); border-radius:1px; animation:ds-blink 1s steps(2) infinite; }
@keyframes ds-blink{ 50%{ opacity:0; } }

.assistant__chips{ display:flex; gap:var(--ds-r2); flex-wrap:wrap; padding:0 var(--ds-r4) var(--ds-r2); }
.achip{ font-size:var(--ds-text-xs); padding:4px 10px; border:1px solid var(--ds-line);
  border-radius:999px; background:var(--ds-paper); color:var(--ds-ink-soft); cursor:pointer;
  transition:border-color .14s var(--ds-ease-out), color .14s var(--ds-ease-out); }
.achip:hover{ border-color:var(--ds-ring); color:var(--ds-ink); }

.assistant__foot{ border-top:1px solid var(--ds-line); padding:var(--ds-r3);
  display:flex; gap:var(--ds-r2); align-items:flex-end; }
.assistant__input{ flex:1; resize:none; max-height:120px; line-height:1.4; padding-top:8px; padding-bottom:8px; }
#assistant-voice.is-rec{ color:var(--ds-destructive); border-color:var(--ds-destructive); }

@media (prefers-reduced-motion: reduce){
  #assistant-panel{ transition:none; }
  #assistant-toggle{ transition:none; }
  .abub.typing::after{ animation:none; }
}

/* ---- Canvas nodal du pipeline (étape révision) ---- */
.pnodes{ display:flex; align-items:stretch; gap:0; flex-wrap:wrap; margin-bottom:1.25rem; }
.pnode{ flex:1; min-width:92px; background:var(--ds-surface); border:1px solid var(--ds-line);
  border-radius:var(--ds-radius); padding:var(--ds-r3); text-align:center; }
.pnode--accent{ border-color:var(--ds-primary); box-shadow:0 0 0 1px color-mix(in srgb, var(--ds-primary) 30%, transparent); }
.pnode__k{ font-size:var(--ds-text-2xs); text-transform:uppercase; letter-spacing:.08em; color:var(--ds-ink-soft); }
.pnode__v{ font-size:var(--ds-text-md); font-weight:600; margin-top:2px; color:var(--ds-ink);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.pnode__link{ align-self:center; flex:0 0 auto; width:22px; height:2px; background:var(--ds-line-2); position:relative; }
.pnode__link::after{ content:""; position:absolute; right:-1px; top:-3px;
  border:4px solid transparent; border-left-color:var(--ds-primary); }
@media (max-width:640px){ .pnode__link{ display:none; } .pnodes{ gap:var(--ds-r2); } }

/* ---- Sélecteur de projet (shell, R1) ---- */
.projsel{ padding:0 var(--ds-r4) var(--ds-r3); }
.projsel__label{ font-size:var(--ds-text-2xs); text-transform:uppercase; letter-spacing:.08em;
  color:var(--ds-ink-soft); margin-bottom:4px; font-weight:600; }
.projsel__select{ width:100%; height:34px; }

/* ---- Écran « Mes projets » (Phase 2) ---- */
.projgrid{ display:grid; grid-template-columns:repeat(auto-fill, minmax(240px, 1fr)); gap:var(--ds-r4); }
.projcard{ border:1px solid var(--ds-line); border-radius:var(--ds-radius); background:var(--ds-paper);
  padding:var(--ds-r4); display:flex; flex-direction:column; gap:var(--ds-r3);
  transition:border-color .14s var(--ds-ease-out), box-shadow .14s var(--ds-ease-out); }
.projcard:hover{ border-color:var(--ds-line-2); }
.projcard.is-active{ border-color:var(--ds-primary); box-shadow:0 0 0 1px color-mix(in srgb, var(--ds-primary) 30%, transparent); }
.projcard__hit{ text-align:left; background:none; border:none; padding:0; cursor:pointer;
  display:flex; flex-direction:column; gap:var(--ds-r2); width:100%; color:inherit; }
.projcard__name{ font-size:var(--ds-text-md); font-weight:600; color:var(--ds-ink); }
.projcard__url{ color:var(--ds-ink-soft); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.projcard__pills{ display:flex; flex-wrap:wrap; gap:var(--ds-r1); margin-top:2px; }
.pill{ font-size:var(--ds-text-2xs); padding:2px 8px; border-radius:999px;
  background:var(--ds-surface-2); color:var(--ds-ink-soft); border:1px solid var(--ds-line); }
.pill--ok{ background:color-mix(in srgb, var(--ds-success) 14%, transparent);
  color:var(--ds-success); border-color:color-mix(in srgb, var(--ds-success) 30%, transparent); }
.projcard__cta{ align-self:flex-start; }

/* ---- Breadcrumb topbar (R2) ---- */
.crumb{ display:flex; align-items:center; gap:.5rem; font-size:var(--ds-text-sm); }
.crumb__client{ color:var(--ds-ink-soft); }
.crumb__sep{ color:var(--ds-line-2); }
.crumb__cur{ font-weight:600; color:var(--ds-ink); }

/* ---- Canvas nodal éditable (Phase 5) : nœud cliquable = éditer l'étape ---- */
.pnode--edit{ cursor:pointer; text-decoration:none; color:inherit; display:block;
  transition:border-color .12s var(--ds-ease-out), box-shadow .12s var(--ds-ease-out); }
.pnode--edit:hover{ border-color:var(--ds-primary);
  box-shadow:0 0 0 1px color-mix(in srgb, var(--ds-primary) 28%, transparent); }
.pnode--edit:focus-visible{ outline:2px solid var(--ds-ring); outline-offset:2px; }

/* ---- Contrôles rapides de cadence (Phase 5) ---- */
.quickadj{ display:flex; align-items:center; gap:.5rem; flex-wrap:wrap; margin:0 0 1.25rem; }

/* ---- Checklist de mise en route (cockpit projet) ---- */
.checklist{ display:flex; flex-direction:column; gap:.4rem; }
.checkitem{ display:flex; align-items:center; gap:.6rem; padding:.45rem .1rem; border-bottom:1px solid var(--ds-line); }
.checkitem:last-child{ border-bottom:none; }
.checkitem__mark{ width:20px; height:20px; border-radius:50%; display:grid; place-items:center;
  border:1.5px solid var(--ds-line); color:var(--ds-on-primary); flex:none; }
.checkitem.is-done .checkitem__mark{ background:var(--ds-success); border-color:var(--ds-success); }
.checkitem__label{ font-size:var(--ds-text-sm); }
.checkitem.is-done .checkitem__label{ color:var(--ds-ink-soft); text-decoration:line-through; }

/* ---- Métriques par projet (comparaison sur « Mes projets ») ---- */
.projcard__metrics{ margin-top:2px; }

/* ---- Barre de tri « Mes projets » (comparaison) ---- */
.sortbar{ display:flex; align-items:center; gap:.4rem; margin:0 0 1.25rem; flex-wrap:wrap; }
.sortbtn{ font-size:var(--ds-text-xs); padding:3px 10px; border-radius:999px; text-decoration:none;
  color:var(--ds-ink-soft); border:1px solid var(--ds-line); background:var(--ds-paper); }
.sortbtn:hover{ border-color:var(--ds-line-2); }
.sortbtn.is-active{ background:var(--ds-primary); color:var(--ds-on-primary); border-color:var(--ds-primary); }

/* ---- Accessibilité : lien d'évitement (clavier) ---- */
.skip-link{ position:fixed; left:8px; top:-48px; z-index:200; padding:.55rem 1rem;
  background:var(--ds-primary); color:var(--ds-on-primary); border-radius:8px; text-decoration:none;
  font-size:var(--ds-text-sm); transition:top .12s var(--ds-ease-out); }
.skip-link:focus{ top:8px; outline:2px solid var(--ds-ring); outline-offset:2px; }
main:focus{ outline:none; }  /* cible du lien d'évitement : pas de contour disgracieux */

/* ---- Onboarding conversationnel (dashbot / landing) ---- */
.onb-grid{display:grid;grid-template-columns:1fr 320px;gap:1rem;align-items:start}
@media (max-width:820px){.onb-grid{grid-template-columns:1fr}}
.onb-chat{display:flex;flex-direction:column;min-height:380px;overflow:hidden;padding:0}
.onb-msgs{flex:1;overflow-y:auto;max-height:54vh;padding:1rem;display:flex;flex-direction:column;gap:.5rem}
.onb-msg{max-width:86%;padding:.55rem .8rem;border-radius:14px;line-height:1.45;font-size:var(--ds-text-sm)}
.onb-ia{align-self:flex-start;background:var(--ds-surface-2);border:1px solid var(--ds-line)}
.onb-moi{align-self:flex-end;background:var(--ds-primary);color:var(--ds-on-primary)}
.onb-sys{align-self:center;color:var(--ds-ink-soft);font-size:var(--ds-text-xs);text-align:center}
.onb-typing i{display:inline-block;width:6px;height:6px;margin:0 1px;border-radius:50%;background:currentColor;opacity:.5;animation:onbBlink 1s infinite}
.onb-typing i:nth-child(2){animation-delay:.2s}
.onb-typing i:nth-child(3){animation-delay:.4s}
@keyframes onbBlink{0%,60%,100%{opacity:.3}30%{opacity:1}}
.onb-composer{display:flex;gap:.5rem;padding:.75rem;border-top:1px solid var(--ds-line)}
.onb-composer .input{flex:1}
.onb-chips{display:flex;flex-wrap:wrap;gap:.4rem;align-self:flex-start;margin:.25rem 0}
.onb-chip{padding:.4rem .7rem;border:1px solid var(--ds-line);border-radius:999px;background:transparent;color:inherit;cursor:pointer;font-size:var(--ds-text-sm)}
.onb-chip:hover{border-color:var(--ds-primary)}
.onb-chip--apply{border-color:var(--ds-primary);background:var(--ds-primary);color:var(--ds-on-primary)}
.onb-packs{display:grid;grid-template-columns:repeat(3,1fr);gap:.6rem;width:100%;margin:.25rem 0}
.onb-pack{text-align:center}
.onb-pack-n{font-size:var(--ds-text-xl);font-weight:650;line-height:1.1}
.onb-pack-sub{font-size:var(--ds-text-2xs);color:var(--ds-ink-soft)}
.onb-pack-cta{margin-top:.4rem}
.onb-dna{align-self:start}
.onb-dna:not(.on){display:none}
.onb-dna-title{font-size:var(--ds-text-sm);font-weight:650;margin-bottom:.5rem}
.onb-dna-row{display:flex;flex-direction:column;gap:.1rem;padding:.35rem 0;border-top:1px solid var(--ds-line)}
.onb-dna-k{font-size:var(--ds-text-2xs);color:var(--ds-ink-soft)}

/* UGC — bibliothèque & galerie (layout uniquement ; typographie via classes fs-*) */
.ugc-filters { display: flex; flex-wrap: wrap; gap: var(--ds-r3); }
.ugc-filter { border: 1px solid var(--ds-line); border-radius: var(--ds-radius-sm); padding: var(--ds-r2); }
.ugc-filter__opts { display: flex; flex-wrap: wrap; gap: var(--ds-r1); margin-top: var(--ds-r1); }
.ugc-chip { display: inline-flex; align-items: center; gap: var(--ds-r1); padding: 2px 8px; border: 1px solid var(--ds-line); border-radius: 999px; cursor: pointer; }
.ugc-chip input { accent-color: var(--ds-primary); }
.ugc-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: var(--ds-r3); }
.ugc-card { display: flex; flex-direction: column; border: 1px solid var(--ds-line); border-radius: var(--ds-radius); overflow: hidden; background: var(--ds-surface); }
.ugc-card--kept { border-color: var(--ds-primary); }
.ugc-card__thumb { display: flex; align-items: center; justify-content: center; aspect-ratio: 9 / 16; background: var(--ds-surface-2); color: var(--ds-primary); }
.ugc-card__body { padding: var(--ds-r2); display: flex; flex-direction: column; gap: 2px; }
.ugc-tags { display: flex; flex-wrap: wrap; gap: 2px; margin-top: var(--ds-r1); }
.ugc-tag { padding: 1px 6px; border-radius: 4px; background: var(--ds-surface-2); color: var(--ds-ink-soft); }

/* UGC — vignette, preview au survol, sélection */
.ugc-card { position: relative; }
.ugc-card__img { width: 100%; height: 100%; object-fit: cover; display: block; }
.ugc-card__video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; background: var(--ds-ink); }
.ugc-card__pick { position: absolute; top: 6px; left: 6px; z-index: 2; background: rgba(255,255,255,.85); border-radius: 4px; padding: 1px 3px; }
.ugc-card--has-video .ugc-card__thumb { cursor: pointer; }
.ugc-selbar { position: sticky; bottom: 0; display: flex; flex-wrap: wrap; align-items: center; gap: var(--ds-r2); padding: var(--ds-r3); margin-top: var(--ds-r3); background: var(--ds-surface); border: 1px solid var(--ds-line); border-radius: var(--ds-radius); }

/* Projet — renommage inline */
.projcard__rename{margin-top:.5rem}
.projcard__rename summary{cursor:pointer;list-style:none}
.projcard__rename summary::-webkit-details-marker{display:none}
.projrename{display:flex;gap:.4rem;margin-top:.5rem}
.projrename__input{flex:1;min-width:0;background:var(--ds-surface);border:1px solid var(--ds-line);border-radius:var(--ds-r2,6px);padding:.35rem .5rem;color:inherit;font:inherit}

/* Projet — archivage / restauration */
.projarchive{color:var(--ds-ink-soft,#888);border-color:transparent!important;background:transparent!important}
.projarchive:hover{color:var(--ds-danger,#e5484d)}
.archived-wrap summary{cursor:pointer}
.archived-list{display:flex;flex-direction:column;gap:.5rem;margin-top:.75rem}
.archived-row{display:flex;align-items:center;gap:.6rem;padding:.6rem .75rem;background:var(--ds-surface);border:1px solid var(--ds-line);border-radius:var(--ds-r2,6px)}
